Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[d3d9] FF: Apply transform flags count to generated texture coords #4026

Merged
merged 1 commit into from
May 27, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 31 additions & 24 deletions src/d3d9/d3d9_fixed_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1139,12 +1139,12 @@ namespace dxvk {

case (DXVK_TSS_TCI_CAMERASPACENORMAL >> TCIOffset):
transformed = outNrm;
count = 4;
count = std::min(flags, 4u);
break;

case (DXVK_TSS_TCI_CAMERASPACEPOSITION >> TCIOffset):
transformed = m_module.opCompositeInsert(m_vec4Type, m_module.constf32(1.0f), vtx, 1, &wIndex);
count = 4;
count = std::min(flags, 4u);
break;

case (DXVK_TSS_TCI_CAMERASPACEREFLECTIONVECTOR >> TCIOffset): {
Expand All @@ -1159,7 +1159,7 @@ namespace dxvk {
transformIndices[3] = m_module.constf32(1.0f);

transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data());
count = 4;
count = std::min(flags, 4u);
break;
}

Expand All @@ -1183,36 +1183,43 @@ namespace dxvk {
transformIndices[3] = m_module.constf32(1.0f);

transformed = m_module.opCompositeConstruct(m_vec4Type, transformIndices.size(), transformIndices.data());
count = 4;
count = std::min(flags, 4u);
break;
}
}

if (applyTransform || (count != 4 && count != 0)) {
if (applyTransform && !m_vsKey.Data.Contents.HasPositionT) {
for (uint32_t j = count; j < 4; j++) {
// If we're outside the component count of the vertex decl for this texcoord then we pad with zeroes.
// Otherwise, pad with ones.

// Very weird quirk in order to get texcoord transforms to work like they do in native.
// In future, maybe we could sort this out properly by chopping matrices of different sizes, but thats
// a project for another day.
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (3 * inputIndex)) & 0x7;
uint32_t value = j > texcoordCount ? m_module.constf32(0) : m_module.constf32(1);
transformed = m_module.opCompositeInsert(m_vec4Type, value, transformed, 1, &j);
}

transformed = m_module.opVectorTimesMatrix(m_vec4Type, transformed, m_vs.constants.texcoord[i]);
if (applyTransform && !m_vsKey.Data.Contents.HasPositionT) {
for (uint32_t j = count; j < 4; j++) {
// If we're outside the component count of the vertex decl for this texcoord then we pad with zeroes.
// Otherwise, pad with ones.

// Very weird quirk in order to get texcoord transforms to work like they do in native.
// In future, maybe we could sort this out properly by chopping matrices of different sizes, but thats
// a project for another day.
uint32_t texcoordCount = (m_vsKey.Data.Contents.TexcoordDeclMask >> (3 * inputIndex)) & 0x7;
uint32_t value = j > texcoordCount ? m_module.constf32(0) : m_module.constf32(1);
transformed = m_module.opCompositeInsert(m_vec4Type, value, transformed, 1, &j);
}

// Pad the unused section of it with the value for projection.
uint32_t projIdx = std::max(2u, count - 1);
uint32_t projValue = m_module.opCompositeExtract(m_floatType, transformed, 1, &projIdx);
transformed = m_module.opVectorTimesMatrix(m_vec4Type, transformed, m_vs.constants.texcoord[i]);
}

for (uint32_t j = count; j < 4; j++)
transformed = m_module.opCompositeInsert(m_vec4Type, projValue, transformed, 1, &j);
// The projection idx is always based on the flags, even when the input mode is not DXVK_TSS_TCI_PASSTHRU.
uint32_t projValue;
if (count < 3) {
// Not enough components to do projection.
// Native drivers render normally or garbage with D3DFVF_TEXCOORDSIZE2 or D3DTTFF_COUNT <3
projValue = m_module.constf32(1.0f);
} else {
uint32_t projIdx = count - 1;
projValue = m_module.opCompositeExtract(m_floatType, transformed, 1, &projIdx);
}

// The w component is only used for projection or unused, so always insert the component that's supposed to be divided by there.
// The fragment shader will then decide whether to project or not.
uint32_t wIdx = 3;
transformed = m_module.opCompositeInsert(m_vec4Type, projValue, transformed, 1, &wIdx);

m_module.opStore(m_vs.out.TEXCOORD[i], transformed);
}

Expand Down
Loading