Browse Source

Improve BRX target detection heuristics (#1591)

gdkchan 5 năm trước cách đây
mục cha
commit
0954e76a26

+ 10 - 0
Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs

@@ -310,6 +310,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
             return PteUnmapped;
         }
 
+        /// <summary>
+        /// Checks if a given page is mapped.
+        /// </summary>
+        /// <param name="gpuVa">GPU virtual address of the page to check</param>
+        /// <returns>True if the page is mapped, false otherwise</returns>
+        public bool IsMapped(ulong gpuVa)
+        {
+            return Translate(gpuVa) != PteUnmapped;
+        }
+
         /// <summary>
         /// Translates a GPU virtual address to a CPU virtual address.
         /// </summary>

+ 10 - 1
Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs

@@ -3,7 +3,6 @@ using Ryujinx.Graphics.GAL;
 using Ryujinx.Graphics.Gpu.Image;
 using Ryujinx.Graphics.Gpu.State;
 using Ryujinx.Graphics.Shader;
-using System;
 
 namespace Ryujinx.Graphics.Gpu.Shader
 {
@@ -84,6 +83,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
             return _context.MemoryManager.Read<T>(address);
         }
 
+        /// <summary>
+        /// Checks if a given memory address is mapped.
+        /// </summary>
+        /// <param name="address">GPU virtual address to be checked</param>
+        /// <returns>True if the address is mapped, false otherwise</returns>
+        public bool MemoryMapped(ulong address)
+        {
+            return _context.MemoryManager.IsMapped(address);
+        }
+
         /// <summary>
         /// Queries Local Size X for compute shaders.
         /// </summary>

+ 14 - 1
Ryujinx.Graphics.Shader/Decoders/Decoder.cs

@@ -128,7 +128,7 @@ namespace Ryujinx.Graphics.Shader.Decoders
                 }
 
                 // Do we have a block after the current one?
-                if (!IsExit(currBlock.GetLastOp()) && currBlock.BrIndir != null)
+                if (currBlock.BrIndir != null && HasBlockAfter(gpuAccessor, currBlock, startAddress))
                 {
                     bool targetVisited = visited.ContainsKey(currBlock.EndAddress);
 
@@ -154,6 +154,19 @@ namespace Ryujinx.Graphics.Shader.Decoders
             return blocks.ToArray();
         }
 
+        private static bool HasBlockAfter(IGpuAccessor gpuAccessor, Block currBlock, ulong startAdddress)
+        {
+            if (!gpuAccessor.MemoryMapped(startAdddress + currBlock.EndAddress) ||
+                !gpuAccessor.MemoryMapped(startAdddress + currBlock.EndAddress + 7))
+            {
+                return false;
+            }
+
+            ulong inst = gpuAccessor.MemoryRead<ulong>(startAdddress + currBlock.EndAddress);
+
+            return inst != 0UL;
+        }
+
         private static bool BinarySearch(List<Block> blocks, ulong address, out int index)
         {
             index = 0;

+ 5 - 0
Ryujinx.Graphics.Shader/IGpuAccessor.cs

@@ -9,6 +9,11 @@
 
         T MemoryRead<T>(ulong address) where T : unmanaged;
 
+        public bool MemoryMapped(ulong address)
+        {
+            return true;
+        }
+
         public int QueryComputeLocalSizeX()
         {
             return 1;