[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>();
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<DxvkShader> shader = m_swvpEmulator.GetShaderModule(this, cVertexElements);
Rc<DxvkShader> shader = m_swvpEmulator.GetShaderModule(this, std::move(cVertexElements));
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.
size_t D3D9VertexDeclHash::operator () (const D3D9VertexElements& key) const {
size_t D3D9VertexDeclHash::operator () (const D3D9CompactVertexElements& key) const {
DxvkHashState hash;
std::hash<BYTE> bytehash;
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.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<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
{ std::unique_lock<dxvk::mutex> lock(m_mutex);
@ -343,7 +346,8 @@ namespace dxvk {
// that object instead and discard the newly created module.
{ 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)
return status.first->second;
}

View File

@ -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<D3D9CompactVertexElement, 4>;
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<DxvkShader> GetShaderModule(D3D9DeviceEx* pDevice, const D3D9VertexElements& elements);
Rc<DxvkShader> GetShaderModule(D3D9DeviceEx* pDevice, D3D9CompactVertexElements&& elements);
private:
dxvk::mutex m_mutex;
std::unordered_map<
D3D9VertexElements, Rc<DxvkShader>,
D3D9CompactVertexElements, Rc<DxvkShader>,
D3D9VertexDeclHash, D3D9VertexDeclEq> m_modules;
};