radeonsi: update all resident texture descriptors when needed
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 19 Jun 2017 15:40:19 +0000 (17:40 +0200)
committerSamuel Pitoiset <samuel.pitoiset@gmail.com>
Tue, 20 Jun 2017 08:14:55 +0000 (10:14 +0200)
To avoid useless DCC fetches when DCC is disabled, descriptors
have to be updated in order to reflect this change. This is
quite similar to how we update descriptors of bound textures.

As a side effect, this should also prevent VM faults when
bindless textures are invalidated, because the VA in the
descriptor has to be updated accordingly as well.

I don't see any performance improvements with DOW3.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/drivers/radeonsi/si_descriptors.c

index e792cf6..1e92a70 100644 (file)
@@ -1913,6 +1913,108 @@ static void si_invalidate_buffer(struct pipe_context *ctx, struct pipe_resource
        si_rebind_buffer(ctx, buf, old_va);
 }
 
+static void si_upload_bindless_descriptor(struct si_context *sctx,
+                                         struct si_bindless_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_ME));
+       radeon_emit(cs, va);
+       radeon_emit(cs, va >> 32);
+       radeon_emit_array(cs, desc->desc_list, num_dwords);
+}
+
+static void si_upload_bindless_descriptors(struct si_context *sctx)
+{
+       if (!sctx->bindless_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 |
+                        SI_CONTEXT_CS_PARTIAL_FLUSH;
+       si_emit_cache_flush(sctx);
+
+       util_dynarray_foreach(&sctx->resident_tex_handles,
+                             struct si_texture_handle *, tex_handle) {
+               struct si_bindless_descriptor *desc = (*tex_handle)->desc;
+
+               if (!desc->dirty)
+                       continue;
+
+               si_upload_bindless_descriptor(sctx, desc);
+               desc->dirty = false;
+       }
+
+       util_dynarray_foreach(&sctx->resident_img_handles,
+                             struct si_image_handle *, img_handle) {
+               struct si_bindless_descriptor *desc = (*img_handle)->desc;
+
+               if (!desc->dirty)
+                       continue;
+
+               si_upload_bindless_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->bindless_descriptors_dirty = false;
+}
+
+/* Update mutable image descriptor fields of all resident textures. */
+static void si_update_all_resident_texture_descriptors(struct si_context *sctx)
+{
+       util_dynarray_foreach(&sctx->resident_tex_handles,
+                             struct si_texture_handle *, tex_handle) {
+               struct si_bindless_descriptor *desc = (*tex_handle)->desc;
+               struct si_sampler_view *sview =
+                       (struct si_sampler_view *)(*tex_handle)->view;
+               uint32_t desc_list[16];
+
+               if (sview->base.texture->target == PIPE_BUFFER)
+                       continue;
+
+               memcpy(desc_list, desc->desc_list, sizeof(desc_list));
+               si_set_sampler_view_desc(sctx, sview, &(*tex_handle)->sstate,
+                                        &desc->desc_list[0]);
+
+               if (memcmp(desc_list, desc->desc_list, sizeof(desc_list))) {
+                       desc->dirty = true;
+                       sctx->bindless_descriptors_dirty = true;
+               }
+       }
+
+       util_dynarray_foreach(&sctx->resident_img_handles,
+                             struct si_image_handle *, img_handle) {
+               struct si_bindless_descriptor *desc = (*img_handle)->desc;
+               struct pipe_image_view *view = &(*img_handle)->view;
+               uint32_t desc_list[16];
+
+               if (view->resource->target == PIPE_BUFFER)
+                       continue;
+
+               memcpy(desc_list, desc->desc_list, sizeof(desc_list));
+               si_set_shader_image_desc(sctx, view, true,
+                                        &desc->desc_list[0]);
+
+               if (memcmp(desc_list, desc->desc_list, sizeof(desc_list))) {
+                       desc->dirty = true;
+                       sctx->bindless_descriptors_dirty = true;
+               }
+       }
+
+       si_upload_bindless_descriptors(sctx);
+}
+
 /* Update mutable image descriptor fields of all bound textures. */
 void si_update_all_texture_descriptors(struct si_context *sctx)
 {
@@ -1953,6 +2055,8 @@ void si_update_all_texture_descriptors(struct si_context *sctx)
 
                si_update_shader_needs_decompress_mask(sctx, shader);
        }
+
+       si_update_all_resident_texture_descriptors(sctx);
 }
 
 /* SHADER USER DATA */
@@ -2772,63 +2876,6 @@ 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_bindless_descriptor(struct si_context *sctx,
-                                         struct si_bindless_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_ME));
-       radeon_emit(cs, va);
-       radeon_emit(cs, va >> 32);
-       radeon_emit_array(cs, desc->desc_list, num_dwords);
-}
-
-static void si_upload_bindless_descriptors(struct si_context *sctx)
-{
-       if (!sctx->bindless_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 |
-                        SI_CONTEXT_CS_PARTIAL_FLUSH;
-       si_emit_cache_flush(sctx);
-
-       util_dynarray_foreach(&sctx->resident_tex_handles,
-                             struct si_texture_handle *, tex_handle) {
-               struct si_bindless_descriptor *desc = (*tex_handle)->desc;
-
-               if (!desc->dirty)
-                       continue;
-
-               si_upload_bindless_descriptor(sctx, desc);
-               desc->dirty = false;
-       }
-
-       util_dynarray_foreach(&sctx->resident_img_handles,
-                             struct si_image_handle *, img_handle) {
-               struct si_bindless_descriptor *desc = (*img_handle)->desc;
-
-               if (!desc->dirty)
-                       continue;
-
-               si_upload_bindless_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->bindless_descriptors_dirty = false;
-}
-
 bool si_upload_graphics_shader_descriptors(struct si_context *sctx)
 {
        const unsigned mask = u_bit_consecutive(0, SI_DESCS_FIRST_COMPUTE);