diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs index ace94442a..59b6d1e57 100644 --- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs +++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs @@ -310,6 +310,16 @@ namespace Ryujinx.Graphics.Gpu.Memory return PteUnmapped; } + /// + /// Checks if a given page is mapped. + /// + /// GPU virtual address of the page to check + /// True if the page is mapped, false otherwise + public bool IsMapped(ulong gpuVa) + { + return Translate(gpuVa) != PteUnmapped; + } + /// /// Translates a GPU virtual address to a CPU virtual address. /// diff --git a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs b/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs index d726bcb8b..310eee386 100644 --- a/Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs +++ b/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(address); } + /// + /// Checks if a given memory address is mapped. + /// + /// GPU virtual address to be checked + /// True if the address is mapped, false otherwise + public bool MemoryMapped(ulong address) + { + return _context.MemoryManager.IsMapped(address); + } + /// /// Queries Local Size X for compute shaders. /// diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs index e2c9212b3..a15d7f9ee 100644 --- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs +++ b/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(startAdddress + currBlock.EndAddress); + + return inst != 0UL; + } + private static bool BinarySearch(List blocks, ulong address, out int index) { index = 0; diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs index e10d869bf..59069302d 100644 --- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs +++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs @@ -9,6 +9,11 @@ T MemoryRead(ulong address) where T : unmanaged; + public bool MemoryMapped(ulong address) + { + return true; + } + public int QueryComputeLocalSizeX() { return 1;