Mesa (main): radv: implement VK_EXT_vertex_input_dynamic_state

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Oct 13 05:33:39 UTC 2021


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

Author: Rhys Perry <pendingchaos02 at gmail.com>
Date:   Wed May 12 15:46:53 2021 +0100

radv: implement VK_EXT_vertex_input_dynamic_state

Signed-off-by: Rhys Perry <pendingchaos02 at gmail.com>
Acked-By: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Reviewed-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11717>

---

 src/amd/vulkan/radv_cmd_buffer.c |  62 ++++++++++++-
 src/amd/vulkan/radv_device.c     |  12 +++
 src/amd/vulkan/radv_pipeline.c   | 184 +++++++++++++++++++++------------------
 3 files changed, 172 insertions(+), 86 deletions(-)

diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c
index 959ba95e039..59ffa716943 100644
--- a/src/amd/vulkan/radv_cmd_buffer.c
+++ b/src/amd/vulkan/radv_cmd_buffer.c
@@ -4414,7 +4414,9 @@ radv_CmdBindVertexBuffers2EXT(VkCommandBuffer commandBuffer, uint32_t firstBindi
       vb[idx].buffer = buffer;
       vb[idx].offset = pOffsets[i];
       vb[idx].size = size;
-      vb[idx].stride = stride;
+      /* if pStrides=NULL, it shouldn't overwrite the strides specified by CmdSetVertexInputEXT */
+      if (pStrides)
+         vb[idx].stride = stride;
 
       if (buffer) {
          radv_cs_add_buffer(cmd_buffer->device->ws, cmd_buffer->cs, vb[idx].buffer->bo);
@@ -5371,6 +5373,64 @@ radv_CmdSetColorWriteEnableEXT(VkCommandBuffer commandBuffer, uint32_t attachmen
    state->dirty |= RADV_CMD_DIRTY_DYNAMIC_COLOR_WRITE_ENABLE;
 }
 
+void
+radv_CmdSetVertexInputEXT(VkCommandBuffer commandBuffer, uint32_t vertexBindingDescriptionCount,
+                          const VkVertexInputBindingDescription2EXT *pVertexBindingDescriptions,
+                          uint32_t vertexAttributeDescriptionCount,
+                          const VkVertexInputAttributeDescription2EXT *pVertexAttributeDescriptions)
+{
+   RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
+   struct radv_vs_input_state *state = &cmd_buffer->state.dynamic_vs_input;
+
+   const VkVertexInputBindingDescription2EXT *bindings[MAX_VBS];
+   for (unsigned i = 0; i < vertexBindingDescriptionCount; i++)
+      bindings[pVertexBindingDescriptions[i].binding] = &pVertexBindingDescriptions[i];
+
+   state->attribute_mask = 0;
+   state->instance_rate_inputs = 0;
+   state->nontrivial_divisors = 0;
+   state->post_shuffle = 0;
+   state->alpha_adjust_lo = 0;
+   state->alpha_adjust_hi = 0;
+
+   for (unsigned i = 0; i < vertexAttributeDescriptionCount; i++) {
+      const VkVertexInputAttributeDescription2EXT *attrib = &pVertexAttributeDescriptions[i];
+      const VkVertexInputBindingDescription2EXT *binding = bindings[attrib->binding];
+      unsigned loc = attrib->location;
+      const struct util_format_description *format_desc = vk_format_description(attrib->format);
+      unsigned nfmt, dfmt;
+      bool post_shuffle;
+      enum radv_vs_input_alpha_adjust alpha_adjust;
+
+      state->attribute_mask |= 1u << loc;
+      state->bindings[loc] = attrib->binding;
+      if (binding->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE) {
+         state->instance_rate_inputs |= 1u << loc;
+         state->divisors[loc] = binding->divisor;
+         if (binding->divisor != 1)
+            state->nontrivial_divisors |= 1u << loc;
+      }
+      cmd_buffer->vertex_bindings[attrib->binding].stride = binding->stride;
+      state->offsets[loc] = attrib->offset;
+
+      radv_translate_vertex_format(cmd_buffer->device->physical_device, attrib->format, format_desc,
+                                   &dfmt, &nfmt, &post_shuffle, &alpha_adjust);
+
+      state->formats[loc] = dfmt | (nfmt << 4);
+      state->format_align_req_minus_1[loc] =
+         format_desc->channel[0].size >= 32 ? 3 : (format_desc->block.bits / 8u - 1);
+      state->format_sizes[loc] = format_desc->block.bits / 8u;
+
+      state->alpha_adjust_lo |= (alpha_adjust & 0x1) << loc;
+      state->alpha_adjust_hi |= (alpha_adjust >> 1) << loc;
+
+      if (post_shuffle)
+         state->post_shuffle |= 1u << loc;
+   }
+
+   cmd_buffer->state.dirty |= RADV_CMD_DIRTY_VERTEX_STATE;
+}
+
 void
 radv_CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount,
                         const VkCommandBuffer *pCmdBuffers)
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index 3246ffeefe3..02cfe28ad1a 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -1627,6 +1627,12 @@ radv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
          features->maintenance4 = true;
          break;
       }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
