From 3a4e555e9c289cf3803c9a4d5bfd7fa488a86d46 Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Fri, 16 Oct 2020 10:57:02 +0200 Subject: [PATCH] vkd3d: Track if we have a valid index buffer bound. Ignore any indexed draw calls which uses a NULL index buffer. This is not fully correct, but there is no easy way to emulate D3D12 behavior exactly. Signed-off-by: Hans-Kristian Arntzen --- libs/vkd3d/command.c | 40 +++++++++++++++++++++++++++++++------- libs/vkd3d/vkd3d_private.h | 1 + 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 93dcf268..c30dd984 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -2813,6 +2813,7 @@ static void d3d12_command_list_reset_state(struct d3d12_command_list *list, list->debug_capture = false; #endif list->has_replaced_shaders = false; + list->has_valid_index_buffer = false; list->current_framebuffer = VK_NULL_HANDLE; list->current_pipeline = VK_NULL_HANDLE; @@ -3678,6 +3679,19 @@ static void STDMETHODCALLTYPE d3d12_command_list_DrawIndexedInstanced(d3d12_comm iface, index_count_per_instance, instance_count, start_vertex_location, base_vertex_location, start_instance_location); + if (!list->has_valid_index_buffer) + { + FIXME_ONCE("Application attempts to perform an indexed draw call without index buffer bound.\n"); + /* We are supposed to render all 0 indices here. However, there are several problems with emulating this approach. + * There is no robustness support for index buffers, and if we render all 0 indices, + * it is extremely unlikely that this would create a meaningful side effect. + * For any line or triangle primitive, we would end up creating degenerates for every primitive. + * The only reasonable scenarios where we will observe anything is stream-out with all duplicate values, or + * geometry shaders where the application makes use of PrimitiveID to construct primitives. + * Until proven to be required otherwise, we just ignore the draw call. */ + return; + } + if (!d3d12_command_list_begin_render_pass(list)) { WARN("Failed to begin render pass, ignoring draw call.\n"); @@ -5440,7 +5454,8 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetIndexBuffer(d3d12_command_ if (!view) { - WARN("Ignoring NULL index buffer view.\n"); + WARN("Got NULL index buffer view, indexed draw calls will be dropped.\n"); + list->has_valid_index_buffer = false; return; } @@ -5455,15 +5470,20 @@ static void STDMETHODCALLTYPE d3d12_command_list_IASetIndexBuffer(d3d12_command_ index_type = VK_INDEX_TYPE_UINT32; break; default: - WARN("Invalid index format %#x.\n", view->Format); - return; + FIXME_ONCE("Invalid index format %#x. This will map to R16_UINT to match observed driver behavior.\n", view->Format); + /* D3D12 debug layer disallows this case, but it doesn't trigger a DEVICE LOST event, so we shouldn't crash and burn. */ + index_type = VK_INDEX_TYPE_UINT16; + break; } list->index_buffer_format = view->Format; - - resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, view->BufferLocation); - VK_CALL(vkCmdBindIndexBuffer(list->vk_command_buffer, resource->vk_buffer, - view->BufferLocation - resource->gpu_address, index_type)); + list->has_valid_index_buffer = view->BufferLocation != 0; + if (list->has_valid_index_buffer) + { + resource = vkd3d_gpu_va_allocator_dereference(&list->device->gpu_va_allocator, view->BufferLocation); + VK_CALL(vkCmdBindIndexBuffer(list->vk_command_buffer, resource->vk_buffer, + view->BufferLocation - resource->gpu_address, index_type)); + } } static void STDMETHODCALLTYPE d3d12_command_list_IASetVertexBuffers(d3d12_command_list_iface *iface, @@ -6521,6 +6541,12 @@ static void STDMETHODCALLTYPE d3d12_command_list_ExecuteIndirect(d3d12_command_l break; case D3D12_INDIRECT_ARGUMENT_TYPE_DRAW_INDEXED: + if (!list->has_valid_index_buffer) + { + FIXME_ONCE("Application attempts to perform an indexed draw call without index buffer bound.\n"); + break; + } + if (!d3d12_command_list_begin_render_pass(list)) { WARN("Failed to begin render pass, ignoring draw.\n"); diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index 052019c1..39e1c9ea 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -1295,6 +1295,7 @@ struct d3d12_command_list bool need_host_barrier; bool debug_capture; bool has_replaced_shaders; + bool has_valid_index_buffer; VkCommandBuffer vk_command_buffer; DXGI_FORMAT index_buffer_format;