From 6cb6b15612a20717c0e98045914b535f582cdc33 Mon Sep 17 00:00:00 2001 From: makigumo Date: Mon, 22 May 2023 22:32:15 +0200 Subject: [PATCH] Implement p2rc, p2ri, p2rr and r2p.cc shaders (#5031) * implement P2rC, P2rI, P2rR shaders * implement R2p.CC shader * bump CodeGenVersion * address feedback --- .../Shader/DiskCache/DiskCacheHostStorage.cs | 2 +- .../Instructions/InstEmit.cs | 21 ------ .../Instructions/InstEmitMove.cs | 22 +++---- .../Instructions/InstEmitPredicate.cs | 64 ++++++++++++++++++- 4 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs index 9f263e9d7..400f63f56 100644 --- a/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs +++ b/src/Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs @@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache private const ushort FileFormatVersionMajor = 1; private const ushort FileFormatVersionMinor = 2; private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor; - private const uint CodeGenVersion = 4646; + private const uint CodeGenVersion = 5031; private const string SharedTocFileName = "shared.toc"; private const string SharedDataFileName = "shared.data"; diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs index 3a9e658aa..963a5c656 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmit.cs @@ -187,27 +187,6 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Config.GpuAccessor.Log("Shader instruction Longjmp is not implemented."); } - public static void P2rR(EmitterContext context) - { - InstP2rR op = context.GetOp(); - - context.Config.GpuAccessor.Log("Shader instruction P2rR is not implemented."); - } - - public static void P2rI(EmitterContext context) - { - InstP2rI op = context.GetOp(); - - context.Config.GpuAccessor.Log("Shader instruction P2rI is not implemented."); - } - - public static void P2rC(EmitterContext context) - { - InstP2rC op = context.GetOp(); - - context.Config.GpuAccessor.Log("Shader instruction P2rC is not implemented."); - } - public static void Pexit(EmitterContext context) { InstPexit op = context.GetOp(); diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs index 9992ac378..e12177f7d 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitMove.cs @@ -209,21 +209,15 @@ namespace Ryujinx.Graphics.Shader.Instructions return context.ICompareNotEqual(context.BitwiseAnd(value, Const(1 << bit)), Const(0)); } - if (ccpr) + int count = ccpr ? RegisterConsts.FlagsCount : RegisterConsts.PredsCount; + RegisterType type = ccpr ? RegisterType.Flag : RegisterType.Predicate; + int shift = (int)byteSel * 8; + + for (int bit = 0; bit < count; bit++) { - // TODO: Support Register to condition code flags copy. - context.Config.GpuAccessor.Log("R2P.CC not implemented."); - } - else - { - int shift = (int)byteSel * 8; - - for (int bit = 0; bit < RegisterConsts.PredsCount; bit++) - { - Operand pred = Register(bit, RegisterType.Predicate); - Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), pred); - context.Copy(pred, res); - } + Operand flag = Register(bit, type); + Operand res = context.ConditionalSelect(Test(mask, bit), Test(value, bit + shift), flag); + context.Copy(flag, res); } } diff --git a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs index d605661ff..79919624e 100644 --- a/src/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs +++ b/src/Ryujinx.Graphics.Shader/Instructions/InstEmitPredicate.cs @@ -1,7 +1,6 @@ using Ryujinx.Graphics.Shader.Decoders; using Ryujinx.Graphics.Shader.IntermediateRepresentation; using Ryujinx.Graphics.Shader.Translation; - using static Ryujinx.Graphics.Shader.Instructions.InstEmitAluHelper; using static Ryujinx.Graphics.Shader.Instructions.InstEmitHelper; using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper; @@ -50,5 +49,68 @@ namespace Ryujinx.Graphics.Shader.Instructions context.Copy(Register(op.DestPred, RegisterType.Predicate), p0Res); context.Copy(Register(op.DestPredInv, RegisterType.Predicate), p1Res); } + + public static void P2rC(EmitterContext context) + { + InstP2rC op = context.GetOp(); + + Operand srcA = GetSrcReg(context, op.SrcA); + Operand dest = GetSrcReg(context, op.Dest); + Operand mask = GetSrcCbuf(context, op.CbufSlot, op.CbufOffset); + + EmitP2r(context, srcA, dest, mask, op.ByteSel, op.Ccpr); + } + + public static void P2rI(EmitterContext context) + { + InstP2rI op = context.GetOp(); + + Operand srcA = GetSrcReg(context, op.SrcA); + Operand dest = GetSrcReg(context, op.Dest); + Operand mask = GetSrcImm(context, op.Imm20); + + EmitP2r(context, srcA, dest, mask, op.ByteSel, op.Ccpr); + } + + public static void P2rR(EmitterContext context) + { + InstP2rR op = context.GetOp(); + + Operand srcA = GetSrcReg(context, op.SrcA); + Operand dest = GetSrcReg(context, op.Dest); + Operand mask = GetSrcReg(context, op.SrcB); + + EmitP2r(context, srcA, dest, mask, op.ByteSel, op.Ccpr); + } + + private static void EmitP2r( + EmitterContext context, + Operand srcA, + Operand dest, + Operand mask, + ByteSel byteSel, + bool ccpr) + { + int count = ccpr ? RegisterConsts.FlagsCount : RegisterConsts.PredsCount; + int shift = (int)byteSel * 8; + mask = context.BitwiseAnd(mask, Const(0xff)); + + Operand insert = Const(0); + for (int i = 0; i < count; i++) + { + Operand condition = ccpr + ? Register(i, RegisterType.Flag) + : Register(i, RegisterType.Predicate); + + Operand bit = context.ConditionalSelect(condition, Const(1 << (i + shift)), Const(0)); + insert = context.BitwiseOr(insert, bit); + } + + Operand maskShifted = context.ShiftLeft(mask, Const(shift)); + Operand masked = context.BitwiseAnd(srcA, context.BitwiseNot(maskShifted)); + Operand res = context.BitwiseOr(masked, context.BitwiseAnd(insert, maskShifted)); + + context.Copy(dest, res); + } } } \ No newline at end of file