Mesa (master): v3dv: only update uniforms for dirty descriptors if stage has descriptors

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jan 19 08:16:13 UTC 2021


Module: Mesa
Branch: master
Commit: a46547671b09f40e774e89a8f11ef947f75ce152
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=a46547671b09f40e774e89a8f11ef947f75ce152

Author: Iago Toral Quiroga <itoral at igalia.com>
Date:   Tue Jan  5 09:02:13 2021 +0100

v3dv: only update uniforms for dirty descriptors if stage has descriptors

If we have dirty descriptor set state we have to update our uniform
data to reference the new resources such as addresses for textures
or UBOs. This is known to have a high CPU cost, so we want to limit
this as much as we can.

It is a common rendering pattern in applications to render many objects
using the same pipeline, but modifying the descriptor sets bound to update
textures, UBOs, etc. In this scenario, we would be incurring in unnecessary
uniform stream updates for stages that don't access descriptor sets at all.

This change makes it so we track which shader stages in a pipeline
use descriptor set state and skips updating uniform streams for them
when dirty descriptor set state is the only reason requiring us to
generate new uniform streams for a draw call.

v2: reuse shader stage information from the pipeline set layouts
    to track shader stages that use descriptor state.

Reviewed-by: Alejandro Piñeiro <apinheiro at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8555>

---

 src/broadcom/vulkan/v3dv_cmd_buffer.c     | 54 +++++++++++++++++++++++--------
 src/broadcom/vulkan/v3dv_descriptor_set.c |  6 ++--
 src/broadcom/vulkan/v3dv_private.h        |  5 ++-
 3 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index e1edb75266e..b2ce7547445 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -3507,19 +3507,43 @@ emit_configuration_bits(struct v3dv_cmd_buffer *cmd_buffer)
 }
 
 static void
-update_uniform_state(struct v3dv_cmd_buffer *cmd_buffer)
+update_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
+                     uint32_t dirty_uniform_state)
 {
+   /* We need to update uniform streams if any piece of state that is passed
+    * to the shader as a uniform may have changed.
+    *
+    * If only descriptor sets are dirty then we can safely ignore updates
+    * for shader stages that don't access descriptors.
+    */
+
    struct v3dv_pipeline *pipeline = cmd_buffer->state.pipeline;
    assert(pipeline);
 
-   cmd_buffer->state.uniforms.fs =
-      v3dv_write_uniforms(cmd_buffer, pipeline->fs);
+   const bool dirty_descriptors_only =
+      (cmd_buffer->state.dirty & dirty_uniform_state) ==
+      V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
 
-   cmd_buffer->state.uniforms.vs =
-      v3dv_write_uniforms(cmd_buffer, pipeline->vs);
+   const bool needs_fs_update =
+      !dirty_descriptors_only ||
+      (pipeline->layout->shader_stages & VK_SHADER_STAGE_FRAGMENT_BIT);
+
+   if (needs_fs_update) {
+      cmd_buffer->state.uniforms.fs =
+         v3dv_write_uniforms(cmd_buffer, pipeline->fs);
+   }
 
-   cmd_buffer->state.uniforms.vs_bin =
-      v3dv_write_uniforms(cmd_buffer, pipeline->vs_bin);
+   const bool needs_vs_update =
+      !dirty_descriptors_only ||
+      (pipeline->layout->shader_stages & VK_SHADER_STAGE_VERTEX_BIT);
+
+   if (needs_vs_update) {
+      cmd_buffer->state.uniforms.vs =
+         v3dv_write_uniforms(cmd_buffer, pipeline->vs);
+
+      cmd_buffer->state.uniforms.vs_bin =
+         v3dv_write_uniforms(cmd_buffer, pipeline->vs_bin);
+   }
 }
 
 static void
@@ -4066,14 +4090,16 @@ cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer)
     */
    uint32_t *dirty = &cmd_buffer->state.dirty;
 
-   const bool dirty_uniforms = *dirty & (V3DV_CMD_DIRTY_PIPELINE |
-                                         V3DV_CMD_DIRTY_PUSH_CONSTANTS |
-                                         V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
-                                         V3DV_CMD_DIRTY_VIEWPORT);
-   if (dirty_uniforms)
-      update_uniform_state(cmd_buffer);
+   const uint32_t dirty_uniform_state =
+      *dirty & (V3DV_CMD_DIRTY_PIPELINE |
+                V3DV_CMD_DIRTY_PUSH_CONSTANTS |
+                V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
+                V3DV_CMD_DIRTY_VIEWPORT);
+
+   if (dirty_uniform_state)
+      update_uniform_state(cmd_buffer, dirty_uniform_state);
 
-   if (dirty_uniforms || (*dirty & V3DV_CMD_DIRTY_VERTEX_BUFFER))
+   if (dirty_uniform_state || (*dirty & V3DV_CMD_DIRTY_VERTEX_BUFFER))
       emit_gl_shader_state(cmd_buffer);
 
    if (*dirty & (V3DV_CMD_DIRTY_PIPELINE)) {
diff --git a/src/broadcom/vulkan/v3dv_descriptor_set.c b/src/broadcom/vulkan/v3dv_descriptor_set.c
index 1cf09f35248..8b6b4453799 100644
--- a/src/broadcom/vulkan/v3dv_descriptor_set.c
+++ b/src/broadcom/vulkan/v3dv_descriptor_set.c
@@ -359,6 +359,8 @@ v3dv_CreatePipelineLayout(VkDevice _device,
          dynamic_offset_count += set_layout->binding[b].array_size *
             set_layout->binding[b].dynamic_offset_count;
       }
+
+      layout->shader_stages |= set_layout->shader_stages;
    }
 
    layout->push_constant_size = 0;
@@ -707,10 +709,6 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device,
       dynamic_offset_count += binding->descriptorCount *
          set_layout->binding[binding_number].dynamic_offset_count;
 
-      /* FIXME: right now we don't use shader_stages. We could explore if we
-       * could use it to add another filter to upload or allocate the
-       * descriptor data.
-       */
       set_layout->shader_stages |= binding->stageFlags;
 
       set_layout->binding[binding_number].descriptor_offset = set_layout->bo_size;
diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h
index 0f0b15c9cc2..e6f7afb9c5e 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -1548,8 +1548,11 @@ struct v3dv_pipeline_layout {
    } set[MAX_SETS];
 
    uint32_t num_sets;
-   uint32_t dynamic_offset_count;
 
+   /* Shader stages that are declared to use descriptors from this layout */
+   uint32_t shader_stages;
+
+   uint32_t dynamic_offset_count;
    uint32_t push_constant_size;
 };
 



More information about the mesa-commit mailing list