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 {
