From e4bca7a42f5754c3851199a3db91a3b94296b560 Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Sat, 26 Sep 2020 06:03:22 +0100 Subject: [PATCH] [d3d9] Handle specular fog factor for fixed function Also handle POSITION_T shenanigans Closes #1771 --- src/d3d9/d3d9_fixed_function.cpp | 135 +++++++++++++++++-------------- src/d3d9/d3d9_fixed_function.h | 5 ++ src/dxso/dxso_compiler.cpp | 4 + 3 files changed, 85 insertions(+), 59 deletions(-) diff --git a/src/d3d9/d3d9_fixed_function.cpp b/src/d3d9/d3d9_fixed_function.cpp index ecd8b96ab..75047fcf5 100644 --- a/src/d3d9/d3d9_fixed_function.cpp +++ b/src/d3d9/d3d9_fixed_function.cpp @@ -91,74 +91,83 @@ namespace dxvk { ? fogCtx.vFog : 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 fogVariables; - std::array fogVariables; + std::array 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 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() }, - } }; + spvModule.opSelectionMerge(applyFogFactor, spv::SelectionControlMaskNone); + spvModule.opSwitch(fogMode, + fogCaseLabels[D3DFOG_NONE].labelId, + fogCaseLabels.size(), + fogCaseLabels.data()); - - spvModule.opSelectionMerge(applyFogFactor, spv::SelectionControlMaskNone); - spvModule.opSwitch(fogMode, - fogCaseLabels[D3DFOG_NONE].labelId, - fogCaseLabels.size(), - fogCaseLabels.data()); - - for (uint32_t i = 0; i < fogCaseLabels.size(); i++) { - spvModule.opLabel(fogCaseLabels[i].labelId); + for (uint32_t i = 0; i < fogCaseLabels.size(); i++) { + spvModule.opLabel(fogCaseLabels[i].labelId); - fogVariables[i].labelId = fogCaseLabels[i].labelId; - fogVariables[i].varId = [&] { - auto mode = D3DFOGMODE(fogCaseLabels[i].literal); - switch (mode) { - default: - // vFog - case D3DFOG_NONE: { - return fogCtx.IsPixel - ? fogCtx.vFog - : spvModule.constf32(1.0f); + fogVariables[i].labelId = fogCaseLabels[i].labelId; + fogVariables[i].varId = [&] { + auto mode = D3DFOGMODE(fogCaseLabels[i].literal); + switch (mode) { + default: + // vFog + case D3DFOG_NONE: { + if (fogCtx.IsPixel) + return fogCtx.vFog; + + if (fogCtx.IsFixedFunction && fogCtx.HasSpecular) + return spvModule.opCompositeExtract(floatType, fogCtx.Specular, 1, &wIndex); + + return spvModule.constf32(1.0f); + } + + // (end - d) / (end - start) + 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 + 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) - 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 - 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; - } - } - }(); + }(); - spvModule.opBranch(applyFogFactor); + spvModule.opBranch(applyFogFactor); + } + + spvModule.opLabel(applyFogFactor); + + fogFactor = spvModule.opPhi(floatType, + fogVariables.size(), + fogVariables.data()); } - spvModule.opLabel(applyFogFactor); - - uint32_t fogFactor = spvModule.opPhi(floatType, - fogVariables.size(), - fogVariables.data()); - uint32_t fogRetValue = 0; // 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.vFog = m_vs.in.FOG; 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)); 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.vFog = m_ps.in.FOG; fogCtx.oColor = current; + fogCtx.IsFixedFunction = true; + fogCtx.IsPositionT = false; + fogCtx.HasSpecular = false; + fogCtx.Specular = 0; current = DoFixedFunctionFog(m_module, fogCtx); m_module.opStore(m_ps.out.COLOR, current); diff --git a/src/d3d9/d3d9_fixed_function.h b/src/d3d9/d3d9_fixed_function.h index f839e12e8..49b00d180 100644 --- a/src/d3d9/d3d9_fixed_function.h +++ b/src/d3d9/d3d9_fixed_function.h @@ -29,6 +29,11 @@ namespace dxvk { uint32_t oColor; bool HasFogInput; + + bool IsFixedFunction; + bool IsPositionT; + bool HasSpecular; + uint32_t Specular; }; struct D3D9FixedFunctionOptions { diff --git a/src/dxso/dxso_compiler.cpp b/src/dxso/dxso_compiler.cpp index 92d0d7d3d..7199ed40e 100644 --- a/src/dxso/dxso_compiler.cpp +++ b/src/dxso/dxso_compiler.cpp @@ -3521,6 +3521,10 @@ void DxsoCompiler::emitControlFlowGenericLoop( fogCtx.vPos = m_module.opLoad(getVectorTypeId(vPosPtr.type), vPosPtr.id); fogCtx.vFog = m_module.opLoad(getVectorTypeId(vFogPtr.type), vFogPtr.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)); }