From 6a1cd595a58bb516ea21be57fb95658d4e61c585 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Wed, 13 Mar 2024 15:49:46 +0100 Subject: [PATCH] [d3d9] Reduce data copied for SWVP vertex decls --- src/d3d9/d3d9_device.cpp | 9 +++++++-- src/d3d9/d3d9_swvp_emu.cpp | 22 +++++++++++++--------- src/d3d9/d3d9_swvp_emu.h | 23 +++++++++++++++++++---- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index de67014e..5c2e7359 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -2946,14 +2946,19 @@ namespace dxvk { auto slice = dst->GetBufferSlice(); slice = slice.subSlice(offset, slice.length() - offset); + D3D9CompactVertexElements elements; + for (const D3DVERTEXELEMENT9& element : decl->GetElements()) { + elements.emplace_back(element); + } + EmitCs([this, - cVertexElements = decl->GetElements(), + cVertexElements = std::move(elements), cVertexCount = VertexCount, cStartIndex = SrcStartIndex, cInstanceCount = GetInstanceCount(), cBufferSlice = slice ](DxvkContext* ctx) mutable { - Rc shader = m_swvpEmulator.GetShaderModule(this, cVertexElements); + Rc shader = m_swvpEmulator.GetShaderModule(this, std::move(cVertexElements)); auto drawInfo = GenerateDrawInfo(D3DPT_POINTLIST, cVertexCount, cInstanceCount); diff --git a/src/d3d9/d3d9_swvp_emu.cpp b/src/d3d9/d3d9_swvp_emu.cpp index 43e30a70..98ed7782 100644 --- a/src/d3d9/d3d9_swvp_emu.cpp +++ b/src/d3d9/d3d9_swvp_emu.cpp @@ -9,13 +9,14 @@ namespace dxvk { // Doesn't compare everything, only what we use in SWVP. - size_t D3D9VertexDeclHash::operator () (const D3D9VertexElements& key) const { + size_t D3D9VertexDeclHash::operator () (const D3D9CompactVertexElements& key) const { DxvkHashState hash; std::hash bytehash; std::hash wordhash; - for (auto& element : key) { + for (uint32_t i = 0; i < key.size(); i++) { + const auto& element = key[i]; hash.add(wordhash(element.Stream)); hash.add(wordhash(element.Offset)); hash.add(bytehash(element.Type)); @@ -27,7 +28,7 @@ namespace dxvk { return hash; } - bool D3D9VertexDeclEq::operator () (const D3D9VertexElements& a, const D3D9VertexElements& b) const { + bool D3D9VertexDeclEq::operator () (const D3D9CompactVertexElements& a, const D3D9CompactVertexElements& b) const { if (a.size() != b.size()) return false; @@ -109,7 +110,7 @@ namespace dxvk { m_module.opLabel(m_module.allocateId()); } - void compile(const D3D9VertexElements& elements) { + void compile(const D3D9CompactVertexElements& elements) { uint32_t uint_t = m_module.defIntType(32, false); uint32_t float_t = m_module.defFloatType(32); uint32_t vec4_t = m_module.defVectorType(float_t, 4); @@ -144,8 +145,9 @@ namespace dxvk { uint32_t primitiveId = m_module.opLoad(uint_t, primitiveIdPtr); // The size of any given vertex - uint32_t size = 0; - for (const auto& element : elements) { + uint32_t size = 0; + for (uint32_t i = 0; i < elements.size(); i++) { + const auto& element = elements[i]; if (element.Stream == 0 && element.Type != D3DDECLTYPE_UNUSED) { size = std::max(size, element.Offset + GetDecltypeSize(D3DDECLTYPE(element.Type))); } @@ -157,7 +159,8 @@ namespace dxvk { uint32_t thisVertexOffset = m_module.opIMul(uint_t, vertexSize, primitiveId); - for (auto& element : elements) { + for (uint32_t i = 0; i < elements.size(); i++) { + const auto& element = elements[i]; // Load the slot associated with this element DxsoSemantic semantic = { DxsoUsage(element.Usage), element.UsageIndex }; @@ -304,7 +307,7 @@ namespace dxvk { }; - Rc D3D9SWVPEmulator::GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexElements& elements) { + Rc D3D9SWVPEmulator::GetShaderModule(D3D9DeviceEx* pDevice, D3D9CompactVertexElements&& elements) { // Use the shader's unique key for the lookup { std::unique_lock lock(m_mutex); @@ -343,7 +346,8 @@ namespace dxvk { // that object instead and discard the newly created module. { std::unique_lock lock(m_mutex); - auto status = m_modules.insert({ elements, shader }); + std::pair> pair = { std::move(elements), shader }; + auto status = m_modules.insert(std::move(pair)); if (!status.second) return status.first->second; } diff --git a/src/d3d9/d3d9_swvp_emu.h b/src/d3d9/d3d9_swvp_emu.h index c80823f0..905a5766 100644 --- a/src/d3d9/d3d9_swvp_emu.h +++ b/src/d3d9/d3d9_swvp_emu.h @@ -11,26 +11,41 @@ namespace dxvk { class D3D9VertexDecl; class D3D9DeviceEx; + struct D3D9CompactVertexElement { + uint16_t Stream : 4; + uint16_t Type : 5; + uint16_t Method : 3; + uint16_t Usage : 4; + uint16_t UsageIndex; + uint16_t Offset; + + D3D9CompactVertexElement(const D3DVERTEXELEMENT9& element) + : Stream(element.Stream), Type(element.Type), Method(element.Method), + Usage(element.Usage), UsageIndex(element.UsageIndex), Offset(element.Offset) {} + }; + + using D3D9CompactVertexElements = small_vector; + struct D3D9VertexDeclHash { - size_t operator () (const D3D9VertexElements& key) const; + size_t operator () (const D3D9CompactVertexElements& key) const; }; struct D3D9VertexDeclEq { - bool operator () (const D3D9VertexElements& a, const D3D9VertexElements& b) const; + bool operator () (const D3D9CompactVertexElements& a, const D3D9CompactVertexElements& b) const; }; class D3D9SWVPEmulator { public: - Rc GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexElements& elements); + Rc GetShaderModule(D3D9DeviceEx* pDevice, D3D9CompactVertexElements&& elements); private: dxvk::mutex m_mutex; std::unordered_map< - D3D9VertexElements, Rc, + D3D9CompactVertexElements, Rc, D3D9VertexDeclHash, D3D9VertexDeclEq> m_modules; };