Module: Mesa Branch: staging/23.0 Commit: 52ddeed25e5e683fbf641eb8fac4c1baa78d62e9 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=52ddeed25e5e683fbf641eb8fac4c1baa78d62e9
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> (cherry picked from commit c356f1b4edc942f8c62125d01b7ddb886b72bbb7) --- .pick_status.json | 2 +- src/amd/vulkan/radv_cmd_buffer.c | 55 +++++++++++++++++++++++++--------------- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 22a182dbb4b..6e69a5ca9e1 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -13,7 +13,7 @@ "description": "radv: fix draw calls with 0-sized index buffers and robustness on NAVI10", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 7ef3093c614..7b3d217b3d1 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -7873,6 +7873,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, @@ -7893,18 +7912,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 { @@ -7917,12 +7935,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) @@ -7932,8 +7951,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 { @@ -7964,14 +7981,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); @@ -7985,19 +8001,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 {
