[d3d9] Reduce data copied for SWVP vertex decls

This commit is contained in:
Robin Kertels 2024-03-13 15:49:46 +01:00
parent 260ec73b37
commit 6a1cd595a5
No known key found for this signature in database
GPG Key ID: 3824904F14D40757
3 changed files with 39 additions and 15 deletions

View File

@ -2946,14 +2946,19 @@ namespace dxvk {
auto slice = dst->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>(); auto slice = dst->GetBufferSlice<D3D9_COMMON_BUFFER_TYPE_REAL>();
slice = slice.subSlice(offset, slice.length() - offset); slice = slice.subSlice(offset, slice.length() - offset);
D3D9CompactVertexElements elements;
for (const D3DVERTEXELEMENT9& element : decl->GetElements()) {
elements.emplace_back(element);
}
EmitCs([this, EmitCs([this,
cVertexElements = decl->GetElements(), cVertexElements = std::move(elements),
cVertexCount = VertexCount, cVertexCount = VertexCount,
cStartIndex = SrcStartIndex, cStartIndex = SrcStartIndex,
cInstanceCount = GetInstanceCount(), cInstanceCount = GetInstanceCount(),
cBufferSlice = slice cBufferSlice = slice
](DxvkContext* ctx) mutable { ](DxvkContext* ctx) mutable {
Rc<DxvkShader> shader = m_swvpEmulator.GetShaderModule(this, cVertexElements); Rc<DxvkShader> shader = m_swvpEmulator.GetShaderModule(this, std::move(cVertexElements));
auto drawInfo = GenerateDrawInfo(D3DPT_POINTLIST, cVertexCount, cInstanceCount); auto drawInfo = GenerateDrawInfo(D3DPT_POINTLIST, cVertexCount, cInstanceCount);

View File

@ -9,13 +9,14 @@ namespace dxvk {
// Doesn't compare everything, only what we use in SWVP. // 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; DxvkHashState hash;
std::hash<BYTE> bytehash; std::hash<BYTE> bytehash;
std::hash<WORD> wordhash; std::hash<WORD> 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.Stream));
hash.add(wordhash(element.Offset)); hash.add(wordhash(element.Offset));
hash.add(bytehash(element.Type)); hash.add(bytehash(element.Type));
@ -27,7 +28,7 @@ namespace dxvk {
return hash; 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()) if (a.size() != b.size())
return false; return false;
@ -109,7 +110,7 @@ namespace dxvk {
m_module.opLabel(m_module.allocateId()); 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 uint_t = m_module.defIntType(32, false);
uint32_t float_t = m_module.defFloatType(32); uint32_t float_t = m_module.defFloatType(32);
uint32_t vec4_t = m_module.defVectorType(float_t, 4); 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); uint32_t primitiveId = m_module.opLoad(uint_t, primitiveIdPtr);
// The size of any given vertex // The size of any given vertex
uint32_t size = 0; uint32_t size = 0;
for (const auto& element : elements) { for (uint32_t i = 0; i < elements.size(); i++) {
const auto& element = elements[i];
if (element.Stream == 0 && element.Type != D3DDECLTYPE_UNUSED) { if (element.Stream == 0 && element.Type != D3DDECLTYPE_UNUSED) {
size = std::max(size, element.Offset + GetDecltypeSize(D3DDECLTYPE(element.Type))); 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); 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 // Load the slot associated with this element
DxsoSemantic semantic = { DxsoUsage(element.Usage), element.UsageIndex }; DxsoSemantic semantic = { DxsoUsage(element.Usage), element.UsageIndex };
@ -304,7 +307,7 @@ namespace dxvk {
}; };
Rc<DxvkShader> D3D9SWVPEmulator::GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexElements& elements) { Rc<DxvkShader> D3D9SWVPEmulator::GetShaderModule(D3D9DeviceEx* pDevice, D3D9CompactVertexElements&& elements) {
// Use the shader's unique key for the lookup // Use the shader's unique key for the lookup
{ std::unique_lock<dxvk::mutex> lock(m_mutex); { std::unique_lock<dxvk::mutex> lock(m_mutex);
@ -343,7 +346,8 @@ namespace dxvk {
// that object instead and discard the newly created module. // that object instead and discard the newly created module.
{ std::unique_lock<dxvk::mutex> lock(m_mutex); { std::unique_lock<dxvk::mutex> lock(m_mutex);
auto status = m_modules.insert({ elements, shader }); std::pair<D3D9CompactVertexElements, Rc<DxvkShader>> pair = { std::move(elements), shader };
auto status = m_modules.insert(std::move(pair));
if (!status.second) if (!status.second)
return status.first->second; return status.first->second;
} }

View File

@ -11,26 +11,41 @@ namespace dxvk {
class D3D9VertexDecl; class D3D9VertexDecl;
class D3D9DeviceEx; 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<D3D9CompactVertexElement, 4>;
struct D3D9VertexDeclHash { struct D3D9VertexDeclHash {
size_t operator () (const D3D9VertexElements& key) const; size_t operator () (const D3D9CompactVertexElements& key) const;
}; };
struct D3D9VertexDeclEq { struct D3D9VertexDeclEq {
bool operator () (const D3D9VertexElements& a, const D3D9VertexElements& b) const; bool operator () (const D3D9CompactVertexElements& a, const D3D9CompactVertexElements& b) const;
}; };
class D3D9SWVPEmulator { class D3D9SWVPEmulator {
public: public:
Rc<DxvkShader> GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexElements& elements); Rc<DxvkShader> GetShaderModule(D3D9DeviceEx* pDevice, D3D9CompactVertexElements&& elements);
private: private:
dxvk::mutex m_mutex; dxvk::mutex m_mutex;
std::unordered_map< std::unordered_map<
D3D9VertexElements, Rc<DxvkShader>, D3D9CompactVertexElements, Rc<DxvkShader>,
D3D9VertexDeclHash, D3D9VertexDeclEq> m_modules; D3D9VertexDeclHash, D3D9VertexDeclEq> m_modules;
}; };