[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