summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2013-10-30 20:44:23 +0100
committerMarek Olšák <[email protected]>2013-11-04 19:07:57 +0100
commit4569bf919930a417d9d94f0d626d88ed164b32a9 (patch)
tree06adb8bf4361c86152964abc5f6918fc6f457cf1 /src
parent2fd42001231b70ba1764b1455d642037d2d5fff5 (diff)
radeonsi: bind a dummy constant buffer in place of NULL buffers
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/radeonsi/radeonsi_pipe.c22
-rw-r--r--src/gallium/drivers/radeonsi/radeonsi_pipe.h1
-rw-r--r--src/gallium/drivers/radeonsi/si_descriptors.c6
3 files changed, 29 insertions, 0 deletions
diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c
index f4d323310d8..0431ab0b4df 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 1d4a91bf8ad..de613e0ed34 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 93d3684b684..c4915846d94 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;