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 <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21471>
This commit is contained in:
Samuel Pitoiset 2023-02-22 17:56:03 +01:00 committed by Marge Bot
parent b1c19498c6
commit c356f1b4ed

View file

@ -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 {