Fix shader integer from/to double conversion (#2831)
This commit is contained in:
parent
788aec511f
commit
b9d83cc97e
7 changed files with 90 additions and 34 deletions
|
@ -53,10 +53,14 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions
|
||||||
Add(Instruction.ConditionalSelect, InstType.OpTernary, "?:", 12);
|
Add(Instruction.ConditionalSelect, InstType.OpTernary, "?:", 12);
|
||||||
Add(Instruction.ConvertFP32ToFP64, InstType.CallUnary, "double");
|
Add(Instruction.ConvertFP32ToFP64, InstType.CallUnary, "double");
|
||||||
Add(Instruction.ConvertFP64ToFP32, InstType.CallUnary, "float");
|
Add(Instruction.ConvertFP64ToFP32, InstType.CallUnary, "float");
|
||||||
Add(Instruction.ConvertFPToS32, InstType.CallUnary, "int");
|
Add(Instruction.ConvertFP32ToS32, InstType.CallUnary, "int");
|
||||||
Add(Instruction.ConvertFPToU32, InstType.CallUnary, "uint");
|
Add(Instruction.ConvertFP32ToU32, InstType.CallUnary, "uint");
|
||||||
Add(Instruction.ConvertS32ToFP, InstType.CallUnary, "float");
|
Add(Instruction.ConvertFP64ToS32, InstType.CallUnary, "int");
|
||||||
Add(Instruction.ConvertU32ToFP, InstType.CallUnary, "float");
|
Add(Instruction.ConvertFP64ToU32, InstType.CallUnary, "uint");
|
||||||
|
Add(Instruction.ConvertS32ToFP32, InstType.CallUnary, "float");
|
||||||
|
Add(Instruction.ConvertS32ToFP64, InstType.CallUnary, "double");
|
||||||
|
Add(Instruction.ConvertU32ToFP32, InstType.CallUnary, "float");
|
||||||
|
Add(Instruction.ConvertU32ToFP64, InstType.CallUnary, "double");
|
||||||
Add(Instruction.Cosine, InstType.CallUnary, "cos");
|
Add(Instruction.Cosine, InstType.CallUnary, "cos");
|
||||||
Add(Instruction.Ddx, InstType.CallUnary, "dFdx");
|
Add(Instruction.Ddx, InstType.CallUnary, "dFdx");
|
||||||
Add(Instruction.Ddy, InstType.CallUnary, "dFdy");
|
Add(Instruction.Ddy, InstType.CallUnary, "dFdy");
|
||||||
|
|
|
@ -179,27 +179,40 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Instruction fpType = srcType.ToInstFPType();
|
||||||
|
|
||||||
bool isSignedInt = dstType == IDstFmt.S16 || dstType == IDstFmt.S32 || dstType == IDstFmt.S64;
|
bool isSignedInt = dstType == IDstFmt.S16 || dstType == IDstFmt.S32 || dstType == IDstFmt.S64;
|
||||||
bool isSmallInt = dstType == IDstFmt.U16 || dstType == IDstFmt.S16;
|
bool isSmallInt = dstType == IDstFmt.U16 || dstType == IDstFmt.S16;
|
||||||
|
|
||||||
Operand srcB = context.FPAbsNeg(src, absolute, negate);
|
Operand srcB = context.FPAbsNeg(src, absolute, negate, fpType);
|
||||||
|
|
||||||
srcB = roundingMode switch
|
srcB = roundingMode switch
|
||||||
{
|
{
|
||||||
RoundMode2.Round => context.FPRound(srcB),
|
RoundMode2.Round => context.FPRound(srcB, fpType),
|
||||||
RoundMode2.Floor => context.FPFloor(srcB),
|
RoundMode2.Floor => context.FPFloor(srcB, fpType),
|
||||||
RoundMode2.Ceil => context.FPCeiling(srcB),
|
RoundMode2.Ceil => context.FPCeiling(srcB, fpType),
|
||||||
RoundMode2.Trunc => context.FPTruncate(srcB),
|
RoundMode2.Trunc => context.FPTruncate(srcB, fpType),
|
||||||
_ => srcB
|
_ => srcB
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!isSignedInt)
|
if (!isSignedInt)
|
||||||
{
|
{
|
||||||
// Negative float to uint cast is undefined, so we clamp the value before conversion.
|
// Negative float to uint cast is undefined, so we clamp the value before conversion.
|
||||||
srcB = context.FPMaximum(srcB, ConstF(0));
|
srcB = context.FPMaximum(srcB, ConstF(0), fpType);
|
||||||
}
|
}
|
||||||
|
|
||||||
srcB = isSignedInt ? context.FPConvertToS32(srcB) : context.FPConvertToU32(srcB);
|
if (srcType == DstFmt.F64)
|
||||||
|
{
|
||||||
|
srcB = isSignedInt
|
||||||
|
? context.FP64ConvertToS32(srcB)
|
||||||
|
: context.FP64ConvertToU32(srcB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srcB = isSignedInt
|
||||||
|
? context.FP32ConvertToS32(srcB)
|
||||||
|
: context.FP32ConvertToU32(srcB);
|
||||||
|
}
|
||||||
|
|
||||||
if (isSmallInt)
|
if (isSmallInt)
|
||||||
{
|
{
|
||||||
|
@ -252,7 +265,18 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
: context.BitfieldExtractU32(srcB, Const((int)byteSelection * 8), Const(size));
|
: context.BitfieldExtractU32(srcB, Const((int)byteSelection * 8), Const(size));
|
||||||
}
|
}
|
||||||
|
|
||||||
srcB = isSignedInt ? context.IConvertS32ToFP(srcB) : context.IConvertU32ToFP(srcB);
|
if (dstType == DstFmt.F64)
|
||||||
|
{
|
||||||
|
srcB = isSignedInt
|
||||||
|
? context.IConvertS32ToFP64(srcB)
|
||||||
|
: context.IConvertU32ToFP64(srcB);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
srcB = isSignedInt
|
||||||
|
? context.IConvertS32ToFP32(srcB)
|
||||||
|
: context.IConvertU32ToFP32(srcB);
|
||||||
|
}
|
||||||
|
|
||||||
WriteFP(context, dstType, srcB, rd);
|
WriteFP(context, dstType, srcB, rd);
|
||||||
|
|
||||||
|
|
|
@ -939,7 +939,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
tempDest = context.FPMultiply(tempDest, ConstF(256.0f));
|
tempDest = context.FPMultiply(tempDest, ConstF(256.0f));
|
||||||
|
|
||||||
Operand fixedPointValue = context.FPConvertToS32(tempDest);
|
Operand fixedPointValue = context.FP32ConvertToS32(tempDest);
|
||||||
|
|
||||||
context.Copy(GetDest(), fixedPointValue);
|
context.Copy(GetDest(), fixedPointValue);
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,10 +49,14 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
||||||
ConditionalSelect,
|
ConditionalSelect,
|
||||||
ConvertFP32ToFP64,
|
ConvertFP32ToFP64,
|
||||||
ConvertFP64ToFP32,
|
ConvertFP64ToFP32,
|
||||||
ConvertFPToS32,
|
ConvertFP32ToS32,
|
||||||
ConvertFPToU32,
|
ConvertFP32ToU32,
|
||||||
ConvertS32ToFP,
|
ConvertFP64ToS32,
|
||||||
ConvertU32ToFP,
|
ConvertFP64ToU32,
|
||||||
|
ConvertS32ToFP32,
|
||||||
|
ConvertS32ToFP64,
|
||||||
|
ConvertU32ToFP32,
|
||||||
|
ConvertU32ToFP64,
|
||||||
Copy,
|
Copy,
|
||||||
Cosine,
|
Cosine,
|
||||||
Ddx,
|
Ddx,
|
||||||
|
|
|
@ -66,10 +66,14 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
Add(Instruction.ConditionalSelect, VariableType.Scalar, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
Add(Instruction.ConditionalSelect, VariableType.Scalar, VariableType.Bool, VariableType.Scalar, VariableType.Scalar);
|
||||||
Add(Instruction.ConvertFP32ToFP64, VariableType.F64, VariableType.F32);
|
Add(Instruction.ConvertFP32ToFP64, VariableType.F64, VariableType.F32);
|
||||||
Add(Instruction.ConvertFP64ToFP32, VariableType.F32, VariableType.F64);
|
Add(Instruction.ConvertFP64ToFP32, VariableType.F32, VariableType.F64);
|
||||||
Add(Instruction.ConvertFPToS32, VariableType.S32, VariableType.F32);
|
Add(Instruction.ConvertFP32ToS32, VariableType.S32, VariableType.F32);
|
||||||
Add(Instruction.ConvertFPToU32, VariableType.U32, VariableType.F32);
|
Add(Instruction.ConvertFP32ToU32, VariableType.U32, VariableType.F32);
|
||||||
Add(Instruction.ConvertS32ToFP, VariableType.F32, VariableType.S32);
|
Add(Instruction.ConvertFP64ToS32, VariableType.S32, VariableType.F64);
|
||||||
Add(Instruction.ConvertU32ToFP, VariableType.F32, VariableType.U32);
|
Add(Instruction.ConvertFP64ToU32, VariableType.U32, VariableType.F64);
|
||||||
|
Add(Instruction.ConvertS32ToFP32, VariableType.F32, VariableType.S32);
|
||||||
|
Add(Instruction.ConvertS32ToFP64, VariableType.F64, VariableType.S32);
|
||||||
|
Add(Instruction.ConvertU32ToFP32, VariableType.F32, VariableType.U32);
|
||||||
|
Add(Instruction.ConvertU32ToFP64, VariableType.F64, VariableType.U32);
|
||||||
Add(Instruction.Cosine, VariableType.Scalar, VariableType.Scalar);
|
Add(Instruction.Cosine, VariableType.Scalar, VariableType.Scalar);
|
||||||
Add(Instruction.Ddx, VariableType.F32, VariableType.F32);
|
Add(Instruction.Ddx, VariableType.F32, VariableType.F32);
|
||||||
Add(Instruction.Ddy, VariableType.F32, VariableType.F32);
|
Add(Instruction.Ddy, VariableType.F32, VariableType.F32);
|
||||||
|
|
|
@ -241,14 +241,24 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return context.Add(fpType | Instruction.CompareLess, Local(), a, b);
|
return context.Add(fpType | Instruction.CompareLess, Local(), a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand FPConvertToS32(this EmitterContext context, Operand a)
|
public static Operand FP32ConvertToS32(this EmitterContext context, Operand a)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.ConvertFPToS32, Local(), a);
|
return context.Add(Instruction.ConvertFP32ToS32, Local(), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand FPConvertToU32(this EmitterContext context, Operand a)
|
public static Operand FP32ConvertToU32(this EmitterContext context, Operand a)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.ConvertFPToU32, Local(), a);
|
return context.Add(Instruction.ConvertFP32ToU32, Local(), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand FP64ConvertToS32(this EmitterContext context, Operand a)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.ConvertFP64ToS32, Local(), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand FP64ConvertToU32(this EmitterContext context, Operand a)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.ConvertFP64ToU32, Local(), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand FPCosine(this EmitterContext context, Operand a)
|
public static Operand FPCosine(this EmitterContext context, Operand a)
|
||||||
|
@ -281,9 +291,9 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return context.Add(Instruction.FP32 | Instruction.LogarithmB2, Local(), a);
|
return context.Add(Instruction.FP32 | Instruction.LogarithmB2, Local(), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand FPMaximum(this EmitterContext context, Operand a, Operand b)
|
public static Operand FPMaximum(this EmitterContext context, Operand a, Operand b, Instruction fpType = Instruction.FP32)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.FP32 | Instruction.Maximum, Local(), a, b);
|
return context.Add(fpType | Instruction.Maximum, Local(), a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand FPMinimum(this EmitterContext context, Operand a, Operand b)
|
public static Operand FPMinimum(this EmitterContext context, Operand a, Operand b)
|
||||||
|
@ -461,14 +471,24 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return context.Add(Instruction.CompareNotEqual, Local(), a, b);
|
return context.Add(Instruction.CompareNotEqual, Local(), a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand IConvertS32ToFP(this EmitterContext context, Operand a)
|
public static Operand IConvertS32ToFP32(this EmitterContext context, Operand a)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.ConvertS32ToFP, Local(), a);
|
return context.Add(Instruction.ConvertS32ToFP32, Local(), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand IConvertU32ToFP(this EmitterContext context, Operand a)
|
public static Operand IConvertS32ToFP64(this EmitterContext context, Operand a)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.ConvertU32ToFP, Local(), a);
|
return context.Add(Instruction.ConvertS32ToFP64, Local(), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand IConvertU32ToFP32(this EmitterContext context, Operand a)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.ConvertU32ToFP32, Local(), a);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand IConvertU32ToFP64(this EmitterContext context, Operand a)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.ConvertU32ToFP64, Local(), a);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Operand IMaximumS32(this EmitterContext context, Operand a, Operand b)
|
public static Operand IMaximumS32(this EmitterContext context, Operand a, Operand b)
|
||||||
|
|
|
@ -286,7 +286,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
Operand res = Local();
|
Operand res = Local();
|
||||||
|
|
||||||
node.List.AddBefore(node, new Operation(Instruction.ConvertFPToS32, res, value));
|
node.List.AddBefore(node, new Operation(Instruction.ConvertFP32ToS32, res, value));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
Operand res = Local();
|
Operand res = Local();
|
||||||
|
|
||||||
node.List.AddBefore(node, new Operation(Instruction.ConvertS32ToFP, res, value));
|
node.List.AddBefore(node, new Operation(Instruction.ConvertS32ToFP32, res, value));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +501,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
// as replacement for SNORM (which is not supported).
|
// as replacement for SNORM (which is not supported).
|
||||||
INode[] uses = texOp.Dest.UseOps.ToArray();
|
INode[] uses = texOp.Dest.UseOps.ToArray();
|
||||||
|
|
||||||
Operation convOp = new Operation(Instruction.ConvertS32ToFP, Local(), texOp.Dest);
|
Operation convOp = new Operation(Instruction.ConvertS32ToFP32, Local(), texOp.Dest);
|
||||||
Operation normOp = new Operation(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive));
|
Operation normOp = new Operation(Instruction.FP32 | Instruction.Multiply, Local(), convOp.Dest, ConstF(1f / maxPositive));
|
||||||
|
|
||||||
node = node.List.AddAfter(node, convOp);
|
node = node.List.AddAfter(node, convOp);
|
||||||
|
|
Loading…
Reference in a new issue