1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-13 19:29:14 +01:00

[d3d9] Fix for missing mapping of VertexElements declarations to FVF bits

When Vertex declaration is created by CreateVertexDeclaration
and SetFVF is not called then GetFVF returns 0.
This code change implements mapping of D3D declarations to FVF mask
and sets it if FVF was not set previously.
This commit is contained in:
Krzysztof Dobrowolski 2022-09-22 10:41:40 +02:00 committed by GitHub
parent 82ebc29e18
commit 1e1ef8f1bd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 150 additions and 1 deletions

View File

@ -23,6 +23,7 @@ namespace dxvk {
, m_elements ( DeclCount )
, m_fvf ( 0 ) {
std::copy(pVertexElements, pVertexElements + DeclCount, m_elements.begin());
m_fvf = this->MapD3D9VertexElementsToFvf();
this->Classify();
}
@ -194,7 +195,7 @@ namespace dxvk {
for (uint32_t i = 0; i < elemCount; i++) {
elements[i].Stream = 0;
elements[i].Offset = (i == 0)
elements[i].Offset = (i == 0)
? 0
: (elements[i - 1].Offset + GetDecltypeSize(D3DDECLTYPE(elements[i - 1].Type)));
@ -205,6 +206,139 @@ namespace dxvk {
std::copy(elements.begin(), elements.begin() + elemCount, m_elements.data());
}
DWORD D3D9VertexDecl::MapD3DDeclToFvf(
const D3DVERTEXELEMENT9& element,
DWORD fvf,
DWORD& texCountPostUpdate) {
// Mapping between a Direct3D Declaration and FVF Codes (Direct3D 9)
// This table maps members of a D3DVERTEXELEMENT9 declaration to a FVF code.
//
// Data type Usage Usage index FVF
// ----------------------------------------------------------------------------------------
// D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_POSITION 0 D3DFVF_XYZ
// D3DDECLTYPE_FLOAT4 D3DDECLUSAGE_POSITIONT 0 D3DFVF_XYZRHW
// D3DDECLTYPE_FLOATn D3DDECLUSAGE_BLENDWEIGHT 0 D3DFVF_XYZBn
// D3DDECLTYPE_UBYTE4 D3DDECLUSAGE_BLENDINDICES 0 D3DFVF_XYZB(nWeights + 1)
// D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_NORMAL 0 D3DFVF_NORMAL
// D3DDECLTYPE_FLOAT1 D3DDECLUSAGE_PSIZE 0 D3DFVF_PSIZE
// D3DDECLTYPE_D3DCOLOR D3DDECLUSAGE_COLOR 0 D3DFVF_DIFFUSE
// D3DDECLTYPE_D3DCOLOR D3DDECLUSAGE_COLOR 1 D3DFVF_SPECULAR
// D3DDECLTYPE_FLOATm D3DDECLUSAGE_TEXCOORD n D3DFVF_TEXCOORDSIZEm(n)
// D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_POSITION 1 N / A
// D3DDECLTYPE_FLOAT3 D3DDECLUSAGE_NORMAL 1 N / A
if (element.Usage == D3DDECLUSAGE_POSITION && element.Type == D3DDECLTYPE_FLOAT3 && element.UsageIndex == 0)
return D3DFVF_XYZ;
else if (element.Usage == D3DDECLUSAGE_POSITIONT && element.Type == D3DDECLTYPE_FLOAT4 && element.UsageIndex == 0)
return D3DFVF_XYZRHW;
else if (element.Usage == D3DDECLUSAGE_BLENDWEIGHT && element.UsageIndex == 0) {
DWORD fvfRet = MapD3DDeclTypeFloatToFvfXYZBn(element.Type);
if (likely(fvfRet != 0))
return fvfRet;
else {
Logger::warn("D3D9VertexDecl::MapD3DDeclToFvf: Unsupported set of D3DDECLUSAGE_BLENDWEIGHT / D3DDECLTYPE_* / UsageIndex");
return 0;
}
}
else if (element.Usage == D3DDECLUSAGE_BLENDINDICES && element.Type == D3DDECLTYPE_UBYTE4 && element.UsageIndex == 0)
return D3DFVF_XYZB1;
else if (element.Usage == D3DDECLUSAGE_NORMAL && element.Type == D3DDECLTYPE_FLOAT3 && element.UsageIndex == 0)
return D3DFVF_NORMAL;
else if (element.Usage == D3DDECLUSAGE_PSIZE && element.Type == D3DDECLTYPE_FLOAT1 && element.UsageIndex == 0)
return D3DFVF_PSIZE;
else if (element.Usage == D3DDECLUSAGE_COLOR && element.Type == D3DDECLTYPE_D3DCOLOR) {
switch (element.UsageIndex)
{
case 0:
return D3DFVF_DIFFUSE;
case 1:
return D3DFVF_SPECULAR;
default:;
Logger::warn("D3D9VertexDecl::MapD3DDeclToFvf: Unsupported set of D3DDECLUSAGE_COLOR / D3DDECLTYPE_D3DCOLOR / UsageIndex");
return 0;
}
}
else if (element.Usage == D3DDECLUSAGE_TEXCOORD && element.UsageIndex < 8) {
DWORD retFvf = 0;
if (likely(MapD3DDeclUsageTexCoordToFvfTexCoordSize(element, fvf, retFvf, texCountPostUpdate)))
return retFvf;
else {
Logger::warn("D3D9VertexDecl::MapD3DDeclToFvf: Unsupported set of D3DDECLUSAGE_TEXCOORD / D3DDECLTYPE_* / UsageIndex");
return 0;
}
}
Logger::warn("D3D9VertexDecl::MapD3DDeclToFvf: Unsupported set of D3DDECLUSAGE_* / D3DDECLTYPE_* / UsageIndex");
return 0;
}
DWORD D3D9VertexDecl::MapD3DDeclTypeFloatToFvfXYZBn(BYTE type) {
switch (type)
{
default:;
return 0;
case D3DDECLTYPE_FLOAT1:
return D3DFVF_XYZB1;
case D3DDECLTYPE_FLOAT2:
return D3DFVF_XYZB2;
case D3DDECLTYPE_FLOAT3:
return D3DFVF_XYZB3;
case D3DDECLTYPE_FLOAT4:
return D3DFVF_XYZB4;
}
}
bool D3D9VertexDecl::MapD3DDeclUsageTexCoordToFvfTexCoordSize(
const D3DVERTEXELEMENT9& element,
DWORD fvf,
DWORD& outFvf,
DWORD& texCountPostUpdate) {
// Check if bits of format for current UsageIndex are free in the fvf
// It is necessary to skip multiple initializations of the bitfield because
// returned value is bitwise or-ed to final fvf DWORD.
// The D3DFVF_TEXCOORDSIZE1 is used below because it covers all formats bits.
if ((D3DFVF_TEXCOORDSIZE1(element.UsageIndex) & fvf) != 0)
return false;
// Update max texture's index in fvf
DWORD currentTexCount = element.UsageIndex + 1;
bool retStatus = true;
if (texCountPostUpdate < currentTexCount)
texCountPostUpdate = currentTexCount;
if (element.Type == D3DDECLTYPE_FLOAT1)
outFvf = D3DFVF_TEXCOORDSIZE1(element.UsageIndex);
else if (element.Type == D3DDECLTYPE_FLOAT2)
outFvf = D3DFVF_TEXCOORDSIZE2(element.UsageIndex);
else if (element.Type == D3DDECLTYPE_FLOAT3)
outFvf = D3DFVF_TEXCOORDSIZE3(element.UsageIndex);
else if (element.Type == D3DDECLTYPE_FLOAT4)
outFvf = D3DFVF_TEXCOORDSIZE4(element.UsageIndex);
else
retStatus = false;
return retStatus;
}
DWORD D3D9VertexDecl::MapD3D9VertexElementsToFvf() {
DWORD fvf = 0;
DWORD texCountPostUpdate = 0;
for (const auto& element : m_elements)
fvf |= MapD3DDeclToFvf(element, fvf, texCountPostUpdate);
fvf |= (texCountPostUpdate << 8);
return fvf;
}
void D3D9VertexDecl::Classify() {
for (const auto& element : m_elements) {

View File

@ -68,6 +68,21 @@ namespace dxvk {
private:
DWORD MapD3DDeclToFvf(
const D3DVERTEXELEMENT9& element,
DWORD fvf,
DWORD& texCountPostUpdate);
DWORD MapD3D9VertexElementsToFvf();
DWORD MapD3DDeclTypeFloatToFvfXYZBn(BYTE type);
bool MapD3DDeclUsageTexCoordToFvfTexCoordSize(
const D3DVERTEXELEMENT9& element,
DWORD fvf,
DWORD& outFvf,
DWORD& texCountPostUpdate);
void Classify();
D3D9VertexDeclFlags m_flags;