diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
index ace94442..59b6d1e5 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 d726bcb8..310eee38 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 e2c9212b..a15d7f9e 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 e10d869b..59069302 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;