Mesa (main): zink: selectively disable dynamic vertex stride

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 19 03:54:42 UTC 2022


Module: Mesa
Branch: main
Commit: 1eada1b02d3b16b88a07b9924a52617e08371907
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=1eada1b02d3b16b88a07b9924a52617e08371907

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Mon Apr 18 16:00:35 2022 -0400

zink: selectively disable dynamic vertex stride

if the vertex state doesn't meet the requirements to use this feature,
fall back to fully-baked pipelines instead of violating spec

Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16018>

---

 src/gallium/drivers/zink/zink_context.c  |  2 ++
 src/gallium/drivers/zink/zink_draw.cpp   |  8 +++++--
 src/gallium/drivers/zink/zink_pipeline.c |  4 ++--
 src/gallium/drivers/zink/zink_pipeline.h |  1 +
 src/gallium/drivers/zink/zink_program.c  | 36 +++++++++++++++++++++++++++++---
 5 files changed, 44 insertions(+), 7 deletions(-)

diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c
index 77db0b28f6d..5aa6331e33b 100644
--- a/src/gallium/drivers/zink/zink_context.c
+++ b/src/gallium/drivers/zink/zink_context.c
@@ -4205,6 +4205,8 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
 
    ctx->pipeline_changed[0] = ctx->pipeline_changed[1] = true;
    ctx->gfx_pipeline_state.dirty = true;
+   ctx->gfx_pipeline_state.uses_dynamic_stride = screen->info.have_EXT_extended_dynamic_state ||
+                                                 screen->info.have_EXT_vertex_input_dynamic_state;
    ctx->compute_pipeline_state.dirty = true;
    ctx->fb_changed = ctx->rp_changed = true;
    ctx->gfx_pipeline_state.gfx_prim_mode = PIPE_PRIM_MAX;
