From 9a8263f465949f6484c859c2f7bbbbed6e253c6f Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Tue, 17 Apr 2018 17:24:16 +0200 Subject: [PATCH] [dxvk] Implement vertex binding divisors Uses VK_EXT_vertex_attribute_divisor when available. --- src/dxvk/dxvk_context.cpp | 14 +------------- src/dxvk/dxvk_context_state.h | 9 ++------- src/dxvk/dxvk_graphics.cpp | 27 ++++++++++++++++++++++++++- src/dxvk/dxvk_graphics.h | 1 + 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 25de161e..927d0366 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -1386,8 +1386,6 @@ namespace dxvk { m_flags.set( DxvkContextFlag::GpDirtyPipelineState, DxvkContextFlag::GpDirtyVertexBuffers); - m_flags.clr( - DxvkContextFlag::GpEmulateInstanceFetchRate); for (uint32_t i = 0; i < attributeCount; i++) { m_state.gp.state.ilAttributes[i].location = attributes[i].location; @@ -1402,10 +1400,7 @@ namespace dxvk { for (uint32_t i = 0; i < bindingCount; i++) { m_state.gp.state.ilBindings[i].binding = bindings[i].binding; m_state.gp.state.ilBindings[i].inputRate = bindings[i].inputRate; - m_state.vi.vertexFetchRates[bindings[i].binding] = bindings[i].fetchRate; - - if (bindings[i].inputRate == VK_VERTEX_INPUT_RATE_INSTANCE && bindings[i].fetchRate != 1) - m_flags.set(DxvkContextFlag::GpEmulateInstanceFetchRate); + m_state.gp.state.ilDivisors[i] = bindings[i].fetchRate; } for (uint32_t i = bindingCount; i < m_state.gp.state.ilBindingCount; i++) @@ -1413,13 +1408,6 @@ namespace dxvk { m_state.gp.state.ilAttributeCount = attributeCount; m_state.gp.state.ilBindingCount = bindingCount; - - if (m_flags.test(DxvkContextFlag::GpEmulateInstanceFetchRate)) { - static bool errorShown = false; - - if (!std::exchange(errorShown, true)) - Logger::warn("Dxvk: GpEmulateInstanceFetchRate not handled yet"); - } } diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index d28b0a11..0ebc1b31 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -27,7 +27,6 @@ namespace dxvk { GpDirtyResources, ///< Graphics pipeline resource bindings are out of date GpDirtyVertexBuffers, ///< Vertex buffer bindings are out of date GpDirtyIndexBuffer, ///< Index buffer binding are out of date - GpEmulateInstanceFetchRate, ///< The current input layout uses fetch rates != 1 CpDirtyPipeline, ///< Compute pipeline binding are out of date CpDirtyPipelineState, ///< Compute pipeline needs to be recompiled @@ -42,12 +41,8 @@ namespace dxvk { VkIndexType indexType = VK_INDEX_TYPE_UINT32; uint32_t bindingMask = 0; - std::array vertexBuffers = { }; - std::array vertexStrides = { }; - std::array vertexFetchRates = { }; + std::array vertexBuffers = { }; + std::array vertexStrides = { }; }; diff --git a/src/dxvk/dxvk_graphics.cpp b/src/dxvk/dxvk_graphics.cpp index 611c5053..554434d4 100644 --- a/src/dxvk/dxvk_graphics.cpp +++ b/src/dxvk/dxvk_graphics.cpp @@ -135,15 +135,40 @@ namespace dxvk { if (m_gs != nullptr) stages.push_back(m_gs->stageInfo(&specInfo)); if (m_fs != nullptr) stages.push_back(m_fs->stageInfo(&specInfo)); + std::array viDivisorDesc; + uint32_t viDivisorCount = 0; + + for (uint32_t i = 0; i < state.ilBindingCount; i++) { + if (state.ilBindings[i].inputRate == VK_VERTEX_INPUT_RATE_INSTANCE) { + const uint32_t id = viDivisorCount++; + + viDivisorDesc[id].binding = state.ilBindings[i].binding; + viDivisorDesc[id].divisor = state.ilDivisors[i]; + } + } + + VkPipelineVertexInputDivisorStateCreateInfoEXT viDivisorInfo; + viDivisorInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT; + viDivisorInfo.pNext = nullptr; + viDivisorInfo.vertexBindingDivisorCount = viDivisorCount; + viDivisorInfo.pVertexBindingDivisors = viDivisorDesc.data(); + VkPipelineVertexInputStateCreateInfo viInfo; viInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - viInfo.pNext = nullptr; + viInfo.pNext = &viDivisorInfo; viInfo.flags = 0; viInfo.vertexBindingDescriptionCount = state.ilBindingCount; viInfo.pVertexBindingDescriptions = state.ilBindings; viInfo.vertexAttributeDescriptionCount = state.ilAttributeCount; viInfo.pVertexAttributeDescriptions = state.ilAttributes; + if (viDivisorCount == 0) + viInfo.pNext = viDivisorInfo.pNext; + + // TODO make this extension required when widely supported + if (!m_device->extensions().extVertexAttributeDivisor.enabled()) + viInfo.pNext = viDivisorInfo.pNext; + VkPipelineInputAssemblyStateCreateInfo iaInfo; iaInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; iaInfo.pNext = nullptr; diff --git a/src/dxvk/dxvk_graphics.h b/src/dxvk/dxvk_graphics.h index 67d620ee..8b6f56a4 100644 --- a/src/dxvk/dxvk_graphics.h +++ b/src/dxvk/dxvk_graphics.h @@ -43,6 +43,7 @@ namespace dxvk { uint32_t ilBindingCount; VkVertexInputAttributeDescription ilAttributes[DxvkLimits::MaxNumVertexAttributes]; VkVertexInputBindingDescription ilBindings[DxvkLimits::MaxNumVertexBindings]; + uint32_t ilDivisors[DxvkLimits::MaxNumVertexBindings]; VkBool32 rsEnableDepthClamp; VkBool32 rsEnableDiscard;