[Mesa-dev] [PATCH 4/9] freedreno: core SSBO support
Rob Clark
robdclark at gmail.com
Tue Apr 18 22:15:56 UTC 2017
The generation-independent support for binding shader buffer objects.
Signed-off-by: Rob Clark <robdclark at gmail.com>
---
src/gallium/drivers/freedreno/freedreno_context.h | 8 ++++
src/gallium/drivers/freedreno/freedreno_draw.c | 6 +++
src/gallium/drivers/freedreno/freedreno_resource.c | 9 ++++
src/gallium/drivers/freedreno/freedreno_screen.h | 1 +
src/gallium/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 733c64b..d5d071d 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 {
@@ -253,6 +260,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 16c9ea8..99bc840 100644
--- a/src/gallium/drivers/freedreno/freedreno_draw.c
+++ b/src/gallium/drivers/freedreno/freedreno_draw.c
@@ -145,6 +145,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 3b06709..60aed3f 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 f2b1d8c..dac7224 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 3b02e63..9955627 100644
--- a/src/gallium/drivers/freedreno/freedreno_state.c
+++ b/src/gallium/drivers/freedreno/freedreno_state.c
@@ -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;
--
2.9.3
More information about the mesa-dev
mailing list