freedreno: core SSBO support
authorRob Clark <robdclark@gmail.com>
Mon, 17 Apr 2017 14:56:20 +0000 (10:56 -0400)
committerRob Clark <robdclark@gmail.com>
Thu, 4 May 2017 17:48:06 +0000 (13:48 -0400)
The generation-independent support for binding shader buffer objects.

Signed-off-by: Rob Clark <robdclark@gmail.com>
src/gallium/drivers/freedreno/freedreno_context.h
src/gallium/drivers/freedreno/freedreno_draw.c
src/gallium/drivers/freedreno/freedreno_resource.c
src/gallium/drivers/freedreno/freedreno_screen.h
src/gallium/drivers/freedreno/freedreno_state.c

index b50e66c..7e940bc 100644 (file)
@@ -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;
index d5b9a7b..6691f65 100644 (file)
@@ -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)
index e47ac32..b5afe86 100644 (file)
@@ -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;
+               }
        }
 }
 
index f2b1d8c..dac7224 100644 (file)
@@ -38,6 +38,7 @@
 #include "os/os_thread.h"
 
 #include "freedreno_batch_cache.h"
+#include "freedreno_util.h"
 
 struct fd_bo;
 
index 8f46633..bc9fe4a 100644 (file)
@@ -114,6 +114,54 @@ fd_set_constant_buffer(struct pipe_context *pctx,
 }
 
 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;