mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-11-14 06:56:39 +00:00
Implement shader CC mode for ISCADD, X mode for ISETP and fix STL/STS/STG with RZ (#1901)
* Implement shader CC mode for ISCADD, X mode for ISETP and fix STS/STG with RZ * Fix STG too and bump shader cache version * Fix wrong name * Fix Carry being inverted on comparison
This commit is contained in:
parent
df820a72de
commit
36c6e67df2
4 changed files with 128 additions and 34 deletions
|
@ -34,7 +34,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Version of the codegen (to be changed when codegen or guest format change).
|
/// Version of the codegen (to be changed when codegen or guest format change).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private const ulong ShaderCodeGenVersion = 1878;
|
private const ulong ShaderCodeGenVersion = 1901;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new instance of the shader cache.
|
/// Creates a new instance of the shader cache.
|
||||||
|
|
|
@ -119,17 +119,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
Operand res = context.IAdd(srcA, srcB);
|
Operand res = context.IAdd(srcA, srcB);
|
||||||
|
|
||||||
bool isSubtraction = negateA || negateB;
|
|
||||||
|
|
||||||
if (op.Extended)
|
if (op.Extended)
|
||||||
{
|
{
|
||||||
// Add carry, or subtract borrow.
|
res = context.IAdd(res, context.BitwiseAnd(GetCF(), Const(1)));
|
||||||
res = context.IAdd(res, isSubtraction
|
|
||||||
? context.BitwiseNot(GetCF())
|
|
||||||
: context.BitwiseAnd(GetCF(), Const(1)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetIaddFlags(context, res, srcA, srcB, op.SetCondCode, op.Extended, isSubtraction);
|
SetIaddFlags(context, res, srcA, srcB, op.SetCondCode, op.Extended);
|
||||||
|
|
||||||
context.Copy(GetDest(context), res);
|
context.Copy(GetDest(context), res);
|
||||||
}
|
}
|
||||||
|
@ -317,9 +312,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
Operand res = context.IAdd(srcA, srcB);
|
Operand res = context.IAdd(srcA, srcB);
|
||||||
|
|
||||||
context.Copy(GetDest(context), res);
|
SetIaddFlags(context, res, srcA, srcB, op.SetCondCode, false);
|
||||||
|
|
||||||
// TODO: CC, X
|
context.Copy(GetDest(context), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Iset(EmitterContext context)
|
public static void Iset(EmitterContext context)
|
||||||
|
@ -334,7 +329,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
Operand srcA = GetSrcA(context);
|
Operand srcA = GetSrcA(context);
|
||||||
Operand srcB = GetSrcB(context);
|
Operand srcB = GetSrcB(context);
|
||||||
|
|
||||||
Operand res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned);
|
Operand res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, op.Extended);
|
||||||
|
|
||||||
Operand pred = GetPredicate39(context);
|
Operand pred = GetPredicate39(context);
|
||||||
|
|
||||||
|
@ -356,8 +351,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
SetZnFlags(context, res, op.SetCondCode, op.Extended);
|
SetZnFlags(context, res, op.SetCondCode, op.Extended);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: X
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Isetp(EmitterContext context)
|
public static void Isetp(EmitterContext context)
|
||||||
|
@ -371,7 +364,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
Operand srcA = GetSrcA(context);
|
Operand srcA = GetSrcA(context);
|
||||||
Operand srcB = GetSrcB(context);
|
Operand srcB = GetSrcB(context);
|
||||||
|
|
||||||
Operand p0Res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned);
|
Operand p0Res = GetIntComparison(context, cmpOp, srcA, srcB, isSigned, op.Extended);
|
||||||
|
|
||||||
Operand p1Res = context.BitwiseNot(p0Res);
|
Operand p1Res = context.BitwiseNot(p0Res);
|
||||||
|
|
||||||
|
@ -799,6 +792,84 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
context.Copy(GetDest(context), res);
|
context.Copy(GetDest(context), res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Operand GetIntComparison(
|
||||||
|
EmitterContext context,
|
||||||
|
IntegerCondition cond,
|
||||||
|
Operand srcA,
|
||||||
|
Operand srcB,
|
||||||
|
bool isSigned,
|
||||||
|
bool extended)
|
||||||
|
{
|
||||||
|
return extended
|
||||||
|
? GetIntComparisonExtended(context, cond, srcA, srcB, isSigned)
|
||||||
|
: GetIntComparison (context, cond, srcA, srcB, isSigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Operand GetIntComparisonExtended(
|
||||||
|
EmitterContext context,
|
||||||
|
IntegerCondition cond,
|
||||||
|
Operand srcA,
|
||||||
|
Operand srcB,
|
||||||
|
bool isSigned)
|
||||||
|
{
|
||||||
|
Operand res;
|
||||||
|
|
||||||
|
if (cond == IntegerCondition.Always)
|
||||||
|
{
|
||||||
|
res = Const(IrConsts.True);
|
||||||
|
}
|
||||||
|
else if (cond == IntegerCondition.Never)
|
||||||
|
{
|
||||||
|
res = Const(IrConsts.False);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res = context.ISubtract(srcA, srcB);
|
||||||
|
res = context.IAdd(res, context.BitwiseNot(GetCF()));
|
||||||
|
|
||||||
|
switch (cond)
|
||||||
|
{
|
||||||
|
case Decoders.IntegerCondition.Equal: // r = xh == yh && xl == yl
|
||||||
|
res = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetZF());
|
||||||
|
break;
|
||||||
|
case Decoders.IntegerCondition.Less: // r = xh < yh || (xh == yh && xl < yl)
|
||||||
|
Operand notC = context.BitwiseNot(GetCF());
|
||||||
|
Operand prevLt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notC);
|
||||||
|
res = isSigned
|
||||||
|
? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLt)
|
||||||
|
: context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLt);
|
||||||
|
break;
|
||||||
|
case Decoders.IntegerCondition.LessOrEqual: // r = xh < yh || (xh == yh && xl <= yl)
|
||||||
|
Operand zOrNotC = context.BitwiseOr(GetZF(), context.BitwiseNot(GetCF()));
|
||||||
|
Operand prevLe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), zOrNotC);
|
||||||
|
res = isSigned
|
||||||
|
? context.BitwiseOr(context.ICompareLess(srcA, srcB), prevLe)
|
||||||
|
: context.BitwiseOr(context.ICompareLessUnsigned(srcA, srcB), prevLe);
|
||||||
|
break;
|
||||||
|
case Decoders.IntegerCondition.Greater: // r = xh > yh || (xh == yh && xl > yl)
|
||||||
|
Operand notZAndC = context.BitwiseAnd(context.BitwiseNot(GetZF()), GetCF());
|
||||||
|
Operand prevGt = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), notZAndC);
|
||||||
|
res = isSigned
|
||||||
|
? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGt)
|
||||||
|
: context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGt);
|
||||||
|
break;
|
||||||
|
case Decoders.IntegerCondition.GreaterOrEqual: // r = xh > yh || (xh == yh && xl >= yl)
|
||||||
|
Operand prevGe = context.BitwiseAnd(context.ICompareEqual(srcA, srcB), GetCF());
|
||||||
|
res = isSigned
|
||||||
|
? context.BitwiseOr(context.ICompareGreater(srcA, srcB), prevGe)
|
||||||
|
: context.BitwiseOr(context.ICompareGreaterUnsigned(srcA, srcB), prevGe);
|
||||||
|
break;
|
||||||
|
case Decoders.IntegerCondition.NotEqual: // r = xh != yh || xl != yl
|
||||||
|
context.BitwiseOr(context.ICompareNotEqual(srcA, srcB), context.BitwiseNot(GetZF()));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new InvalidOperationException($"Unexpected condition \"{cond}\".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
private static Operand GetIntComparison(
|
private static Operand GetIntComparison(
|
||||||
EmitterContext context,
|
EmitterContext context,
|
||||||
IntegerCondition cond,
|
IntegerCondition cond,
|
||||||
|
@ -879,20 +950,14 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
Operand srcA,
|
Operand srcA,
|
||||||
Operand srcB,
|
Operand srcB,
|
||||||
bool setCC,
|
bool setCC,
|
||||||
bool extended,
|
bool extended)
|
||||||
bool isSubtraction = false)
|
|
||||||
{
|
{
|
||||||
if (!setCC)
|
if (!setCC)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!extended || isSubtraction)
|
if (extended)
|
||||||
{
|
|
||||||
// C = d < a
|
|
||||||
context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// C = (d == a && CIn) || d < a
|
// C = (d == a && CIn) || d < a
|
||||||
Operand tempC0 = context.ICompareEqual (res, srcA);
|
Operand tempC0 = context.ICompareEqual (res, srcA);
|
||||||
|
@ -902,6 +967,11 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1));
|
context.Copy(GetCF(), context.BitwiseOr(tempC0, tempC1));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// C = d < a
|
||||||
|
context.Copy(GetCF(), context.ICompareLessUnsigned(res, srcA));
|
||||||
|
}
|
||||||
|
|
||||||
// V = (d ^ a) & ~(a ^ b) < 0
|
// V = (d ^ a) & ~(a ^ b) < 0
|
||||||
Operand tempV0 = context.BitwiseExclusiveOr(res, srcA);
|
Operand tempV0 = context.BitwiseExclusiveOr(res, srcA);
|
||||||
|
|
|
@ -501,7 +501,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
for (int index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr);
|
bool isRz = op.Rd.IsRZ;
|
||||||
|
|
||||||
|
Register rd = new Register(isRz ? op.Rd.Index : op.Rd.Index + index, RegisterType.Gpr);
|
||||||
|
|
||||||
Operand value = Register(rd);
|
Operand value = Register(rd);
|
||||||
|
|
||||||
|
@ -525,11 +527,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
case MemoryRegion.Local: context.StoreLocal (offset, value); break;
|
case MemoryRegion.Local: context.StoreLocal (offset, value); break;
|
||||||
case MemoryRegion.Shared: context.StoreShared(offset, value); break;
|
case MemoryRegion.Shared: context.StoreShared(offset, value); break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rd.IsRZ)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -547,7 +544,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
|
|
||||||
for (int index = 0; index < count; index++)
|
for (int index = 0; index < count; index++)
|
||||||
{
|
{
|
||||||
Register rd = new Register(op.Rd.Index + index, RegisterType.Gpr);
|
bool isRz = op.Rd.IsRZ;
|
||||||
|
|
||||||
|
Register rd = new Register(isRz ? op.Rd.Index : op.Rd.Index + index, RegisterType.Gpr);
|
||||||
|
|
||||||
Operand value = Register(rd);
|
Operand value = Register(rd);
|
||||||
|
|
||||||
|
@ -559,11 +558,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
context.StoreGlobal(context.IAdd(addrLow, Const(index * 4)), addrHigh, value);
|
context.StoreGlobal(context.IAdd(addrLow, Const(index * 4)), addrHigh, value);
|
||||||
|
|
||||||
if (rd.IsRZ)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -406,11 +406,41 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return context.Add(Instruction.CompareEqual, Local(), a, b);
|
return context.Add(Instruction.CompareEqual, Local(), a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operand ICompareGreater(this EmitterContext context, Operand a, Operand b)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.CompareGreater, Local(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand ICompareGreaterOrEqual(this EmitterContext context, Operand a, Operand b)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.CompareGreaterOrEqual, Local(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand ICompareGreaterOrEqualUnsigned(this EmitterContext context, Operand a, Operand b)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.CompareGreaterOrEqualU32, Local(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand ICompareGreaterUnsigned(this EmitterContext context, Operand a, Operand b)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.CompareGreaterU32, Local(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand ICompareLess(this EmitterContext context, Operand a, Operand b)
|
public static Operand ICompareLess(this EmitterContext context, Operand a, Operand b)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.CompareLess, Local(), a, b);
|
return context.Add(Instruction.CompareLess, Local(), a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operand ICompareLessOrEqual(this EmitterContext context, Operand a, Operand b)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.CompareLessOrEqual, Local(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Operand ICompareLessOrEqualUnsigned(this EmitterContext context, Operand a, Operand b)
|
||||||
|
{
|
||||||
|
return context.Add(Instruction.CompareLessOrEqualU32, Local(), a, b);
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand ICompareLessUnsigned(this EmitterContext context, Operand a, Operand b)
|
public static Operand ICompareLessUnsigned(this EmitterContext context, Operand a, Operand b)
|
||||||
{
|
{
|
||||||
return context.Add(Instruction.CompareLessU32, Local(), a, b);
|
return context.Add(Instruction.CompareLessU32, Local(), a, b);
|
||||||
|
|
Loading…
Reference in a new issue