diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index 5be7d014..17ad6bfa 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -463,9 +463,10 @@ namespace dxvk { if (m_state.ia.inputLayout != inputLayout) { m_state.ia.inputLayout = inputLayout; - m_context->setInputLayout(inputLayout != nullptr - ? inputLayout->GetDXVKInputLayout() - : nullptr); + if (inputLayout != nullptr) + inputLayout->BindToContext(m_context); + else + m_context->setInputLayout(0, nullptr, 0, nullptr); } } diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index d42e9657..bab8af5e 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -342,8 +342,8 @@ namespace dxvk { Rc inputSignature = dxbcModule.isgn(); - std::vector attributes; - std::vector bindings; + std::vector attributes; + std::vector bindings; for (uint32_t i = 0; i < NumElements; i++) { const DxbcSgnEntry* entry = inputSignature->find( @@ -359,7 +359,7 @@ namespace dxvk { } // Create vertex input attribute description - VkVertexInputAttributeDescription attrib; + DxvkVertexAttribute attrib; attrib.location = entry->registerId; attrib.binding = pInputElementDescs[i].InputSlot; attrib.format = m_dxgiAdapter->LookupFormat( @@ -376,9 +376,8 @@ namespace dxvk { // Create vertex input binding description. The // stride is dynamic state in D3D11 and will be // set by D3D11DeviceContext::IASetVertexBuffers. - VkVertexInputBindingDescription binding; + DxvkVertexBinding binding; binding.binding = pInputElementDescs[i].InputSlot; - binding.stride = 0; binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; if (pInputElementDescs[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) { @@ -417,11 +416,10 @@ namespace dxvk { if (ppInputLayout != nullptr) { *ppInputLayout = ref( new D3D11InputLayout(this, - new DxvkInputLayout( - attributes.size(), - attributes.data(), - bindings.size(), - bindings.data()))); + attributes.size(), + attributes.data(), + bindings.size(), + bindings.data())); } return S_OK; diff --git a/src/d3d11/d3d11_input_layout.cpp b/src/d3d11/d3d11_input_layout.cpp index eb6623c4..9652a04e 100644 --- a/src/d3d11/d3d11_input_layout.cpp +++ b/src/d3d11/d3d11_input_layout.cpp @@ -5,9 +5,19 @@ namespace dxvk { D3D11InputLayout::D3D11InputLayout( D3D11Device* pDevice, - const Rc& inputLayout) - : m_device(pDevice), m_inputLayout(inputLayout) { + uint32_t numAttributes, + const DxvkVertexAttribute* pAttributes, + uint32_t numBindings, + const DxvkVertexBinding* pBindings) + : m_device(pDevice) { + m_attributes.resize(numAttributes); + m_bindings.resize(numBindings); + for (uint32_t i = 0; i < numAttributes; i++) + m_attributes.at(i) = pAttributes[i]; + + for (uint32_t i = 0; i < numBindings; i++) + m_bindings.at(i) = pBindings[i]; } @@ -30,4 +40,13 @@ namespace dxvk { *ppDevice = ref(m_device); } + + void D3D11InputLayout::BindToContext(const Rc& ctx) { + ctx->setInputLayout( + m_attributes.size(), + m_attributes.data(), + m_bindings.size(), + m_bindings.data()); + } + } diff --git a/src/d3d11/d3d11_input_layout.h b/src/d3d11/d3d11_input_layout.h index 3748b593..2b3ee523 100644 --- a/src/d3d11/d3d11_input_layout.h +++ b/src/d3d11/d3d11_input_layout.h @@ -12,7 +12,10 @@ namespace dxvk { D3D11InputLayout( D3D11Device* pDevice, - const Rc& inputLayout); + uint32_t numAttributes, + const DxvkVertexAttribute* pAttributes, + uint32_t numBindings, + const DxvkVertexBinding* pBindings); ~D3D11InputLayout(); @@ -23,14 +26,15 @@ namespace dxvk { void GetDevice( ID3D11Device **ppDevice) final; - Rc GetDXVKInputLayout() const { - return m_inputLayout; - } + void BindToContext( + const Rc& ctx); private: D3D11Device* const m_device; - Rc m_inputLayout; + + std::vector m_attributes; + std::vector m_bindings; }; diff --git a/src/dxgi/dxgi_presenter.cpp b/src/dxgi/dxgi_presenter.cpp index 1d5d65da..c2c02631 100644 --- a/src/dxgi/dxgi_presenter.cpp +++ b/src/dxgi/dxgi_presenter.cpp @@ -61,8 +61,7 @@ namespace dxvk { m_context->setInputAssemblyState(iaState); m_context->setInputLayout( - new DxvkInputLayout( - 0, nullptr, 0, nullptr)); + 0, nullptr, 0, nullptr); DxvkRasterizerState rsState; rsState.enableDepthClamp = VK_FALSE; diff --git a/src/dxvk/dxvk_constant_state.cpp b/src/dxvk/dxvk_constant_state.cpp index 6294152c..88ce0017 100644 --- a/src/dxvk/dxvk_constant_state.cpp +++ b/src/dxvk/dxvk_constant_state.cpp @@ -41,30 +41,4 @@ namespace dxvk { m_info.blendConstants[i] = 0.0f; } - - DxvkInputLayout::DxvkInputLayout( - uint32_t attributeCount, - const VkVertexInputAttributeDescription* attributeInfo, - uint32_t bindingCount, - const VkVertexInputBindingDescription* bindingInfo) { - // Copy vertex attribute info to a persistent array - m_attributes.resize(attributeCount); - for (uint32_t i = 0; i < attributeCount; i++) - m_attributes.at(i) = attributeInfo[i]; - - // Copy vertex binding info to a persistent array - m_bindings.resize(bindingCount); - for (uint32_t i = 0; i < bindingCount; i++) - m_bindings.at(i) = bindingInfo[i]; - - // Create info structure referencing those arrays - m_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - m_info.pNext = nullptr; - m_info.flags = 0; - m_info.vertexBindingDescriptionCount = m_bindings.size(); - m_info.pVertexBindingDescriptions = m_bindings.data(); - m_info.vertexAttributeDescriptionCount = m_attributes.size(); - m_info.pVertexAttributeDescriptions = m_attributes.data(); - } - } \ No newline at end of file diff --git a/src/dxvk/dxvk_constant_state.h b/src/dxvk/dxvk_constant_state.h index f12d45eb..c0b98c4c 100644 --- a/src/dxvk/dxvk_constant_state.h +++ b/src/dxvk/dxvk_constant_state.h @@ -103,47 +103,48 @@ namespace dxvk { }; + /** + * \brief Vertex attribute description + * + * Stores information about a + * single vertex attribute. + */ + struct DxvkVertexAttribute { + uint32_t location; + uint32_t binding; + VkFormat format; + uint32_t offset; + }; + + + /** + * \brief Vertex binding description + * + * Stores information about a + * single vertex binding slot. + */ + struct DxvkVertexBinding { + uint32_t binding; + VkVertexInputRate inputRate; + }; + + /** * \brief Input layout * - * Stores the attributes and vertex buffer binding - * descriptions that the vertex shader will take - * its input values from. + * Stores the description of all active + * vertex attributes and vertex bindings. */ - class DxvkInputLayout : public RcObject { - - public: - - DxvkInputLayout( - uint32_t attributeCount, - const VkVertexInputAttributeDescription* attributeInfo, - uint32_t bindingCount, - const VkVertexInputBindingDescription* bindingInfo); - - uint32_t vertexAttributeCount() const { - return m_attributes.size(); - } - - uint32_t vertexBindingCount() const { - return m_bindings.size(); - } - - const VkPipelineVertexInputStateCreateInfo& info() const { - return m_info; - } - - private: - - std::vector m_attributes; - std::vector m_bindings; - - VkPipelineVertexInputStateCreateInfo m_info; + struct DxvkInputLayout { + uint32_t numAttributes; + uint32_t numBindings; + std::array attributes; + std::array bindings; }; struct DxvkConstantStateObjects { - Rc inputLayout; Rc blendState; }; diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 372d5b31..0504eced 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -389,11 +389,20 @@ namespace dxvk { void DxvkContext::setInputLayout( - const Rc& state) { - if (m_state.co.inputLayout != state) { - m_state.co.inputLayout = state; - m_flags.set(DxvkContextFlag::GpDirtyPipelineState); - } + uint32_t attributeCount, + const DxvkVertexAttribute* attributes, + uint32_t bindingCount, + const DxvkVertexBinding* bindings) { + m_flags.set(DxvkContextFlag::GpDirtyPipelineState); + + m_state.il.numAttributes = attributeCount; + m_state.il.numBindings = bindingCount; + + for (uint32_t i = 0; i < attributeCount; i++) + m_state.il.attributes.at(i) = attributes[i]; + + for (uint32_t i = 0; i < bindingCount; i++) + m_state.il.bindings.at(i) = bindings[i]; } @@ -501,16 +510,20 @@ namespace dxvk { gpState.iaPrimitiveTopology = m_state.ia.primitiveTopology; gpState.iaPrimitiveRestart = m_state.ia.primitiveRestart; - const auto& il = m_state.co.inputLayout->info(); - gpState.ilAttributeCount = il.vertexAttributeDescriptionCount; - gpState.ilBindingCount = il.vertexBindingDescriptionCount; + gpState.ilAttributeCount = m_state.il.numAttributes; + gpState.ilBindingCount = m_state.il.numBindings; - for (uint32_t i = 0; i < gpState.ilAttributeCount; i++) - gpState.ilAttributes[i] = il.pVertexAttributeDescriptions[i]; + for (uint32_t i = 0; i < m_state.il.numAttributes; i++) { + gpState.ilAttributes[i].location = m_state.il.attributes[i].location; + gpState.ilAttributes[i].binding = m_state.il.attributes[i].binding; + gpState.ilAttributes[i].format = m_state.il.attributes[i].format; + gpState.ilAttributes[i].offset = m_state.il.attributes[i].offset; + } - for (uint32_t i = 0; i < gpState.ilBindingCount; i++) { - gpState.ilBindings[i] = il.pVertexBindingDescriptions[i]; - gpState.ilBindings[i].stride = m_state.vi.vertexStrides.at(i); + for (uint32_t i = 0; i < m_state.il.numBindings; i++) { + gpState.ilBindings[i].binding = m_state.il.bindings[i].binding; + gpState.ilBindings[i].inputRate = m_state.il.bindings[i].inputRate; + gpState.ilBindings[i].stride = m_state.vi.vertexStrides.at(i); } gpState.rsEnableDepthClamp = m_state.rs.enableDepthClamp; diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 0d04befa..f87fe651 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -270,11 +270,18 @@ namespace dxvk { const DxvkInputAssemblyState& state); /** - * \brief Sets input layout state - * \param [in] state New state object + * \brief Sets input layout + * + * \param [in] attributeCount Number of vertex attributes + * \param [in] attributes The vertex attributes + * \param [in] bindingCount Number of buffer bindings + * \param [in] bindings Vertex buffer bindigs */ void setInputLayout( - const Rc& state); + uint32_t attributeCount, + const DxvkVertexAttribute* attributes, + uint32_t bindingCount, + const DxvkVertexBinding* bindings); /** * \brief Sets rasterizer state diff --git a/src/dxvk/dxvk_context_state.h b/src/dxvk/dxvk_context_state.h index 17a93e9c..8fa12c38 100644 --- a/src/dxvk/dxvk_context_state.h +++ b/src/dxvk/dxvk_context_state.h @@ -90,6 +90,7 @@ namespace dxvk { */ struct DxvkContextState { DxvkInputAssemblyState ia; + DxvkInputLayout il; DxvkRasterizerState rs; DxvkMultisampleState ms; DxvkDepthStencilState ds; diff --git a/tests/dxvk/test_dxvk_triangle.cpp b/tests/dxvk/test_dxvk_triangle.cpp index 977f4315..2ffe42dc 100644 --- a/tests/dxvk/test_dxvk_triangle.cpp +++ b/tests/dxvk/test_dxvk_triangle.cpp @@ -87,8 +87,7 @@ public: iaState.primitiveRestart = VK_FALSE; m_dxvkContext->setInputAssemblyState(iaState); - m_dxvkContext->setInputLayout( - new DxvkInputLayout(0, nullptr, 0, nullptr)); + m_dxvkContext->setInputLayout(0, nullptr, 0, nullptr); DxvkRasterizerState rsState; rsState.enableDepthClamp = VK_FALSE;