From 644f33a82b1f678b9953883e88a0187faec141b7 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 8 May 2019 00:52:30 +0200 Subject: [PATCH] [dxvk] Optimize unbound vertex buffer handling We can actually just set the stride to 0 when binding a null buffer, so that we can avoid all the runtime tracking. --- src/d3d11/d3d11_context.cpp | 2 +- src/dxvk/dxvk_context.cpp | 23 ++++++----------------- src/dxvk/dxvk_context_state.h | 1 - 3 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index bd601b8b0..3894da89a 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -3200,7 +3200,7 @@ namespace dxvk { EmitCs([ cSlotId = Slot, cBufferSlice = pBuffer != nullptr ? pBuffer->GetBufferSlice(Offset) : DxvkBufferSlice(), - cStride = pBuffer != nullptr ? Stride : 0 + cStride = Stride ] (DxvkContext* ctx) { ctx->bindVertexBuffer(cSlotId, cBufferSlice, cStride); }); diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 9a4554091..1c91992ab 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -242,6 +242,9 @@ namespace dxvk { m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers); } + if (unlikely(!buffer.defined())) + stride = 0; + if (m_state.vi.vertexStrides[binding] != stride) { m_state.vi.vertexStrides[binding] = stride; m_flags.set(DxvkContextFlag::GpDirtyPipelineState); @@ -3316,14 +3319,10 @@ namespace dxvk { this->pauseTransformFeedback(); - // Fix up vertex binding strides for unbound buffers + // Set up vertex buffer strides for active bindings 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.bindingMask & (1u << binding)) != 0 - ? m_state.vi.vertexStrides[binding] - : 0; + m_state.gp.state.ilBindings[i].stride = m_state.vi.vertexStrides[binding]; } for (uint32_t i = m_state.gp.state.ilBindingCount; i < MaxNumVertexBindings; i++) @@ -3679,10 +3678,10 @@ namespace dxvk { // Set buffer handles and offsets for active bindings uint32_t bindingMask = 0; - uint32_t bindingDead = 0; for (uint32_t i = 0; i < m_state.gp.state.ilBindingCount; i++) { uint32_t binding = m_state.gp.state.ilBindings[i].binding; + bindingMask |= 1u << binding; if (likely(m_state.vi.vertexBuffers[binding].defined())) { auto vbo = m_state.vi.vertexBuffers[binding].getDescriptor(); @@ -3690,24 +3689,14 @@ namespace dxvk { buffers[binding] = vbo.buffer.buffer; offsets[binding] = vbo.buffer.offset; - bindingMask |= 1u << binding; m_cmd->trackResource(m_state.vi.vertexBuffers[binding].buffer()); } else { buffers[binding] = m_device->dummyBufferHandle(); offsets[binding] = 0; - - bindingDead |= 1u << binding; } } - // Adjust stride of inactive bindings if needed - if (unlikely(m_state.vi.bindingMask != bindingMask)) { - m_flags.set(DxvkContextFlag::GpDirtyPipelineState); - m_state.vi.bindingMask = bindingMask; - } - // Actually bind all the vertex buffers. - bindingMask |= bindingDead; uint32_t bindingIndex = 0; while (bindingMask) { diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 9d9ba56eb..906ee56c8 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -81,7 +81,6 @@ namespace dxvk { struct DxvkVertexInputState { DxvkBufferSlice indexBuffer; VkIndexType indexType = VK_INDEX_TYPE_UINT32; - uint32_t bindingMask = 0; std::array vertexBuffers = { }; std::array vertexStrides = { };