aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-10-03 02:43:33 -0300
committerGitHub <noreply@github.com>2020-10-03 15:43:33 +1000
commit0954e76a261235107b2255c33de595d188570274 (patch)
tree719e71e2938e808ca1164aa0da69f95d23248a88
parent86412ed30a5e28a7c11ba30c3987bdebeeb903c1 (diff)
Improve BRX target detection heuristics (#1591)
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs10
-rw-r--r--Ryujinx.Graphics.Gpu/Shader/GpuAccessor.cs11
-rw-r--r--Ryujinx.Graphics.Shader/Decoders/Decoder.cs15
-rw-r--r--Ryujinx.Graphics.Shader/IGpuAccessor.cs5
4 files changed, 39 insertions, 2 deletions
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
@@ -311,6 +311,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <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>
/// <param name="gpuVa">GPU virtual address to be translated</param>
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
{
@@ -85,6 +84,16 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
/// <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>
/// <returns>Local Size X</returns>
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<ulong>(startAdddress + currBlock.EndAddress);
+
+ return inst != 0UL;
+ }
+
private static bool BinarySearch(List<Block> 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<T>(ulong address) where T : unmanaged;
+ public bool MemoryMapped(ulong address)
+ {
+ return true;
+ }
+
public int QueryComputeLocalSizeX()
{
return 1;