aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs')
-rw-r--r--src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs b/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
index eab0f9d2..866ae522 100644
--- a/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
+++ b/src/Ryujinx.Graphics.Shader/Translation/Rewriter.cs
@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public static void RunPass(HelperFunctionManager hfm, BasicBlock[] blocks, ShaderConfig config)
{
bool isVertexShader = config.Stage == ShaderStage.Vertex;
+ bool isImpreciseFragmentShader = config.Stage == ShaderStage.Fragment && config.GpuAccessor.QueryHostReducedPrecision();
bool hasConstantBufferDrawParameters = config.GpuAccessor.QueryHasConstantBufferDrawParameters();
bool hasVectorIndexingBug = config.GpuAccessor.QueryHostHasVectorIndexingBug();
bool supportsSnormBufferTextureFormat = config.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat();
@@ -45,6 +46,11 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ if (isImpreciseFragmentShader)
+ {
+ EnableForcePreciseIfNeeded(operation);
+ }
+
if (hasVectorIndexingBug)
{
InsertVectorComponentSelect(node, config);
@@ -81,6 +87,25 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ private static void EnableForcePreciseIfNeeded(Operation operation)
+ {
+ // There are some cases where a small bias is added to values to prevent division by zero.
+ // When operating with reduced precision, it is possible for this bias to get rounded to 0
+ // and cause a division by zero.
+ // To prevent that, we force those operations to be precise even if the host wants
+ // imprecise operations for performance.
+
+ if (operation.Inst == (Instruction.FP32 | Instruction.Divide) &&
+ operation.GetSource(0).Type == OperandType.Constant &&
+ operation.GetSource(0).AsFloat() == 1f &&
+ operation.GetSource(1).AsgOp is Operation addOp &&
+ addOp.Inst == (Instruction.FP32 | Instruction.Add) &&
+ addOp.GetSource(1).Type == OperandType.Constant)
+ {
+ addOp.ForcePrecise = true;
+ }
+ }
+
private static void InsertVectorComponentSelect(LinkedListNode<INode> node, ShaderConfig config)
{
Operation operation = (Operation)node.Value;