Skip to content

Commit

Permalink
[d3d11] Chjeck whether input layouts are identical
Browse files Browse the repository at this point in the history
Prevents redundant state changes when a game switches between
identical input layouts. Reduces the the number of Vulkan
calls in Grim Dawn by ~30%.
  • Loading branch information
doitsujin committed May 26, 2018
1 parent de9ffdc commit 8cd9795
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 15 deletions.
12 changes: 11 additions & 1 deletion src/d3d11/d3d11_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1235,8 +1235,18 @@ namespace dxvk {
auto inputLayout = static_cast<D3D11InputLayout*>(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();
}
}

Expand Down
31 changes: 26 additions & 5 deletions src/d3d11/d3d11_input_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

}
21 changes: 12 additions & 9 deletions src/d3d11/d3d11_input_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<DxvkContext>& ctx);
const Rc<DxvkContext>& ctx);

bool Compare(
const D3D11InputLayout* pOther) const;

private:

Expand Down

0 comments on commit 8cd9795

Please sign in to comment.