radv: add support for dynamic vertex input binding stride
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 13 Apr 2020 12:35:44 +0000 (14:35 +0200)
committerMarge Bot <eric+marge@anholt.net>
Mon, 13 Jul 2020 08:31:54 +0000 (08:31 +0000)
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5718>

src/amd/vulkan/radv_cmd_buffer.c
src/amd/vulkan/radv_pipeline.c
src/amd/vulkan/radv_private.h

index 91b1b0f..bfae582 100644 (file)
@@ -2689,8 +2689,8 @@ radv_flush_vertex_descriptors(struct radv_cmd_buffer *cmd_buffer,
                        uint32_t *desc = &((uint32_t *)vb_ptr)[i * 4];
                        uint32_t offset;
                        struct radv_buffer *buffer = cmd_buffer->vertex_bindings[i].buffer;
-                       uint32_t stride = cmd_buffer->state.pipeline->binding_stride[i];
                        unsigned num_records;
+                       unsigned stride;
 
                        if (!buffer)
                                continue;
@@ -2700,7 +2700,18 @@ radv_flush_vertex_descriptors(struct radv_cmd_buffer *cmd_buffer,
                        offset = cmd_buffer->vertex_bindings[i].offset;
                        va += offset + buffer->offset;
 
-                       num_records = buffer->size - offset;
+                       if (cmd_buffer->vertex_bindings[i].size) {
+                               num_records = cmd_buffer->vertex_bindings[i].size;
+                       } else {
+                               num_records = buffer->size - offset;
+                       }
+
+                       if (cmd_buffer->state.pipeline->graphics.uses_dynamic_stride) {
+                               stride = cmd_buffer->vertex_bindings[i].stride;
+                       } else {
+                               stride = cmd_buffer->state.pipeline->binding_stride[i];
+                       }
+
                        if (cmd_buffer->device->physical_device->rad_info.chip_class != GFX8 && stride)
                                num_records /= stride;
 
@@ -3691,11 +3702,25 @@ VkResult radv_BeginCommandBuffer(
 }
 
 void radv_CmdBindVertexBuffers(
+        VkCommandBuffer                             commandBuffer,
+        uint32_t                                    firstBinding,
+        uint32_t                                    bindingCount,
+        const VkBuffer*                             pBuffers,
+        const VkDeviceSize*                         pOffsets)
+{
+       radv_CmdBindVertexBuffers2EXT(commandBuffer, firstBinding,
+                                     bindingCount, pBuffers, pOffsets,
+                                     NULL, NULL);
+}
+
+void radv_CmdBindVertexBuffers2EXT(
        VkCommandBuffer                             commandBuffer,
        uint32_t                                    firstBinding,
        uint32_t                                    bindingCount,
        const VkBuffer*                             pBuffers,
-       const VkDeviceSize*                         pOffsets)
+       const VkDeviceSize*                         pOffsets,
+       const VkDeviceSize*                         pSizes,
+       const VkDeviceSize*                         pStrides)
 {
        RADV_FROM_HANDLE(radv_cmd_buffer, cmd_buffer, commandBuffer);
        struct radv_vertex_binding *vb = cmd_buffer->vertex_bindings;
@@ -3708,15 +3733,22 @@ void radv_CmdBindVertexBuffers(
        for (uint32_t i = 0; i < bindingCount; i++) {
                RADV_FROM_HANDLE(radv_buffer, buffer, pBuffers[i]);
                uint32_t idx = firstBinding + i;
+               VkDeviceSize size = pSizes ? pSizes[i] : 0;
+               VkDeviceSize stride = pStrides ? pStrides[i] : 0;
 
+               /* pSizes and pStrides are optional. */
                if (!changed &&
                    (vb[idx].buffer != buffer ||
-                    vb[idx].offset != pOffsets[i])) {
+                    vb[idx].offset != pOffsets[i] ||
+                    vb[idx].size != size ||
+                    vb[idx].stride != stride)) {
                        changed = true;
                }
 
                vb[idx].buffer = buffer;
                vb[idx].offset = pOffsets[i];
+               vb[idx].size = size;
+               vb[idx].stride = stride;
 
                if (buffer) {
                        radv_cs_add_buffer(cmd_buffer->device->ws,
index ea1f928..f6df654 100644 (file)
@@ -1293,6 +1293,8 @@ static unsigned radv_dynamic_state_mask(VkDynamicState state)
                return RADV_DYNAMIC_STENCIL_TEST_ENABLE;
        case VK_DYNAMIC_STATE_STENCIL_OP_EXT:
                return RADV_DYNAMIC_STENCIL_OP;
+       case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT:
+               return RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE;
        default:
                unreachable("Unhandled dynamic state");
        }
@@ -1304,10 +1306,11 @@ static uint32_t radv_pipeline_needed_dynamic_state(const VkGraphicsPipelineCreat
 
        /* If rasterization is disabled we do not care about any of the
         * dynamic states, since they are all rasterization related only,
-        * except primitive topology.
+        * except primitive topology and vertex binding stride.
         */
        if (pCreateInfo->pRasterizationState->rasterizerDiscardEnable)
-               return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY;
+               return RADV_DYNAMIC_PRIMITIVE_TOPOLOGY |
+                      RADV_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE;
 
        if (!pCreateInfo->pRasterizationState->depthBiasEnable)
                states &= ~RADV_DYNAMIC_DEPTH_BIAS;
@@ -1559,6 +1562,9 @@ 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))
+               pipeline->graphics.uses_dynamic_stride = true;
+
        pipeline->dynamic_state.mask = states;
 }
 
index 359110e..53fc176 100644 (file)
@@ -1036,6 +1036,8 @@ enum radv_cmd_flush_bits {
 struct radv_vertex_binding {
        struct radv_buffer *                          buffer;
        VkDeviceSize                                 offset;
+       VkDeviceSize size;
+       VkDeviceSize stride;
 };
 
 struct radv_streamout_binding {
@@ -1678,6 +1680,7 @@ struct radv_pipeline {
                        unsigned tess_patch_control_points;
                        unsigned pa_su_sc_mode_cntl;
                        unsigned db_depth_control;
+                       bool uses_dynamic_stride;
 
                        /* Used for rbplus */
                        uint32_t col_format;