radeonsi: bind a dummy constant buffer in place of NULL buffers
authorMarek Olšák <marek.olsak@amd.com>
Wed, 30 Oct 2013 19:44:23 +0000 (20:44 +0100)
committerMarek Olšák <marek.olsak@amd.com>
Mon, 4 Nov 2013 18:07:57 +0000 (19:07 +0100)
src/gallium/drivers/radeonsi/radeonsi_pipe.c
src/gallium/drivers/radeonsi/radeonsi_pipe.h
src/gallium/drivers/radeonsi/si_descriptors.c

index f4d323310d8864e3984eb1efd06092265f945d65..0431ab0b4df014e654661900078bb29c89fa82f5 100644 (file)
@@ -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);
index 1d4a91bf8adbfcb803304f5819a82a91cb8315b2..de613e0ed34360e04af84d9c123f65405519ea60 100644 (file)
@@ -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;
index 93d3684b68419d18d573e5720a49d4deb7473588..c4915846d94af42d318ebed72cb92677d283b4dc 100644 (file)
@@ -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;