When texture buffers are invalidated the addr in the resident
descriptor has to be updated but we can't create a new descriptor
because the resident handle has to be the same.

Instead, use the WRITE_DATA packet which allows to update memory
directly but graphics/compute have to be idle in case the GPU is
reading the descriptor.

Signed-off-by: Samuel Pitoiset <samuel.pitoi...@gmail.com>
---
 src/gallium/drivers/radeon/r600_pipe_common.h |   4 +
 src/gallium/drivers/radeonsi/si_descriptors.c | 121 ++++++++++++++++++++++++++
 src/gallium/drivers/radeonsi/si_pipe.h        |   3 +
 3 files changed, 128 insertions(+)

diff --git a/src/gallium/drivers/radeon/r600_pipe_common.h 
b/src/gallium/drivers/radeon/r600_pipe_common.h
index b17b690fab..6c4df2e733 100644
--- a/src/gallium/drivers/radeon/r600_pipe_common.h
+++ b/src/gallium/drivers/radeon/r600_pipe_common.h
@@ -181,6 +181,10 @@ struct r600_resource {
 
        /* Whether the resource has been exported via resource_get_handle. */
        unsigned                        external_usage; /* PIPE_HANDLE_USAGE_* 
*/
+
+       /* Whether this resource is referenced by bindless handles. */
+       bool                            texture_handle_allocated;
+       bool                            image_handle_allocated;
 };
 
 struct r600_transfer {
diff --git a/src/gallium/drivers/radeonsi/si_descriptors.c 
b/src/gallium/drivers/radeonsi/si_descriptors.c
index 05559d90d7..6adad06757 100644
--- a/src/gallium/drivers/radeonsi/si_descriptors.c
+++ b/src/gallium/drivers/radeonsi/si_descriptors.c
@@ -1849,6 +1849,55 @@ static void si_rebind_buffer(struct pipe_context *ctx, 
struct pipe_resource *buf
                        }
                }
        }
