소스 검색

Fix shaders with global memory access from unknown locations (#4029)

* Fix shaders with global memory access from unknown locations

* Shader cache version bump
gdkchan 3 년 전
부모
커밋
de06ffb0f7
2개의 변경된 파일64개의 추가작업 그리고 43개의 파일을 삭제
  1. 1 1
      Ryujinx.Graphics.Gpu/Shader/DiskCache/DiskCacheHostStorage.cs
  2. 63 42
      Ryujinx.Graphics.Shader/Translation/Rewriter.cs

+ 1 - 1
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 = 4011;
+        private const uint CodeGenVersion = 4029;
 
         private const string SharedTocFileName = "shared.toc";
         private const string SharedDataFileName = "shared.data";

+ 63 - 42
Ryujinx.Graphics.Shader/Translation/Rewriter.cs

@@ -21,10 +21,11 @@ namespace Ryujinx.Graphics.Shader.Translation
             {
                 BasicBlock block = blocks[blkIndex];
 
-                for (LinkedListNode<INode> node = block.Operations.First; node != null; node = node.Next)
+                for (LinkedListNode<INode> node = block.Operations.First; node != null;)
                 {
                     if (node.Value is not Operation operation)
                     {
+                        node = node.Next;
                         continue;
                     }
 
@@ -43,10 +44,7 @@ namespace Ryujinx.Graphics.Shader.Translation
                         }
                     }
 
-                    if (UsesGlobalMemory(operation.Inst))
-                    {
-                        node = RewriteGlobalAccess(node, config);
-                    }
+                    LinkedListNode<INode> nextNode = node.Next;
 
                     if (operation is TextureOperation texOp)
                     {
@@ -59,7 +57,15 @@ namespace Ryujinx.Graphics.Shader.Translation
                                 node = InsertSnormNormalization(node, config);
                             }
                         }
+
+                        nextNode = node.Next;
                     }
+                    else if (UsesGlobalMemory(operation.Inst))
+                    {
+                        nextNode = RewriteGlobalAccess(node, config)?.Next ?? nextNode;
+                    }
+
+                    node = nextNode;
                 }
             }
         }
@@ -72,7 +78,7 @@ namespace Ryujinx.Graphics.Shader.Translation
             bool isStg16Or8 = operation.Inst == Instruction.StoreGlobal16 || operation.Inst == Instruction.StoreGlobal8;
             bool isWrite = isAtomic || operation.Inst == Instruction.StoreGlobal || isStg16Or8;
 
-            Operation storageOp;
+            Operation storageOp = null;
 
             Operand PrependOperation(Instruction inst, params Operand[] sources)
             {
@@ -120,49 +126,56 @@ namespace Ryujinx.Graphics.Shader.Translation
                 sbSlot        = PrependOperation(Instruction.ConditionalSelect, inRange, Const(slot), sbSlot);
             }
 
-            Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
+            if (sbUseMask != 0)
+            {
+                Operand alignMask = Const(-config.GpuAccessor.QueryHostStorageBufferOffsetAlignment());
 
-            Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
-            Operand byteOffset    = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
+                Operand baseAddrTrunc = PrependOperation(Instruction.BitwiseAnd, sbBaseAddrLow, alignMask);
+                Operand byteOffset    = PrependOperation(Instruction.Subtract, addrLow, baseAddrTrunc);
 
-            Operand[] sources = new Operand[operation.SourcesCount];
+                Operand[] sources = new Operand[operation.SourcesCount];
 
-            sources[0] = sbSlot;
+                sources[0] = sbSlot;
 
-            if (isStg16Or8)
-            {
-                sources[1] = byteOffset;
-            }
-            else
-            {
-                sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
-            }
+                if (isStg16Or8)
+                {
+                    sources[1] = byteOffset;
+                }
+                else
+                {
+                    sources[1] = PrependOperation(Instruction.ShiftRightU32, byteOffset, Const(2));
+                }
 
-            for (int index = 2; index < operation.SourcesCount; index++)
-            {
-                sources[index] = operation.GetSource(index);
-            }
+                for (int index = 2; index < operation.SourcesCount; index++)
+                {
+                    sources[index] = operation.GetSource(index);
+                }
 
-            if (isAtomic)
-            {
-                Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage;
+                if (isAtomic)
+                {
+                    Instruction inst = (operation.Inst & ~Instruction.MrMask) | Instruction.MrStorage;
 
-                storageOp = new Operation(inst, operation.Dest, sources);
-            }
-            else if (operation.Inst == Instruction.LoadGlobal)
-            {
-                storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
-            }
-            else
-            {
-                Instruction storeInst = operation.Inst switch
+                    storageOp = new Operation(inst, operation.Dest, sources);
+                }
+                else if (operation.Inst == Instruction.LoadGlobal)
+                {
+                    storageOp = new Operation(Instruction.LoadStorage, operation.Dest, sources);
+                }
+                else
                 {
-                    Instruction.StoreGlobal16 => Instruction.StoreStorage16,
-                    Instruction.StoreGlobal8 => Instruction.StoreStorage8,
-                    _ => Instruction.StoreStorage
-                };
+                    Instruction storeInst = operation.Inst switch
+                    {
+                        Instruction.StoreGlobal16 => Instruction.StoreStorage16,
+                        Instruction.StoreGlobal8 => Instruction.StoreStorage8,
+                        _ => Instruction.StoreStorage
+                    };
 
-                storageOp = new Operation(storeInst, null, sources);
+                    storageOp = new Operation(storeInst, null, sources);
+                }
+            }
+            else if (operation.Dest != null)
+            {
+                storageOp = new Operation(Instruction.Copy, operation.Dest, Const(0));
             }
 
             for (int index = 0; index < operation.SourcesCount; index++)
@@ -171,10 +184,18 @@ namespace Ryujinx.Graphics.Shader.Translation
             }
 
             LinkedListNode<INode> oldNode = node;
+            LinkedList<INode> oldNodeList = oldNode.List;
 
-            node = node.List.AddBefore(node, storageOp);
+            if (storageOp != null)
+            {
+                node = node.List.AddBefore(node, storageOp);
+            }
+            else
+            {
+                node = null;
+            }
 
-            node.List.Remove(oldNode);
+            oldNodeList.Remove(oldNode);
 
             return node;
         }