From 8cd97959f2b97c17d25ce2b8b1956a6a08ebe893 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 27 May 2018 01:10:49 +0200 Subject: [PATCH] [d3d11] Chjeck whether input layouts are identical Prevents redundant state changes when a game switches between identical input layouts. Reduces the the number of Vulkan calls in Grim Dawn by ~30%. --- src/d3d11/d3d11_context.cpp | 12 +++++++++++- src/d3d11/d3d11_input_layout.cpp | 31 ++++++++++++++++++++++++++----- src/d3d11/d3d11_input_layout.h | 21 ++++++++++++--------- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/d3d11/d3d11_context.cpp b/src/d3d11/d3d11_context.cpp index e7ab7e9e7..62bb98441 100644 --- a/src/d3d11/d3d11_context.cpp +++ b/src/d3d11/d3d11_context.cpp @@ -1235,8 +1235,18 @@ namespace dxvk { auto inputLayout = static_cast(pInputLayout); if (m_state.ia.inputLayout != inputLayout) { + bool equal = false; + + // Some games (e.g. Grim Dawn) create lots and lots of + // identical input layouts, so we'll only apply the state + // if the input layouts has actually changed between calls. + if (m_state.ia.inputLayout != nullptr && inputLayout != nullptr) + equal = m_state.ia.inputLayout->Compare(inputLayout); + m_state.ia.inputLayout = inputLayout; - ApplyInputLayout(); + + if (!equal) + ApplyInputLayout(); } } diff --git a/src/d3d11/d3d11_input_layout.cpp b/src/d3d11/d3d11_input_layout.cpp index a19aa9151..2e4e794f3 100644 --- a/src/d3d11/d3d11_input_layout.cpp +++ b/src/d3d11/d3d11_input_layout.cpp @@ -4,11 +4,11 @@ namespace dxvk { D3D11InputLayout::D3D11InputLayout( - D3D11Device* pDevice, - uint32_t numAttributes, - const DxvkVertexAttribute* pAttributes, - uint32_t numBindings, - const DxvkVertexBinding* pBindings) + D3D11Device* pDevice, + uint32_t numAttributes, + const DxvkVertexAttribute* pAttributes, + uint32_t numBindings, + const DxvkVertexBinding* pBindings) : m_device(pDevice) { m_attributes.resize(numAttributes); m_bindings.resize(numBindings); @@ -55,4 +55,25 @@ namespace dxvk { m_bindings.data()); } + + bool D3D11InputLayout::Compare(const D3D11InputLayout* pOther) const { + bool eq = m_attributes.size() == pOther->m_attributes.size() + && m_bindings.size() == pOther->m_bindings.size(); + + for (uint32_t i = 0; eq && i < m_attributes.size(); i++) { + eq &= m_attributes[i].location == pOther->m_attributes[i].location + && m_attributes[i].binding == pOther->m_attributes[i].binding + && m_attributes[i].format == pOther->m_attributes[i].format + && m_attributes[i].offset == pOther->m_attributes[i].offset; + } + + for (uint32_t i = 0; eq && i < m_bindings.size(); i++) { + eq &= m_bindings[i].binding == pOther->m_bindings[i].binding + && m_bindings[i].fetchRate == pOther->m_bindings[i].fetchRate + && m_bindings[i].inputRate == pOther->m_bindings[i].inputRate; + } + + return eq; + } + } diff --git a/src/d3d11/d3d11_input_layout.h b/src/d3d11/d3d11_input_layout.h index cfe068d3f..e3d33d1dc 100644 --- a/src/d3d11/d3d11_input_layout.h +++ b/src/d3d11/d3d11_input_layout.h @@ -11,23 +11,26 @@ namespace dxvk { public: D3D11InputLayout( - D3D11Device* pDevice, - uint32_t numAttributes, - const DxvkVertexAttribute* pAttributes, - uint32_t numBindings, - const DxvkVertexBinding* pBindings); + D3D11Device* pDevice, + uint32_t numAttributes, + const DxvkVertexAttribute* pAttributes, + uint32_t numBindings, + const DxvkVertexBinding* pBindings); ~D3D11InputLayout(); HRESULT STDMETHODCALLTYPE QueryInterface( - REFIID riid, - void** ppvObject) final; + REFIID riid, + void** ppvObject) final; void STDMETHODCALLTYPE GetDevice( - ID3D11Device **ppDevice) final; + ID3D11Device** ppDevice) final; void BindToContext( - const Rc& ctx); + const Rc& ctx); + + bool Compare( + const D3D11InputLayout* pOther) const; private: