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

Author: Samuel Pitoiset <[email protected]>
Date:   Wed Feb 22 17:56:03 2023 +0100

radv: fix draw calls with 0-sized index buffers and robustness on NAVI10

The correct workaround is to bind an internal index buffer to handle
robustness2 correctly.

Fixes dEQP-VK.robustness.index_access.* in CTS 1.3.5.0 on NAVI10.

Cc: mesa-stable
Signed-off-by: Samuel Pitoiset <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21471>

---

 src/amd/vulkan/radv_cmd_buffer.c | 55 +++++++++++++++++++++++++---------------
 1 file changed, 35 insertions(+), 20 deletions(-)

diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c
index 5a8222f89c3..acd1d3931f7 100644
--- a/src/amd/vulkan/radv_cmd_buffer.c
+++ b/src/amd/vulkan/radv_cmd_buffer.c
@@ -7937,6 +7937,25 @@ radv_emit_userdata_task(struct radv_cmd_buffer 
*cmd_buffer, uint32_t x, uint32_t
    radv_emit_userdata_task_ib_only(cmd_buffer, ib_va, first_task ? 8 : 0);
 }
 
+/* Bind an internal index buffer for GPUs that hang with 0-sized index buffers 
to handle robustness2
+ * which requires 0 for out-of-bounds access.
+ */
+static void
+radv_handle_zero_index_buffer_bug(struct radv_cmd_buffer *cmd_buffer, uint64_t 
*index_va,
+                                  uint32_t *remaining_indexes)
+{
+   const uint32_t zero = 0;
+   uint32_t offset;
+
+   if (!radv_cmd_buffer_upload_data(cmd_buffer, sizeof(uint32_t), &zero, 
&offset)) {
+      vk_command_buffer_set_error(&cmd_buffer->vk, 
VK_ERROR_OUT_OF_HOST_MEMORY);
+      return;
+   }
+
+   *index_va = radv_buffer_get_va(cmd_buffer->upload.upload_bo) + offset;
+   *remaining_indexes = 1;
+}
+
 ALWAYS_INLINE static void
 radv_emit_draw_packets_indexed(struct radv_cmd_buffer *cmd_buffer,
                                const struct radv_draw_info *info,
@@ -7957,18 +7976,17 @@ radv_emit_draw_packets_indexed(struct radv_cmd_buffer 
*cmd_buffer,
       if (vertexOffset) {
          radv_emit_userdata_vertex(cmd_buffer, info, *vertexOffset);
          vk_foreach_multi_draw_indexed(draw, i, minfo, drawCount, stride) {
-            const uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
 
-            /* Skip draw calls with 0-sized index buffers if the GPU can't 
handle them */
+            /* Handle draw calls with 0-sized index buffers if the GPU can't 
support them. */
             if (!remaining_indexes &&
                 
cmd_buffer->device->physical_device->rad_info.has_zero_index_buffer_bug)
-               continue;
+               radv_handle_zero_index_buffer_bug(cmd_buffer, &index_va, 
&remaining_indexes);
 
             if (i > 0)
                radeon_set_sh_reg(cs, state->graphics_pipeline->vtx_base_sgpr + 
sizeof(uint32_t), i);
 
-            const uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
-
             if (!state->render.view_mask) {
                radv_cs_emit_draw_indexed_packet(cmd_buffer, index_va, 
remaining_indexes, draw->indexCount, false);
             } else {
@@ -7981,12 +7999,13 @@ radv_emit_draw_packets_indexed(struct radv_cmd_buffer 
*cmd_buffer,
          }
       } else {
          vk_foreach_multi_draw_indexed(draw, i, minfo, drawCount, stride) {
-            const uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
 
-            /* Skip draw calls with 0-sized index buffers if the GPU can't 
handle them */
+            /* Handle draw calls with 0-sized index buffers if the GPU can't 
support them. */
             if (!remaining_indexes &&
                 
cmd_buffer->device->physical_device->rad_info.has_zero_index_buffer_bug)
-               continue;
+               radv_handle_zero_index_buffer_bug(cmd_buffer, &index_va, 
&remaining_indexes);
 
             if (i > 0) {
                if (state->last_vertex_offset != draw->vertexOffset)
@@ -7996,8 +8015,6 @@ radv_emit_draw_packets_indexed(struct radv_cmd_buffer 
*cmd_buffer,
             } else
                radv_emit_userdata_vertex(cmd_buffer, info, draw->vertexOffset);
 
-            const uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
-
             if (!state->render.view_mask) {
                radv_cs_emit_draw_indexed_packet(cmd_buffer, index_va, 
remaining_indexes, draw->indexCount, false);
             } else {
@@ -8028,14 +8045,13 @@ radv_emit_draw_packets_indexed(struct radv_cmd_buffer 
*cmd_buffer,
 
          radv_emit_userdata_vertex(cmd_buffer, info, *vertexOffset);
          vk_foreach_multi_draw_indexed(draw, i, minfo, drawCount, stride) {
-            const uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
 
-            /* Skip draw calls with 0-sized index buffers if the GPU can't 
handle them */
+            /* Handle draw calls with 0-sized index buffers if the GPU can't 
support them. */
             if (!remaining_indexes &&
                 
cmd_buffer->device->physical_device->rad_info.has_zero_index_buffer_bug)
-               continue;
-
-            const uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
+               radv_handle_zero_index_buffer_bug(cmd_buffer, &index_va, 
&remaining_indexes);
 
             if (!state->render.view_mask) {
                radv_cs_emit_draw_indexed_packet(cmd_buffer, index_va, 
remaining_indexes, draw->indexCount, can_eop && i < drawCount - 1);
@@ -8049,19 +8065,18 @@ radv_emit_draw_packets_indexed(struct radv_cmd_buffer 
*cmd_buffer,
          }
       } else {
          vk_foreach_multi_draw_indexed(draw, i, minfo, drawCount, stride) {
-            const uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint32_t remaining_indexes = MAX2(state->max_index_count, 
draw->firstIndex) - draw->firstIndex;
+            uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
 
-            /* Skip draw calls with 0-sized index buffers if the GPU can't 
handle them */
+            /* Handle draw calls with 0-sized index buffers if the GPU can't 
support them. */
             if (!remaining_indexes &&
                 
cmd_buffer->device->physical_device->rad_info.has_zero_index_buffer_bug)
-               continue;
+               radv_handle_zero_index_buffer_bug(cmd_buffer, &index_va, 
&remaining_indexes);
 
             const VkMultiDrawIndexedInfoEXT *next = (const 
VkMultiDrawIndexedInfoEXT*)(i < drawCount - 1 ? ((uint8_t*)draw + stride) : 
NULL);
             const bool offset_changes = next && next->vertexOffset != 
draw->vertexOffset;
             radv_emit_userdata_vertex(cmd_buffer, info, draw->vertexOffset);
 
-            const uint64_t index_va = state->index_va + draw->firstIndex * 
index_size;
-
             if (!state->render.view_mask) {
                radv_cs_emit_draw_indexed_packet(cmd_buffer, index_va, 
remaining_indexes, draw->indexCount, can_eop && !offset_changes && i < 
drawCount - 1);
             } else {

Reply via email to