+
+       /* Bindless texture handles */
+       if (rbuffer->texture_handle_allocated) {
+               for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+                       struct si_texture_handle *tex_handle =
+                               sctx->resident_tex_handles[i];
+                       struct si_sampler_view *sview = tex_handle->view;
+                       struct si_resident_descriptor *desc = tex_handle->desc;
+
+                       if (sview->base.texture == buf) {
+                               si_set_buf_desc_address(rbuffer,
+                                                       
sview->base.u.buf.offset,
+                                                       &desc->desc_list[4]);
+                               desc->dirty = true;
+                               sctx->resident_descriptors_dirty = true;
+
+                               radeon_add_to_buffer_list_check_mem(
+                                       &sctx->b, &sctx->b.gfx, rbuffer,
+                                       RADEON_USAGE_READ,
+                                       RADEON_PRIO_SAMPLER_BUFFER, true);
+                       }
+               }
+       }
+
+       /* Bindless image handles */
+       if (rbuffer->image_handle_allocated) {
+               for (i = 0; i < sctx->num_resident_img_handles; i++) {
+                       struct si_image_handle *img_handle =
+                               sctx->resident_img_handles[i];
+                       struct pipe_image_view *view = &img_handle->view;
+                       struct si_resident_descriptor *desc = img_handle->desc;
+
+                       if (view->resource == buf) {
+                               if (view->access & PIPE_IMAGE_ACCESS_WRITE)
+                                       si_mark_image_range_valid(view);
+
+                               si_set_buf_desc_address(rbuffer,
+                                                       view->u.buf.offset,
+                                                       &desc->desc_list[4]);
+                               desc->dirty = true;
+                               sctx->resident_descriptors_dirty = true;
+
+                               radeon_add_to_buffer_list_check_mem(
+                                       &sctx->b, &sctx->b.gfx, rbuffer,
+                                       RADEON_USAGE_READWRITE,
+                                       RADEON_PRIO_SAMPLER_BUFFER, true);
+                       }
+               }
+       }
 }
 
 /* Reallocate a buffer a update all resource bindings where the buffer is
@@ -2365,6 +2414,8 @@ si_create_resident_descriptor(struct si_context *sctx, 
uint32_t *desc_list,
        util_memcpy_cpu_to_le32(ptr + desc->offset, desc_list, size);
        sscreen->b.ws->buffer_unmap(desc->buffer->buf);
 
+       memcpy(desc->desc_list, desc_list, sizeof(desc->desc_list));
+
        return desc;
 }
 
@@ -2415,6 +2466,8 @@ static uint64_t si_create_texture_handle(struct 
pipe_context *ctx,
                return 0;
        }
 
+       r600_resource(sview->base.texture)->texture_handle_allocated = true;
+
        return handle;
 }
 
@@ -2521,6 +2574,8 @@ static uint64_t si_create_image_handle(struct 
pipe_context *ctx,
                return 0;
        }
 
+       r600_resource(view->resource)->image_handle_allocated = true;
+
        return handle;
 }
 
@@ -2800,6 +2855,67 @@ void si_init_all_descriptors(struct si_context *sctx)
        si_set_user_data_base(sctx, PIPE_SHADER_FRAGMENT, 
R_00B030_SPI_SHADER_USER_DATA_PS_0);
 }
 
+static void si_upload_resident_descriptor(struct si_context *sctx,
+                                         struct si_resident_descriptor *desc)
+{
+       struct radeon_winsys_cs *cs = sctx->b.gfx.cs;
+       uint64_t va = desc->buffer->gpu_address + desc->offset;
+       unsigned num_dwords = sizeof(desc->desc_list) / 4;
+
+       radeon_emit(cs, PKT3(PKT3_WRITE_DATA, 2 + num_dwords, 0));
+       radeon_emit(cs, S_370_DST_SEL(V_370_TC_L2) |
+                   S_370_WR_CONFIRM(1) |
+                   S_370_ENGINE_SEL(V_370_PFP));
+       radeon_emit(cs, va);
+       radeon_emit(cs, va >> 32);
+       radeon_emit_array(cs, desc->desc_list, num_dwords);
+}
+
+static void si_upload_resident_descriptors(struct si_context *sctx)
+{
+       unsigned i;
+
+       if (!sctx->resident_descriptors_dirty)
+               return;
+
+       /* Wait for graphics/compute to be idle before updating the resident
+        * descriptors directly in memory, in case the GPU is using them.
+        */
+       sctx->b.flags |= SI_CONTEXT_PS_PARTIAL_FLUSH;
+       sctx->b.flags |= SI_CONTEXT_CS_PARTIAL_FLUSH;
+       si_emit_cache_flush(sctx);
+
+       for (i = 0; i < sctx->num_resident_tex_handles; i++) {
+               struct si_texture_handle *tex_handle =
+                       sctx->resident_tex_handles[i];
+               struct si_resident_descriptor *desc = tex_handle->desc;
+
+               if (!desc->dirty)
+                       continue;
+
+               si_upload_resident_descriptor(sctx, desc);
+               desc->dirty = false;
+       }
+
+       for (i = 0; i < sctx->num_resident_img_handles; i++) {
+               struct si_image_handle *img_handle =
+                       sctx->resident_img_handles[i];
+               struct si_resident_descriptor *desc = img_handle->desc;
+
+               if (!desc->dirty)
+                       continue;
+
+               si_upload_resident_descriptor(sctx, desc);
+               desc->dirty = false;
+       }
+
+       /* Invalidate L1 because it doesn't know that L2 changed. */
+       sctx->b.flags |= SI_CONTEXT_INV_SMEM_L1;
+       si_emit_cache_flush(sctx);
+
+       sctx->resident_descriptors_dirty = false;
+}
+
 bool si_upload_graphics_shader_descriptors(struct si_context *sctx)
 {
        const unsigned mask = u_bit_consecutive(0, SI_DESCS_FIRST_COMPUTE);
@@ -2817,6 +2933,9 @@ bool si_upload_graphics_shader_descriptors(struct 
si_context *sctx)
        }
 
        sctx->descriptors_dirty &= ~mask;
+
+       si_upload_resident_descriptors(sctx);
+
        return true;
 }
 
@@ -2841,6 +2960,8 @@ bool si_upload_compute_shader_descriptors(struct 
si_context *sctx)
 
        sctx->descriptors_dirty &= ~mask;
 
+       si_upload_resident_descriptors(sctx);
+
        return true;
 }
 
diff --git a/src/gallium/drivers/radeonsi/si_pipe.h 
b/src/gallium/drivers/radeonsi/si_pipe.h
index c52b364959..f15881c51f 100644
--- a/src/gallium/drivers/radeonsi/si_pipe.h
+++ b/src/gallium/drivers/radeonsi/si_pipe.h
@@ -229,6 +229,8 @@ struct si_resident_descriptor
        struct pb_slab_entry            entry;
        struct r600_resource            *buffer;
        unsigned                        offset;
+       uint32_t                        desc_list[16];
+       bool                            dirty;
 };
 
 struct si_texture_handle
@@ -415,6 +417,7 @@ struct si_context {
        struct r600_resource    **resident_descriptors;
        unsigned                num_resident_descriptors;
        unsigned                max_resident_descriptors;
+       bool                    resident_descriptors_dirty;
 
        /* Allocatd bindless handles */
        struct hash_table       *tex_handles;
-- 
2.13.0

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to