From d4a0581f8fa0d5cac49f47935007dadb331e978f Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 1 Feb 2018 13:29:57 +0100 Subject: [PATCH] [dxvk] Bind dummy resource for unbound vertex and index buffers Allows GTA V to run, although heavy rendering artifacts remain. --- src/dxvk/dxvk_context.cpp | 24 +++++++++++++++++++++++- src/dxvk/dxvk_context_state.h | 3 ++- src/dxvk/dxvk_device.h | 8 ++++++++ src/dxvk/dxvk_unbound.h | 14 +++++++++++++- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 0addc084a..851b064cd 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1185,8 +1185,12 @@ namespace dxvk { m_flags.clr(DxvkContextFlag::GpDirtyPipelineState); for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) { + const uint32_t binding = m_state.gp.state.ilBindings[i].binding; + m_state.gp.state.ilBindings[i].stride - = m_state.vi.vertexStrides[m_state.gp.state.ilBindings[i].binding]; + = (m_state.vi.bindingMask & (1u << binding)) != 0 + ? m_state.vi.vertexStrides[binding] + : 0; } for (uint32_t i = m_state.gp.state.ilBindingCount; i < MaxNumVertexBindings; i++) @@ -1399,6 +1403,10 @@ namespace dxvk { m_state.vi.indexType); m_cmd->trackResource( physicalSlice.resource()); + } else { + m_cmd->cmdBindIndexBuffer( + m_device->dummyBufferHandle(), + 0, VK_INDEX_TYPE_UINT32); } } } @@ -1408,6 +1416,8 @@ namespace dxvk { if (m_flags.test(DxvkContextFlag::GpDirtyVertexBuffers)) { m_flags.clr(DxvkContextFlag::GpDirtyVertexBuffers); + uint32_t bindingMask = 0; + for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) { const uint32_t binding = m_state.gp.state.ilBindings[i].binding; @@ -1419,8 +1429,20 @@ namespace dxvk { m_cmd->cmdBindVertexBuffers(binding, 1, &handle, &offset); m_cmd->trackResource(vbo.resource()); + + bindingMask |= 1u << binding; + } else { + const VkBuffer handle = m_device->dummyBufferHandle(); + const VkDeviceSize offset = 0; + + m_cmd->cmdBindVertexBuffers(binding, 1, &handle, &offset); } } + + if (m_state.vi.bindingMask != bindingMask) { + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + m_state.vi.bindingMask = bindingMask; + } } } diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index ecfb43027..4ff5c7937 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -38,7 +38,8 @@ namespace dxvk { struct DxvkVertexInputState { DxvkBufferSlice indexBuffer; - VkIndexType indexType = VK_INDEX_TYPE_UINT32; + VkIndexType indexType = VK_INDEX_TYPE_UINT32; + uint32_t bindingMask = 0; std::array vertexBuffers; diff --git a/src/dxvk/dxvk_device.h b/src/dxvk/dxvk_device.h index 88b4e3bdd..be70f3c40 100644 --- a/src/dxvk/dxvk_device.h +++ b/src/dxvk/dxvk_device.h @@ -275,6 +275,14 @@ namespace dxvk { const Rc& surface, const DxvkSwapchainProperties& properties); + /** + * \brief Dummy buffer handle + * \returns Use for unbound vertex buffers. + */ + VkBuffer dummyBufferHandle() const { + return m_unboundResources.bufferHandle(); + } + /** * \brief Dummy buffer descriptor * \returns Descriptor that points to a dummy buffer diff --git a/src/dxvk/dxvk_unbound.h b/src/dxvk/dxvk_unbound.h index 37d87d0d8..8981fdadb 100644 --- a/src/dxvk/dxvk_unbound.h +++ b/src/dxvk/dxvk_unbound.h @@ -20,10 +20,22 @@ namespace dxvk { DxvkUnboundResources(DxvkDevice* dev); ~DxvkUnboundResources(); + /** + * \brief Dummy buffer handle + * + * Returns a handle to a buffer filled + * with zeroes. Use for unbound vertex + * and index buffers. + * \returns Dummy buffer handle + */ + VkBuffer bufferHandle() const { + return m_buffer->slice().handle(); + } + /** * \brief Dummy buffer descriptor * - * Points to a tiny buffer with undefined + * Points to a small buffer with undefined * values. Do not access this buffer. * \returns Dummy buffer descriptor */