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

Avoid gpr overwritting on Ld_C instruction (#371)

* Avoid gpr overwritting on LD_C instruction

* Address feedback

* Ignore invalid registers
ReinUsesLisp 7 лет назад
Родитель
Сommit
afc44850be

+ 0 - 7
Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs

@@ -35,13 +35,6 @@ namespace Ryujinx.Graphics.Gal.Shader
                 (int)(OpCode >> 20) & 0x3fff);
         }
 
-        public static ShaderIrOperCbuf GetOperCbuf36(long OpCode)
-        {
-            return new ShaderIrOperCbuf(
-                (int)(OpCode >> 36) & 0x1f,
-                (int)(OpCode >> 22) & 0x3fff, GetOperGpr8(OpCode));
-        }
-
         public static ShaderIrOperGpr GetOperGpr8(long OpCode)
         {
             return new ShaderIrOperGpr((int)(OpCode >> 8) & 0xff);

+ 15 - 3
Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs

@@ -52,23 +52,35 @@ namespace Ryujinx.Graphics.Gal.Shader
 
         public static void Ld_C(ShaderIrBlock Block, long OpCode)
         {
-            int Type = (int)(OpCode >> 48) & 7;
+            int CbufPos   = (int)(OpCode >> 22) & 0x3fff;
+            int CbufIndex = (int)(OpCode >> 36) & 0x1f;
+            int Type      = (int)(OpCode >> 48) & 7;
 
             if (Type > 5)
             {
                 throw new InvalidOperationException();
             }
 
+            ShaderIrOperGpr Temp = ShaderIrOperGpr.MakeTemporary();
+
+            Block.AddNode(new ShaderIrAsg(Temp, GetOperGpr8(OpCode)));
+
             int Count = Type == 5 ? 2 : 1;
 
             for (int Index = 0; Index < Count; Index++)
             {
-                ShaderIrOperCbuf OperA = GetOperCbuf36(OpCode);
-                ShaderIrOperGpr  OperD = GetOperGpr0  (OpCode);
+                ShaderIrOperCbuf OperA = new ShaderIrOperCbuf(CbufIndex, CbufPos, Temp);
+
+                ShaderIrOperGpr OperD = GetOperGpr0(OpCode);
 
                 OperA.Pos   += Index;
                 OperD.Index += Index;
 
+                if (!OperD.IsValidRegister)
+                {
+                    break;
+                }
+
                 ShaderIrNode Node = OperA;
 
                 if (Type < 4)

+ 7 - 0
Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs

@@ -6,11 +6,18 @@ namespace Ryujinx.Graphics.Gal.Shader
 
         public bool IsConst => Index == ZRIndex;
 
+        public bool IsValidRegister => (Index <= ZRIndex);
+
         public int Index { get; set; }
 
         public ShaderIrOperGpr(int Index)
         {
             this.Index = Index;
         }
+
+        public static ShaderIrOperGpr MakeTemporary(int Index = 0)
+        {
+            return new ShaderIrOperGpr(0x100 + Index);
+        }
     }
 }