v3dv: only write new uniforms when needed
authorIago Toral Quiroga <itoral@igalia.com>
Thu, 19 Nov 2020 08:45:16 +0000 (09:45 +0100)
committerIago Toral Quiroga <itoral@igalia.com>
Fri, 20 Nov 2020 07:00:00 +0000 (08:00 +0100)
Writing uniform streams is performance sensitive so we should try our
best to avoid writing new uniforms if they have not changed. Particularly,
if only the vertex buffers have changed, we should not write new uniforms.

This improves performance in vkQuake2 by about 11.15%.

Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7683>

src/broadcom/vulkan/v3dv_cmd_buffer.c
src/broadcom/vulkan/v3dv_private.h

index 9c06dbf..e6343a0 100644 (file)
@@ -3506,24 +3506,30 @@ emit_configuration_bits(struct v3dv_cmd_buffer *cmd_buffer)
 }
 
 static void
-emit_gl_shader_state(struct v3dv_cmd_buffer *cmd_buffer)
+update_uniform_state(struct v3dv_cmd_buffer *cmd_buffer)
 {
-   struct v3dv_job *job = cmd_buffer->state.job;
-   assert(job);
-
-   struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
-   struct v3dv_pipeline *pipeline = state->pipeline;
+   struct v3dv_pipeline *pipeline = cmd_buffer->state.pipeline;
    assert(pipeline);
 
-   /* Upload the uniforms to the indirect CL first */
-   struct v3dv_cl_reloc fs_uniforms =
+   cmd_buffer->state.uniforms.fs =
       v3dv_write_uniforms(cmd_buffer, pipeline->fs);
 
-   struct v3dv_cl_reloc vs_uniforms =
+   cmd_buffer->state.uniforms.vs =
       v3dv_write_uniforms(cmd_buffer, pipeline->vs);
 
-   struct v3dv_cl_reloc vs_bin_uniforms =
+   cmd_buffer->state.uniforms.vs_bin =
       v3dv_write_uniforms(cmd_buffer, pipeline->vs_bin);
+}
+
+static void
+emit_gl_shader_state(struct v3dv_cmd_buffer *cmd_buffer)
+{
+   struct v3dv_job *job = cmd_buffer->state.job;
+   assert(job);
+
+   struct v3dv_cmd_buffer_state *state = &cmd_buffer->state;
+   struct v3dv_pipeline *pipeline = state->pipeline;
+   assert(pipeline);
 
    /* Update the cache dirty flag based on the shader progs data */
    job->tmu_dirty_rcl |= pipeline->vs_bin->current_variant->prog_data.vs->base.tmu_dirty_rcl;
@@ -3561,9 +3567,9 @@ emit_gl_shader_state(struct v3dv_cmd_buffer *cmd_buffer)
       shader.fragment_shader_code_address =
          v3dv_cl_address(pipeline->fs->current_variant->assembly_bo, 0);
 
-      shader.coordinate_shader_uniforms_address = vs_bin_uniforms;
-      shader.vertex_shader_uniforms_address = vs_uniforms;
-      shader.fragment_shader_uniforms_address = fs_uniforms;
+      shader.coordinate_shader_uniforms_address = cmd_buffer->state.uniforms.vs_bin;
+      shader.vertex_shader_uniforms_address = cmd_buffer->state.uniforms.vs;
+      shader.fragment_shader_uniforms_address = cmd_buffer->state.uniforms.fs;
 
       shader.address_of_default_attribute_values =
          v3dv_cl_address(pipeline->default_attribute_values, 0);
@@ -4058,13 +4064,16 @@ cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer)
     * that will require that we new uniform state for QUNIFORM_VIEWPORT_*.
     */
    uint32_t *dirty = &cmd_buffer->state.dirty;
-   if (*dirty & (V3DV_CMD_DIRTY_PIPELINE |
-                 V3DV_CMD_DIRTY_VERTEX_BUFFER |
-                 V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
-                 V3DV_CMD_DIRTY_PUSH_CONSTANTS |
-                 V3DV_CMD_DIRTY_VIEWPORT)) {
+
+   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);
+
+   if (dirty_uniforms || (*dirty & V3DV_CMD_DIRTY_VERTEX_BUFFER))
       emit_gl_shader_state(cmd_buffer);
-   }
 
    if (*dirty & (V3DV_CMD_DIRTY_PIPELINE)) {
       emit_configuration_bits(cmd_buffer);
index 6f7730b..be63f68 100644 (file)
@@ -1013,6 +1013,13 @@ struct v3dv_cmd_buffer_state {
       uint8_t index_size;
    } index_buffer;
 
+   /* Current uniforms */
+   struct {
+      struct v3dv_cl_reloc vs_bin;
+      struct v3dv_cl_reloc vs;
+      struct v3dv_cl_reloc fs;
+   } uniforms;
+
    /* Used to flag OOM conditions during command buffer recording */
    bool oom;