Skip to content

Commit

Permalink
[d3d9] Reduce data copied for SWVP vertex decls
Browse files Browse the repository at this point in the history
  • Loading branch information
K0bin committed Apr 23, 2024
1 parent 260ec73 commit 6a1cd59
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 15 deletions.
9 changes: 7 additions & 2 deletions src/d3d9/d3d9_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
22 changes: 13 additions & 9 deletions src/d3d9/d3d9_swvp_emu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand All @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)));
}
Expand All @@ -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 };

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
}
Expand Down
23 changes: 19 additions & 4 deletions src/d3d9/d3d9_swvp_emu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

};
Expand Down

0 comments on commit 6a1cd59

Please sign in to comment.