1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-19 05:52:11 +01:00

[d3d9] Handle specular fog factor for fixed function

Also handle POSITION_T shenanigans

Closes #1771
This commit is contained in:
Joshua Ashton 2020-09-26 06:03:22 +01:00
parent dc392f7cfa
commit e4bca7a42f
3 changed files with 85 additions and 59 deletions

View File

@ -91,74 +91,83 @@ namespace dxvk {
? fogCtx.vFog ? fogCtx.vFog
: spvModule.opFAbs(floatType, z); : spvModule.opFAbs(floatType, z);
} }
uint32_t fogFactor;
if (!fogCtx.IsPixel && fogCtx.IsFixedFunction && fogCtx.IsPositionT) {
fogFactor = fogCtx.HasSpecular
? spvModule.opCompositeExtract(floatType, fogCtx.Specular, 1, &wIndex)
: spvModule.constf32(1.0f);
} else {
uint32_t applyFogFactor = spvModule.allocateId();
uint32_t applyFogFactor = spvModule.allocateId(); std::array<SpirvPhiLabel, 4> fogVariables;
std::array<SpirvPhiLabel, 4> fogVariables; std::array<SpirvSwitchCaseLabel, 4> fogCaseLabels = { {
{ uint32_t(D3DFOG_NONE), spvModule.allocateId() },
{ uint32_t(D3DFOG_EXP), spvModule.allocateId() },
{ uint32_t(D3DFOG_EXP2), spvModule.allocateId() },
{ uint32_t(D3DFOG_LINEAR), spvModule.allocateId() },
} };
std::array<SpirvSwitchCaseLabel, 4> fogCaseLabels = { { spvModule.opSelectionMerge(applyFogFactor, spv::SelectionControlMaskNone);
{ uint32_t(D3DFOG_NONE), spvModule.allocateId() }, spvModule.opSwitch(fogMode,
{ uint32_t(D3DFOG_EXP), spvModule.allocateId() }, fogCaseLabels[D3DFOG_NONE].labelId,
{ uint32_t(D3DFOG_EXP2), spvModule.allocateId() }, fogCaseLabels.size(),
{ uint32_t(D3DFOG_LINEAR), spvModule.allocateId() }, fogCaseLabels.data());
} };
for (uint32_t i = 0; i < fogCaseLabels.size(); i++) {
spvModule.opLabel(fogCaseLabels[i].labelId);
spvModule.opSelectionMerge(applyFogFactor, spv::SelectionControlMaskNone); fogVariables[i].labelId = fogCaseLabels[i].labelId;
spvModule.opSwitch(fogMode, fogVariables[i].varId = [&] {
fogCaseLabels[D3DFOG_NONE].labelId, auto mode = D3DFOGMODE(fogCaseLabels[i].literal);
fogCaseLabels.size(), switch (mode) {
fogCaseLabels.data()); default:
// vFog
case D3DFOG_NONE: {
if (fogCtx.IsPixel)
return fogCtx.vFog;
for (uint32_t i = 0; i < fogCaseLabels.size(); i++) { if (fogCtx.IsFixedFunction && fogCtx.HasSpecular)
spvModule.opLabel(fogCaseLabels[i].labelId); return spvModule.opCompositeExtract(floatType, fogCtx.Specular, 1, &wIndex);
fogVariables[i].labelId = fogCaseLabels[i].labelId; return spvModule.constf32(1.0f);
fogVariables[i].varId = [&] { }
auto mode = D3DFOGMODE(fogCaseLabels[i].literal);
switch (mode) { // (end - d) / (end - start)
default: case D3DFOG_LINEAR: {
// vFog uint32_t fogFactor = spvModule.opFSub(floatType, fogEnd, depth);
case D3DFOG_NONE: { fogFactor = spvModule.opFMul(floatType, fogFactor, fogScale);
return fogCtx.IsPixel fogFactor = spvModule.opNClamp(floatType, fogFactor, spvModule.constf32(0.0f), spvModule.constf32(1.0f));
? fogCtx.vFog return fogFactor;
: spvModule.constf32(1.0f); }
// 1 / (e^[d * density])^2
case D3DFOG_EXP2:
// 1 / (e^[d * density])
case D3DFOG_EXP: {
uint32_t fogFactor = spvModule.opFMul(floatType, depth, fogDensity);
if (mode == D3DFOG_EXP2)
fogFactor = spvModule.opFMul(floatType, fogFactor, fogFactor);
// Provides the rcp.
fogFactor = spvModule.opFNegate(floatType, fogFactor);
fogFactor = spvModule.opExp(floatType, fogFactor);
return fogFactor;
}
} }
}();
// (end - d) / (end - start) spvModule.opBranch(applyFogFactor);
case D3DFOG_LINEAR: { }
uint32_t fogFactor = spvModule.opFSub(floatType, fogEnd, depth);
fogFactor = spvModule.opFMul(floatType, fogFactor, fogScale);
fogFactor = spvModule.opNClamp(floatType, fogFactor, spvModule.constf32(0.0f), spvModule.constf32(1.0f));
return fogFactor;
}
// 1 / (e^[d * density])^2 spvModule.opLabel(applyFogFactor);
case D3DFOG_EXP2:
// 1 / (e^[d * density])
case D3DFOG_EXP: {
uint32_t fogFactor = spvModule.opFMul(floatType, depth, fogDensity);
if (mode == D3DFOG_EXP2) fogFactor = spvModule.opPhi(floatType,
fogFactor = spvModule.opFMul(floatType, fogFactor, fogFactor); fogVariables.size(),
fogVariables.data());
// Provides the rcp.
fogFactor = spvModule.opFNegate(floatType, fogFactor);
fogFactor = spvModule.opExp(floatType, fogFactor);
return fogFactor;
}
}
}();
spvModule.opBranch(applyFogFactor);
} }
spvModule.opLabel(applyFogFactor);
uint32_t fogFactor = spvModule.opPhi(floatType,
fogVariables.size(),
fogVariables.data());
uint32_t fogRetValue = 0; uint32_t fogRetValue = 0;
// Return the new color if we are doing this in PS // Return the new color if we are doing this in PS
@ -1156,6 +1165,10 @@ namespace dxvk {
fogCtx.HasFogInput = m_vsKey.Data.Contents.HasFog; fogCtx.HasFogInput = m_vsKey.Data.Contents.HasFog;
fogCtx.vFog = m_vs.in.FOG; fogCtx.vFog = m_vs.in.FOG;
fogCtx.oColor = 0; fogCtx.oColor = 0;
fogCtx.IsFixedFunction = true;
fogCtx.IsPositionT = m_vsKey.Data.Contents.HasPositionT;
fogCtx.HasSpecular = m_vsKey.Data.Contents.HasColor1;
fogCtx.Specular = m_vs.in.COLOR[1];
m_module.opStore(m_vs.out.FOG, DoFixedFunctionFog(m_module, fogCtx)); m_module.opStore(m_vs.out.FOG, DoFixedFunctionFog(m_module, fogCtx));
auto pointInfo = GetPointSizeInfoVS(m_module, 0, vtx, m_vs.in.POINTSIZE, m_rsBlock); auto pointInfo = GetPointSizeInfoVS(m_module, 0, vtx, m_vs.in.POINTSIZE, m_rsBlock);
@ -1942,6 +1955,10 @@ namespace dxvk {
fogCtx.vPos = m_ps.in.POS; fogCtx.vPos = m_ps.in.POS;
fogCtx.vFog = m_ps.in.FOG; fogCtx.vFog = m_ps.in.FOG;
fogCtx.oColor = current; fogCtx.oColor = current;
fogCtx.IsFixedFunction = true;
fogCtx.IsPositionT = false;
fogCtx.HasSpecular = false;
fogCtx.Specular = 0;
current = DoFixedFunctionFog(m_module, fogCtx); current = DoFixedFunctionFog(m_module, fogCtx);
m_module.opStore(m_ps.out.COLOR, current); m_module.opStore(m_ps.out.COLOR, current);

View File

@ -29,6 +29,11 @@ namespace dxvk {
uint32_t oColor; uint32_t oColor;
bool HasFogInput; bool HasFogInput;
bool IsFixedFunction;
bool IsPositionT;
bool HasSpecular;
uint32_t Specular;
}; };
struct D3D9FixedFunctionOptions { struct D3D9FixedFunctionOptions {

View File

@ -3521,6 +3521,10 @@ void DxsoCompiler::emitControlFlowGenericLoop(
fogCtx.vPos = m_module.opLoad(getVectorTypeId(vPosPtr.type), vPosPtr.id); fogCtx.vPos = m_module.opLoad(getVectorTypeId(vPosPtr.type), vPosPtr.id);
fogCtx.vFog = m_module.opLoad(getVectorTypeId(vFogPtr.type), vFogPtr.id); fogCtx.vFog = m_module.opLoad(getVectorTypeId(vFogPtr.type), vFogPtr.id);
fogCtx.oColor = m_module.opLoad(getVectorTypeId(oColor0Ptr.type), oColor0Ptr.id); fogCtx.oColor = m_module.opLoad(getVectorTypeId(oColor0Ptr.type), oColor0Ptr.id);
fogCtx.IsFixedFunction = false;
fogCtx.IsPositionT = false;
fogCtx.HasSpecular = false;
fogCtx.Specular = 0;
m_module.opStore(oColor0Ptr.id, DoFixedFunctionFog(m_module, fogCtx)); m_module.opStore(oColor0Ptr.id, DoFixedFunctionFog(m_module, fogCtx));
} }