+         VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features =
+            (VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *)ext;
+         features->vertexInputDynamicState = true;
+         break;
+      }
       default:
          break;
       }
@@ -2940,6 +2946,12 @@ radv_CreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCr
             image_float32_atomics = true;
          break;
       }
+      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: {
+         const VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features = (const void *)ext;
+         if (features->vertexInputDynamicState)
+            vs_prologs = true;
+         break;
+      }
       default:
          break;
       }
diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c
index d18943b0ecb..e7cbeb7e892 100644
--- a/src/amd/vulkan/radv_pipeline.c
+++ b/src/amd/vulkan/radv_pipeline.c
@@ -1298,6 +1298,8 @@ radv_dynamic_state_mask(VkDynamicState state)
       return RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE;
    case VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT:
       return RADV_DYNAMIC_COLOR_WRITE_ENABLE;
+   case VK_DYNAMIC_STATE_VERTEX_INPUT_EXT:
+      return RADV_DYNAMIC_VERTEX_INPUT;
    default:
       unreachable("Unhandled dynamic state");
    }
@@ -1334,7 +1336,8 @@ radv_pipeline_needed_dynamic_state(const VkGraphicsPipelineCreateInfo *pCreateIn
    if (pCreateInfo->pRasterizationState->rasterizerDiscardEnable &&
        !radv_is_state_dynamic(pCreateInfo, VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE_EXT)) {
       return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY | RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE |
-             RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE | RADV_DYNAMIC_RASTERIZER_DISCARD_ENABLE;
+             RADV_DYNAMIC_PRIMITIVE_RESTART_ENABLE | RADV_DYNAMIC_RASTERIZER_DISCARD_ENABLE |
+             RADV_DYNAMIC_VERTEX_INPUT;
    }
 
    if (!pCreateInfo->pRasterizationState->depthBiasEnable &&
@@ -1681,7 +1684,8 @@ radv_pipeline_init_dynamic_state(struct radv_pipeline *pipeline,
       dynamic->line_stipple.pattern = rast_line_info->lineStipplePattern;
    }
 
-   if (!(states & RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE))
+   if (!(states & RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE) ||
+       !(states & RADV_DYNAMIC_VERTEX_INPUT))
       pipeline->graphics.uses_dynamic_stride = true;
 
    const VkPipelineFragmentShadingRateStateCreateInfoKHR *shading_rate = vk_find_struct_const(
@@ -2545,9 +2549,6 @@ radv_generate_graphics_pipeline_key(const struct radv_pipeline *pipeline,
 {
    RADV_FROM_HANDLE(radv_render_pass, pass, pCreateInfo->renderPass);
    struct radv_subpass *subpass = pass->subpasses + pCreateInfo->subpass;
-   const VkPipelineVertexInputStateCreateInfo *input_state = pCreateInfo->pVertexInputState;
-   const VkPipelineVertexInputDivisorStateCreateInfoEXT *divisor_state =
-      vk_find_struct_const(input_state->pNext, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
    bool uses_dynamic_stride = false;
 
    struct radv_pipeline_key key;
@@ -2558,88 +2559,98 @@ radv_generate_graphics_pipeline_key(const struct radv_pipeline *pipeline,
 
    key.has_multiview_view_index = !!subpass->view_mask;
 
-   uint32_t binding_input_rate = 0;
-   uint32_t instance_rate_divisors[MAX_VERTEX_ATTRIBS];
-   for (unsigned i = 0; i < input_state->vertexBindingDescriptionCount; ++i) {
-      if (input_state->pVertexBindingDescriptions[i].inputRate) {
-         unsigned binding = input_state->pVertexBindingDescriptions[i].binding;
-         binding_input_rate |= 1u << binding;
-         instance_rate_divisors[binding] = 1;
-      }
-   }
-   if (divisor_state) {
-      for (unsigned i = 0; i < divisor_state->vertexBindingDivisorCount; ++i) {
-         instance_rate_divisors[divisor_state->pVertexBindingDivisors[i].binding] =
-            divisor_state->pVertexBindingDivisors[i].divisor;
-      }
-   }
-
    if (pCreateInfo->pDynamicState) {
       uint32_t count = pCreateInfo->pDynamicState->dynamicStateCount;
       for (uint32_t i = 0; i < count; i++) {
-         if (pCreateInfo->pDynamicState->pDynamicStates[i] ==
-             VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT) {
-            uses_dynamic_stride = true;
+         if (pCreateInfo->pDynamicState->pDynamicStates[i] == VK_DYNAMIC_STATE_VERTEX_INPUT_EXT) {
+            key.vs.dynamic_input_state = true;
+            /* we don't care about use_dynamic_stride in this case */
             break;
+         } else if (pCreateInfo->pDynamicState->pDynamicStates[i] ==
+                    VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT) {
+            uses_dynamic_stride = true;
          }
       }
    }
 
-   for (unsigned i = 0; i < input_state->vertexAttributeDescriptionCount; ++i) {
-      const VkVertexInputAttributeDescription *desc = &input_state->pVertexAttributeDescriptions[i];
-      const struct util_format_description *format_desc;
-      unsigned location = desc->location;
-      unsigned binding = desc->binding;
-      unsigned num_format, data_format;
-      bool post_shuffle;
+   if (!key.vs.dynamic_input_state) {
+      const VkPipelineVertexInputStateCreateInfo *input_state = pCreateInfo->pVertexInputState;
+      const VkPipelineVertexInputDivisorStateCreateInfoEXT *divisor_state = vk_find_struct_const(
+         input_state->pNext, PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
 
-      if (binding_input_rate & (1u << binding)) {
-         key.vs.instance_rate_inputs |= 1u << location;
-         key.vs.instance_rate_divisors[location] = instance_rate_divisors[binding];
+      uint32_t binding_input_rate = 0;
+      uint32_t instance_rate_divisors[MAX_VERTEX_ATTRIBS];
+      for (unsigned i = 0; i < input_state->vertexBindingDescriptionCount; ++i) {
+         if (input_state->pVertexBindingDescriptions[i].inputRate) {
+            unsigned binding = input_state->pVertexBindingDescriptions[i].binding;
+            binding_input_rate |= 1u << binding;
+            instance_rate_divisors[binding] = 1;
+         }
+      }
+      if (divisor_state) {
+         for (unsigned i = 0; i < divisor_state->vertexBindingDivisorCount; ++i) {
+            instance_rate_divisors[divisor_state->pVertexBindingDivisors[i].binding] =
+               divisor_state->pVertexBindingDivisors[i].divisor;
+         }
       }
 
-      format_desc = vk_format_description(desc->format);
-      radv_translate_vertex_format(pipeline->device->physical_device, desc->format, format_desc,
-                                   &data_format, &num_format, &post_shuffle,
-                                   &key.vs.vertex_alpha_adjust[location]);
+      for (unsigned i = 0; i < input_state->vertexAttributeDescriptionCount; ++i) {
+         const VkVertexInputAttributeDescription *desc =
+            &input_state->pVertexAttributeDescriptions[i];
+         const struct util_format_description *format_desc;
+         unsigned location = desc->location;
+         unsigned binding = desc->binding;
+         unsigned num_format, data_format;
+         bool post_shuffle;
+
+         if (binding_input_rate & (1u << binding)) {
+            key.vs.instance_rate_inputs |= 1u << location;
+            key.vs.instance_rate_divisors[location] = instance_rate_divisors[binding];
+         }
 
-      key.vs.vertex_attribute_formats[location] = data_format | (num_format << 4);
-      key.vs.vertex_attribute_bindings[location] = desc->binding;
-      key.vs.vertex_attribute_offsets[location] = desc->offset;
+         format_desc = vk_format_description(desc->format);
+         radv_translate_vertex_format(pipeline->device->physical_device, desc->format, format_desc,
+                                      &data_format, &num_format, &post_shuffle,
+                                      &key.vs.vertex_alpha_adjust[location]);
 
-      const struct ac_data_format_info *dfmt_info = ac_get_data_format_info(data_format);
-      unsigned attrib_align =
-         dfmt_info->chan_byte_size ? dfmt_info->chan_byte_size : dfmt_info->element_size;
+         key.vs.vertex_attribute_formats[location] = data_format | (num_format << 4);
+         key.vs.vertex_attribute_bindings[location] = desc->binding;
+         key.vs.vertex_attribute_offsets[location] = desc->offset;
 
-      /* If desc->offset is misaligned, then the buffer offset must be too. Just
-       * skip updating vertex_binding_align in this case.
-       */
-      if (desc->offset % attrib_align == 0)
-         key.vs.vertex_binding_align[desc->binding] =
-            MAX2(key.vs.vertex_binding_align[desc->binding], attrib_align);
+         const struct ac_data_format_info *dfmt_info = ac_get_data_format_info(data_format);
+         unsigned attrib_align =
+            dfmt_info->chan_byte_size ? dfmt_info->chan_byte_size : dfmt_info->element_size;
 
-      if (!uses_dynamic_stride) {
-         /* From the Vulkan spec 1.2.157:
-          *
-          * "If the bound pipeline state object was created
-          *  with the
-          *  VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT
-          *  dynamic state enabled then pStrides[i] specifies
-          *  the distance in bytes between two consecutive
-          *  elements within the corresponding buffer. In this
-          *  case the VkVertexInputBindingDescription::stride
-          *  state from the pipeline state object is ignored."
-          *
-          * Make sure the vertex attribute stride is zero to
-          * avoid computing a wrong offset if it's initialized
-          * to something else than zero.
+         /* If desc->offset is misaligned, then the buffer offset must be too. Just
+          * skip updating vertex_binding_align in this case.
           */
-         key.vs.vertex_attribute_strides[location] =
-            radv_get_attrib_stride(input_state, desc->binding);
-      }
+         if (desc->offset % attrib_align == 0)
+            key.vs.vertex_binding_align[desc->binding] =
+               MAX2(key.vs.vertex_binding_align[desc->binding], attrib_align);
+
+         if (!uses_dynamic_stride) {
+            /* From the Vulkan spec 1.2.157:
+             *
+             * "If the bound pipeline state object was created
+             *  with the
+             *  VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT
+             *  dynamic state enabled then pStrides[i] specifies
+             *  the distance in bytes between two consecutive
+             *  elements within the corresponding buffer. In this
+             *  case the VkVertexInputBindingDescription::stride
+             *  state from the pipeline state object is ignored."
+             *
+             * Make sure the vertex attribute stride is zero to
+             * avoid computing a wrong offset if it's initialized
+             * to something else than zero.
+             */
+            key.vs.vertex_attribute_strides[location] =
+               radv_get_attrib_stride(input_state, desc->binding);
+         }
 
-      if (post_shuffle)
-         key.vs.vertex_post_shuffle |= 1 << location;
+         if (post_shuffle)
+            key.vs.vertex_post_shuffle |= 1 << location;
+      }
    }
 
    const VkPipelineTessellationStateCreateInfo *tess =
@@ -5363,26 +5374,29 @@ radv_pipeline_generate_pm4(struct radv_pipeline *pipeline,
 
 static void
 radv_pipeline_init_vertex_input_state(struct radv_pipeline *pipeline,
-                                      const VkGraphicsPipelineCreateInfo *pCreateInfo)
+                                      const VkGraphicsPipelineCreateInfo *pCreateInfo,
+                                      const struct radv_pipeline_key *key)
 {
    const struct radv_shader_info *info = &radv_get_shader(pipeline, MESA_SHADER_VERTEX)->info;
-   const VkPipelineVertexInputStateCreateInfo *vi_info = pCreateInfo->pVertexInputState;
+   if (!key->vs.dynamic_input_state) {
+      const VkPipelineVertexInputStateCreateInfo *vi_info = pCreateInfo->pVertexInputState;
 
-   for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
-      const VkVertexInputBindingDescription *desc = &vi_info->pVertexBindingDescriptions[i];
+      for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
+         const VkVertexInputBindingDescription *desc = &vi_info->pVertexBindingDescriptions[i];
 
-      pipeline->binding_stride[desc->binding] = desc->stride;
-   }
+         pipeline->binding_stride[desc->binding] = desc->stride;
+      }
 
-   for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
-      const VkVertexInputAttributeDescription *desc = &vi_info->pVertexAttributeDescriptions[i];
+      for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
+         const VkVertexInputAttributeDescription *desc = &vi_info->pVertexAttributeDescriptions[i];
 
-      uint32_t end = desc->offset + vk_format_get_blocksize(desc->format);
-      pipeline->attrib_ends[desc->location] = end;
-      if (pipeline->binding_stride[desc->binding])
-         pipeline->attrib_index_offset[desc->location] =
-            desc->offset / pipeline->binding_stride[desc->binding];
-      pipeline->attrib_bindings[desc->location] = desc->binding;
+         uint32_t end = desc->offset + vk_format_get_blocksize(desc->format);
+         pipeline->attrib_ends[desc->location] = end;
+         if (pipeline->binding_stride[desc->binding])
+            pipeline->attrib_index_offset[desc->location] =
+               desc->offset / pipeline->binding_stride[desc->binding];
+         pipeline->attrib_bindings[desc->location] = desc->binding;
+      }
    }
 
    pipeline->use_per_attribute_vb_descs = info->vs.use_per_attribute_vb_descs;
@@ -5541,7 +5555,7 @@ radv_pipeline_init(struct radv_pipeline *pipeline, struct radv_device *device,
          pCreateInfo->pTessellationState->patchControlPoints;
    }
 
-   radv_pipeline_init_vertex_input_state(pipeline, pCreateInfo);
+   radv_pipeline_init_vertex_input_state(pipeline, pCreateInfo, &key);
    radv_pipeline_init_binning_state(pipeline, pCreateInfo, &blend);
    radv_pipeline_init_shader_stages_state(pipeline);
    radv_pipeline_init_scratch(device, pipeline);



More information about the mesa-commit mailing list