|
@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|
|
public static void RunPass(HelperFunctionManager hfm, BasicBlock[] blocks, ShaderConfig config)
|
|
public static void RunPass(HelperFunctionManager hfm, BasicBlock[] blocks, ShaderConfig config)
|
|
|
{
|
|
{
|
|
|
bool isVertexShader = config.Stage == ShaderStage.Vertex;
|
|
bool isVertexShader = config.Stage == ShaderStage.Vertex;
|
|
|
|
|
+ bool isImpreciseFragmentShader = config.Stage == ShaderStage.Fragment && config.GpuAccessor.QueryHostReducedPrecision();
|
|
|
bool hasConstantBufferDrawParameters = config.GpuAccessor.QueryHasConstantBufferDrawParameters();
|
|
bool hasConstantBufferDrawParameters = config.GpuAccessor.QueryHasConstantBufferDrawParameters();
|
|
|
bool hasVectorIndexingBug = config.GpuAccessor.QueryHostHasVectorIndexingBug();
|
|
bool hasVectorIndexingBug = config.GpuAccessor.QueryHostHasVectorIndexingBug();
|
|
|
bool supportsSnormBufferTextureFormat = config.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat();
|
|
bool supportsSnormBufferTextureFormat = config.GpuAccessor.QueryHostSupportsSnormBufferTextureFormat();
|
|
@@ -45,6 +46,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (isImpreciseFragmentShader)
|
|
|
|
|
+ {
|
|
|
|
|
+ EnableForcePreciseIfNeeded(operation);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if (hasVectorIndexingBug)
|
|
if (hasVectorIndexingBug)
|
|
|
{
|
|
{
|
|
|
InsertVectorComponentSelect(node, config);
|
|
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)
|
|
private static void InsertVectorComponentSelect(LinkedListNode<INode> node, ShaderConfig config)
|
|
|
{
|
|
{
|
|
|
Operation operation = (Operation)node.Value;
|
|
Operation operation = (Operation)node.Value;
|