From 4d841fbaae3eac04f33f6a52f3dd829cfb1913b5 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 17 Apr 2017 10:56:20 -0400 Subject: [PATCH] freedreno: core SSBO support The generation-independent support for binding shader buffer objects. Signed-off-by: Rob Clark --- .../drivers/freedreno/freedreno_context.h | 8 +++ .../drivers/freedreno/freedreno_draw.c | 6 +++ .../drivers/freedreno/freedreno_resource.c | 9 ++++ .../drivers/freedreno/freedreno_screen.h | 1 + .../drivers/freedreno/freedreno_state.c | 49 +++++++++++++++++++ 5 files changed, 73 insertions(+) diff --git a/src/gallium/drivers/freedreno/freedreno_context.h b/src/gallium/drivers/freedreno/freedreno_context.h index b50e66c90a9..7e940bca496 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.h +++ b/src/gallium/drivers/freedreno/freedreno_context.h @@ -72,6 +72,12 @@ struct fd_constbuf_stateobj { uint32_t dirty_mask; }; +struct fd_shaderbuf_stateobj { + struct pipe_shader_buffer sb[PIPE_MAX_SHADER_BUFFERS]; + uint32_t enabled_mask; + uint32_t dirty_mask; +}; + struct fd_vertexbuf_stateobj { struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; unsigned count; @@ -142,6 +148,7 @@ enum fd_dirty_shader_state { FD_DIRTY_SHADER_PROG = BIT(0), FD_DIRTY_SHADER_CONST = BIT(1), FD_DIRTY_SHADER_TEX = BIT(2), + FD_DIRTY_SHADER_SSBO = BIT(3), }; struct fd_context { @@ -264,6 +271,7 @@ struct fd_context { struct pipe_poly_stipple stipple; struct pipe_viewport_state viewport; struct fd_constbuf_stateobj constbuf[PIPE_SHADER_TYPES]; + struct fd_shaderbuf_stateobj shaderbuf[PIPE_SHADER_TYPES]; struct pipe_index_buffer indexbuf; struct fd_streamout_stateobj streamout; struct pipe_clip_state ucp; diff --git a/src/gallium/drivers/freedreno/freedreno_draw.c b/src/gallium/drivers/freedreno/freedreno_draw.c index d5b9a7b23a5..6691f65db97 100644 --- a/src/gallium/drivers/freedreno/freedreno_draw.c +++ b/src/gallium/drivers/freedreno/freedreno_draw.c @@ -151,6 +151,12 @@ fd_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info) batch->gmem_reason |= FD_GMEM_BLEND_ENABLED; } + /* Mark SSBOs as being written.. we don't actually know which ones are + * read vs written, so just assume the worst + */ + foreach_bit(i, ctx->shaderbuf[PIPE_SHADER_FRAGMENT].enabled_mask) + resource_read(batch, ctx->shaderbuf[PIPE_SHADER_FRAGMENT].sb[i].buffer); + foreach_bit(i, ctx->constbuf[PIPE_SHADER_VERTEX].enabled_mask) resource_read(batch, ctx->constbuf[PIPE_SHADER_VERTEX].cb[i].buffer); foreach_bit(i, ctx->constbuf[PIPE_SHADER_FRAGMENT].enabled_mask) diff --git a/src/gallium/drivers/freedreno/freedreno_resource.c b/src/gallium/drivers/freedreno/freedreno_resource.c index e47ac326314..b5afe861e0f 100644 --- a/src/gallium/drivers/freedreno/freedreno_resource.c +++ b/src/gallium/drivers/freedreno/freedreno_resource.c @@ -86,6 +86,15 @@ fd_invalidate_resource(struct fd_context *ctx, struct pipe_resource *prsc) if (ctx->tex[stage].textures[i] && (ctx->tex[stage].textures[i]->texture == prsc)) ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_TEX; } + + /* SSBOs */ + const unsigned num_ssbos = util_last_bit(ctx->shaderbuf[stage].enabled_mask); + for (unsigned i = 0; i < num_ssbos; i++) { + if (ctx->dirty_shader[stage] & FD_DIRTY_SHADER_SSBO) + break; + if (ctx->shaderbuf[stage].sb[i].buffer == prsc) + ctx->dirty_shader[stage] |= FD_DIRTY_SHADER_SSBO; + } } } diff --git a/src/gallium/drivers/freedreno/freedreno_screen.h b/src/gallium/drivers/freedreno/freedreno_screen.h index f2b1d8cea76..dac7224f3af 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.h +++ b/src/gallium/drivers/freedreno/freedreno_screen.h @@ -38,6 +38,7 @@ #include "os/os_thread.h" #include "freedreno_batch_cache.h" +#include "freedreno_util.h" struct fd_bo; diff --git a/src/gallium/drivers/freedreno/freedreno_state.c b/src/gallium/drivers/freedreno/freedreno_state.c index 8f466339799..bc9fe4ab73e 100644 --- a/src/gallium/drivers/freedreno/freedreno_state.c +++ b/src/gallium/drivers/freedreno/freedreno_state.c @@ -113,6 +113,54 @@ fd_set_constant_buffer(struct pipe_context *pctx, ctx->dirty |= FD_DIRTY_CONST; } +static void +fd_set_shader_buffers(struct pipe_context *pctx, + enum pipe_shader_type shader, + unsigned start, unsigned count, + const struct pipe_shader_buffer *buffers) +{ + struct fd_context *ctx = fd_context(pctx); + struct fd_shaderbuf_stateobj *so = &ctx->shaderbuf[shader]; + unsigned mask = 0; + + if (buffers) { + for (unsigned i = 0; i < count; i++) { + unsigned n = i + start; + struct pipe_shader_buffer *buf = &so->sb[n]; + + if ((buf->buffer == buffers[i].buffer) && + (buf->buffer_offset == buffers[i].buffer_offset) && + (buf->buffer_size == buffers[i].buffer_size)) + continue; + + mask |= BIT(n); + + buf->buffer_offset = buffers[i].buffer_offset; + buf->buffer_size = buffers[i].buffer_size; + pipe_resource_reference(&buf->buffer, buffers[i].buffer); + + if (buf->buffer) + so->enabled_mask |= BIT(n); + else + so->enabled_mask &= ~BIT(n); + } + } else { + mask = (BIT(count) - 1) << start; + + for (unsigned i = 0; i < count; i++) { + unsigned n = i + start; + struct pipe_shader_buffer *buf = &so->sb[n]; + + pipe_resource_reference(&buf->buffer, NULL); + } + + so->enabled_mask &= ~mask; + } + + so->dirty_mask |= mask; + ctx->dirty_shader[shader] |= FD_DIRTY_SHADER_SSBO; +} + static void fd_set_framebuffer_state(struct pipe_context *pctx, const struct pipe_framebuffer_state *framebuffer) @@ -411,6 +459,7 @@ fd_state_init(struct pipe_context *pctx) pctx->set_clip_state = fd_set_clip_state; pctx->set_sample_mask = fd_set_sample_mask; pctx->set_constant_buffer = fd_set_constant_buffer; + pctx->set_shader_buffers = fd_set_shader_buffers; pctx->set_framebuffer_state = fd_set_framebuffer_state; pctx->set_polygon_stipple = fd_set_polygon_stipple; pctx->set_scissor_states = fd_set_scissor_states; -- 2.30.2