Просмотр исходного кода

Implement p2rc, p2ri, p2rr and r2p.cc shaders (#5031)

* implement P2rC, P2rI, P2rR shaders

* implement R2p.CC shader

* bump CodeGenVersion

* address feedback
makigumo 2 лет назад
Родитель
Сommit
6cb6b15612

+ 1 - 1
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";

+ 0 - 21
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<InstP2rR>();
-
-            context.Config.GpuAccessor.Log("Shader instruction P2rR is not implemented.");
-        }
-
-        public static void P2rI(EmitterContext context)
-        {
-            InstP2rI op = context.GetOp<InstP2rI>();
-
-            context.Config.GpuAccessor.Log("Shader instruction P2rI is not implemented.");
-        }
-
-        public static void P2rC(EmitterContext context)
-        {
-            InstP2rC op = context.GetOp<InstP2rC>();
-
-            context.Config.GpuAccessor.Log("Shader instruction P2rC is not implemented.");
-        }
-
         public static void Pexit(EmitterContext context)
         {
             InstPexit op = context.GetOp<InstPexit>();

+ 8 - 14
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);
             }
         }
 

+ 63 - 1
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<InstP2rC>();
+
+            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<InstP2rI>();
+
+            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<InstP2rR>();
+
+            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);
+        }
     }
 }