diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs index ec133272..f013ee10 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Instructions/InstGenHelper.cs @@ -50,6 +50,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions Add(Instruction.CompareNotEqual, InstType.OpBinaryCom, "!=", 5); Add(Instruction.ConditionalSelect, InstType.OpTernary, "?:", 12); Add(Instruction.ConvertFPToS32, InstType.CallUnary, "int"); + Add(Instruction.ConvertFPToU32, InstType.CallUnary, "uint"); Add(Instruction.ConvertS32ToFP, InstType.CallUnary, "float"); Add(Instruction.ConvertU32ToFP, InstType.CallUnary, "float"); Add(Instruction.Cosine, InstType.CallUnary, "cos"); diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index b1524152..8c06a24b 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -99,12 +99,26 @@ namespace Ryujinx.Graphics.Shader.Instructions break; } - long min = GetIntMin(intType); - long max = GetIntMax(intType); + if (!isSignedInt) + { + // Negative float to uint cast is undefined, so we clamp + // the value before conversion. + srcB = context.FPMaximum(srcB, ConstF(0)); + } - srcB = context.FPClamp(srcB, ConstF(min), ConstF(max)); + srcB = isSignedInt + ? context.FPConvertToS32(srcB) + : context.FPConvertToU32(srcB); - srcB = context.FPConvertToS32(srcB); + if (isSmallInt) + { + int min = (int)GetIntMin(intType); + int max = (int)GetIntMax(intType); + + srcB = isSignedInt + ? context.IClampS32(srcB, Const(min), Const(max)) + : context.IClampU32(srcB, Const(min), Const(max)); + } Operand dest = GetDest(context); diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs index d99e3f2b..6acaa490 100644 --- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs +++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Instruction.cs @@ -46,6 +46,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation CompareNotEqual, ConditionalSelect, ConvertFPToS32, + ConvertFPToU32, ConvertS32ToFP, ConvertU32ToFP, Copy, diff --git a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs index 55c0d977..4c456d7b 100644 --- a/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs +++ b/Ryujinx.Graphics.Shader/StructuredIr/InstructionInfo.cs @@ -64,6 +64,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Add(Instruction.CompareNotEqual, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); Add(Instruction.ConditionalSelect, VariableType.Scalar, VariableType.Bool, VariableType.Scalar, VariableType.Scalar); Add(Instruction.ConvertFPToS32, VariableType.S32, VariableType.F32); + Add(Instruction.ConvertFPToU32, VariableType.U32, VariableType.F32); Add(Instruction.ConvertS32ToFP, VariableType.F32, VariableType.S32); Add(Instruction.ConvertU32ToFP, VariableType.F32, VariableType.U32); Add(Instruction.Cosine, VariableType.Scalar, VariableType.Scalar); diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs index c55e3430..df8867e9 100644 --- a/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs +++ b/Ryujinx.Graphics.Shader/Translation/EmitterContextInsts.cs @@ -206,11 +206,6 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.FP | Instruction.Ceiling, Local(), a); } - public static Operand FPClamp(this EmitterContext context, Operand a, Operand b, Operand c) - { - return context.Add(Instruction.FP | Instruction.Clamp, Local(), a, b, c); - } - public static Operand FPCompareEqual(this EmitterContext context, Operand a, Operand b) { return context.Add(Instruction.FP | Instruction.CompareEqual, Local(), a, b); @@ -226,6 +221,11 @@ namespace Ryujinx.Graphics.Shader.Translation return context.Add(Instruction.ConvertFPToS32, Local(), a); } + public static Operand FPConvertToU32(this EmitterContext context, Operand a) + { + return context.Add(Instruction.ConvertFPToU32, Local(), a); + } + public static Operand FPCosine(this EmitterContext context, Operand a) { return context.Add(Instruction.FP | Instruction.Cosine, Local(), a);