[Mesa-dev] [PATCH 3/2] radeonsi: bind a dummy constant buffer in place of NULL buffers

Marek Olšák maraeo at gmail.com
Wed Oct 30 20:48:03 CET 2013


From: Marek Olšák <marek.olsak at amd.com>

---

The UBO series continues here.
This is an alternative solution to scalar-memory-read hw bug.

 src/gallium/drivers/radeonsi/radeonsi_pipe.c  | 22 ++++++++++++++++++++++
 src/gallium/drivers/radeonsi/radeonsi_pipe.h  |  1 +
 src/gallium/drivers/radeonsi/si_descriptors.c |  6 ++++++
 3 files changed, 29 insertions(+)

diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
index f4d3233..0431ab0 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
@@ -101,6 +101,7 @@ static void r600_destroy_context(struct pipe_context *context)
 
 	si_release_all_descriptors(rctx);
 
+	pipe_resource_reference(&rctx->null_const_buf.buffer, NULL);
 	r600_resource_reference(&rctx->border_color_table, NULL);
 
 	if (rctx->dummy_pixel_shader) {
@@ -131,6 +132,7 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 {
 	struct r600_context *rctx = CALLOC_STRUCT(r600_context);
 	struct r600_screen* rscreen = (struct r600_screen *)screen;
+	int shader, i;
 
 	if (rctx == NULL)
 		return NULL;
@@ -208,6 +210,26 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
 	/* these must be last */
 	si_begin_new_cs(rctx);
 	si_get_backend_mask(rctx);
+
+	/* CIK cannot unbind a constant buffer (S_BUFFER_LOAD is buggy
+	 * with a NULL buffer). We need to use a dummy buffer instead. */
+	if (rctx->b.chip_class == CIK) {
+		rctx->null_const_buf.buffer = pipe_buffer_create(screen, PIPE_BIND_CONSTANT_BUFFER,
+								 PIPE_USAGE_STATIC, 16);
+		rctx->null_const_buf.buffer_size = rctx->null_const_buf.buffer->width0;
+
+		for (shader = 0; shader < SI_NUM_SHADERS; shader++) {
+			for (i = 0; i < NUM_CONST_BUFFERS; i++) {
+				rctx->b.b.set_constant_buffer(&rctx->b.b, shader, i,
+							      &rctx->null_const_buf);
+			}
+		}
+
+		/* Clear the NULL constant buffer, because loads should return zeros. */
+		rctx->b.clear_buffer(&rctx->b.b, rctx->null_const_buf.buffer, 0,
+				     rctx->null_const_buf.buffer->width0, 0);
+	}
+
 	return &rctx->b.b;
 fail:
 	r600_destroy_context(&rctx->b.b);
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.h b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
index 1d4a91b..de613e0 100644
--- a/src/gallium/drivers/radeonsi/radeonsi_pipe.h
+++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.h
@@ -171,6 +171,7 @@ struct r600_context {
 	 * In that case, we bind this one: */
 	struct si_pipe_shader	*dummy_pixel_shader;
 	struct r600_atom	cache_flush;
+	struct pipe_constant_buffer null_const_buf; /* used for set_constant_buffer(NULL) on CIK */
 
 	/* SI state handling */
 	union si_state	queued;
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c b/src/gallium/drivers/radeonsi/si_descriptors.c
index 93d3684..c491584 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -412,6 +412,12 @@ static void si_set_constant_buffer(struct pipe_context *ctx, uint shader, uint s
 	assert(slot < buffers->num_buffers);
 	pipe_resource_reference(&buffers->buffers[slot], NULL);
 
+	/* CIK cannot unbind a constant buffer (S_BUFFER_LOAD is buggy
+	 * with a NULL buffer). We need to use a dummy buffer instead. */
+	if (rctx->b.chip_class == CIK &&
+	    (!input || (!input->buffer && !input->user_buffer)))
+		input = &rctx->null_const_buf;
+
 	if (input && (input->buffer || input->user_buffer)) {
 		struct pipe_resource *buffer = NULL;
 		uint64_t va;
-- 
1.8.1.2



More information about the mesa-dev mailing list