diff --git a/src/gallium/drivers/zink/zink_draw.cpp b/src/gallium/drivers/zink/zink_draw.cpp
index c1c0625ccaf..b091c6cab1b 100644
--- a/src/gallium/drivers/zink/zink_draw.cpp
+++ b/src/gallium/drivers/zink/zink_draw.cpp
@@ -749,8 +749,12 @@ zink_draw(struct pipe_context *pctx,
 
    if (DRAW_STATE)
       zink_bind_vertex_state(batch, ctx, vstate, partial_velem_mask);
-   else if (BATCH_CHANGED || ctx->vertex_buffers_dirty)
-      zink_bind_vertex_buffers<DYNAMIC_STATE>(batch, ctx);
+   else if (BATCH_CHANGED || ctx->vertex_buffers_dirty) {
+      if (DYNAMIC_STATE == ZINK_DYNAMIC_VERTEX_INPUT || ctx->gfx_pipeline_state.uses_dynamic_stride)
+         zink_bind_vertex_buffers<DYNAMIC_STATE>(batch, ctx);
+      else
+         zink_bind_vertex_buffers<ZINK_NO_DYNAMIC_STATE>(batch, ctx);
+   }
 
    if (BATCH_CHANGED) {
       ctx->pipeline_changed[0] = false;
diff --git a/src/gallium/drivers/zink/zink_pipeline.c b/src/gallium/drivers/zink/zink_pipeline.c
index 768f20b95f7..1823dbba296 100644
--- a/src/gallium/drivers/zink/zink_pipeline.c
+++ b/src/gallium/drivers/zink/zink_pipeline.c
@@ -61,7 +61,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
       vertex_input_state.vertexBindingDescriptionCount = state->element_state->num_bindings;
       vertex_input_state.pVertexAttributeDescriptions = state->element_state->attribs;
       vertex_input_state.vertexAttributeDescriptionCount = state->element_state->num_attribs;
-      if (!screen->info.have_EXT_extended_dynamic_state) {
+      if (!screen->info.have_EXT_extended_dynamic_state || !state->uses_dynamic_stride) {
          for (int i = 0; i < state->element_state->num_bindings; ++i) {
             const unsigned buffer_id = binding_map[i];
             VkVertexInputBindingDescription *binding = &state->element_state->b.bindings[i];
@@ -232,7 +232,7 @@ zink_create_gfx_pipeline(struct zink_screen *screen,
    if (state->element_state->num_attribs) {
       if (screen->info.have_EXT_vertex_input_dynamic_state)
          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_EXT;
-      else if (screen->info.have_EXT_extended_dynamic_state)
+      else if (screen->info.have_EXT_extended_dynamic_state && state->uses_dynamic_stride)
          dynamicStateEnables[state_count++] = VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;
    }
    if (screen->info.have_EXT_extended_dynamic_state2) {
diff --git a/src/gallium/drivers/zink/zink_pipeline.h b/src/gallium/drivers/zink/zink_pipeline.h
index ea220f1bc27..72807d943a4 100644
--- a/src/gallium/drivers/zink/zink_pipeline.h
+++ b/src/gallium/drivers/zink/zink_pipeline.h
@@ -76,6 +76,7 @@ struct zink_gfx_pipeline_state {
    uint32_t vertex_buffers_enabled_mask;
    uint32_t vertex_strides[PIPE_MAX_ATTRIBS];
    bool sample_locations_enabled;
+   bool uses_dynamic_stride;
    bool have_EXT_extended_dynamic_state;
    bool have_EXT_extended_dynamic_state2;
    uint8_t has_points; //either gs outputs points or prim type is points
diff --git a/src/gallium/drivers/zink/zink_program.c b/src/gallium/drivers/zink/zink_program.c
index 85ed5e3e0cc..b0b41692caa 100644
--- a/src/gallium/drivers/zink/zink_program.c
+++ b/src/gallium/drivers/zink/zink_program.c
@@ -240,7 +240,9 @@ equals_gfx_pipeline_state(const void *a, const void *b)
 {
    const struct zink_gfx_pipeline_state *sa = a;
    const struct zink_gfx_pipeline_state *sb = b;
-   if (!sa->have_EXT_extended_dynamic_state) {
+   if (sa->uses_dynamic_stride != sb->uses_dynamic_stride)
+      return false;
+   if (!sa->have_EXT_extended_dynamic_state || !sa->uses_dynamic_stride) {
       if (sa->vertex_buffers_enabled_mask != sb->vertex_buffers_enabled_mask)
          return false;
       /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */
@@ -252,6 +254,8 @@ equals_gfx_pipeline_state(const void *a, const void *b)
          if (sa->vertex_strides[idx_a] != sb->vertex_strides[idx_b])
             return false;
       }
+   }
+   if (!sa->have_EXT_extended_dynamic_state) {
       if (sa->dyn_state1.front_face != sb->dyn_state1.front_face)
          return false;
       if (!!sa->dyn_state1.depth_stencil_alpha_state != !!sb->dyn_state1.depth_stencil_alpha_state ||
@@ -765,7 +769,29 @@ get_pipeline_idx(bool have_EXT_extended_dynamic_state, enum pipe_prim_type mode,
    }
    return vkmode;
 }
-                 
+
+/*
+   VUID-vkCmdBindVertexBuffers2-pStrides-06209
+   If pStrides is not NULL each element of pStrides must be either 0 or greater than or equal
+   to the maximum extent of all vertex input attributes fetched from the corresponding
+   binding, where the extent is calculated as the VkVertexInputAttributeDescription::offset
+   plus VkVertexInputAttributeDescription::format size
+
+   * thus, if the stride doesn't meet the minimum requirement for a binding,
+   * disable the dynamic state here and use a fully-baked pipeline
+ */
+static bool
+check_vertex_strides(struct zink_context *ctx)
+{
+   const struct zink_vertex_elements_state *ves = ctx->element_state;
+   for (unsigned i = 0; i < ves->hw_state.num_bindings; i++) {
+      const struct pipe_vertex_buffer *vb = ctx->vertex_buffers + ves->binding_map[i];
+      unsigned stride = vb->buffer.resource ? vb->stride : 0;
+      if (stride < ves->min_stride[i])
+         return false;
+   }
+   return true;
+}
 
 VkPipeline
 zink_get_gfx_pipeline(struct zink_context *ctx,
@@ -776,6 +802,7 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
    struct zink_screen *screen = zink_screen(ctx->base.screen);
    const bool have_EXT_vertex_input_dynamic_state = screen->info.have_EXT_vertex_input_dynamic_state;
    const bool have_EXT_extended_dynamic_state = screen->info.have_EXT_extended_dynamic_state;
+   bool uses_dynamic_stride = state->uses_dynamic_stride;
 
    VkPrimitiveTopology vkmode = zink_primitive_topology(mode);
    const unsigned idx = get_pipeline_idx(screen->info.have_EXT_extended_dynamic_state, mode, vkmode);
@@ -797,7 +824,9 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
    if (!have_EXT_vertex_input_dynamic_state && ctx->vertex_state_changed) {
       if (state->pipeline)
          state->final_hash ^= state->vertex_hash;
-      if (!have_EXT_extended_dynamic_state) {
+      if (have_EXT_extended_dynamic_state)
+         uses_dynamic_stride = check_vertex_strides(ctx);
+      if (!uses_dynamic_stride) {
          uint32_t hash = 0;
          /* if we don't have dynamic states, we have to hash the enabled vertex buffer bindings */
          uint32_t vertex_buffers_enabled_mask = state->vertex_buffers_enabled_mask;
@@ -815,6 +844,7 @@ zink_get_gfx_pipeline(struct zink_context *ctx,
       state->final_hash ^= state->vertex_hash;
    }
    state->modules_changed = false;
+   state->uses_dynamic_stride = uses_dynamic_stride;
    ctx->vertex_state_changed = false;
 
    entry = _mesa_hash_table_search_pre_hashed(&prog->pipelines[idx], state->final_hash, state);



More information about the mesa-commit mailing list