aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2023-02-10 11:47:59 -0300
committerGitHub <noreply@github.com>2023-02-10 11:47:59 -0300
commit61b1ce252f11e8f8e31080faee60d0a9d99cb67f (patch)
treee8a35bc52965183e0669cf31cf8a98408f3ec1b2
parent5f38086f9494a4ffbcb4b0ce4b7727ad8ac18b3e (diff)
Allow partially mapped textures with unmapped start (#4394)1.1.615
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TextureCache.cs7
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs32
2 files changed, 39 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 27bec786..f18de607 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -474,6 +474,13 @@ namespace Ryujinx.Graphics.Gpu.Image
{
address = memoryManager.Translate(info.GpuAddress);
+ // If the start address is unmapped, let's try to find a page of memory that is mapped.
+ if (address == MemoryManager.PteUnmapped)
+ {
+ address = memoryManager.TranslateFirstMapped(info.GpuAddress, (ulong)info.CalculateSizeInfo(layerSize).TotalSize);
+ }
+
+ // If address is still invalid, the texture is fully unmapped, so it has no data, just return null.
if (address == MemoryManager.PteUnmapped)
{
return null;
diff --git a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
index 0ac6160d..b0f7e799 100644
--- a/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/MemoryManager.cs
@@ -584,6 +584,38 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <summary>
+ /// Translates a GPU virtual address to a CPU virtual address on the first mapped page of memory
+ /// on the specified region.
+ /// If no page is mapped on the specified region, <see cref="PteUnmapped"/> is returned.
+ /// </summary>
+ /// <param name="va">GPU virtual address to be translated</param>
+ /// <param name="size">Size of the range to be translated</param>
+ /// <returns>CPU virtual address, or <see cref="PteUnmapped"/> if unmapped</returns>
+ public ulong TranslateFirstMapped(ulong va, ulong size)
+ {
+ if (!ValidateAddress(va))
+ {
+ return PteUnmapped;
+ }
+
+ ulong endVa = va + size;
+
+ ulong pte = GetPte(va);
+
+ for (; va < endVa && pte == PteUnmapped; va += PageSize - (va & PageMask))
+ {
+ pte = GetPte(va);
+ }
+
+ if (pte == PteUnmapped)
+ {
+ return PteUnmapped;
+ }
+
+ return UnpackPaFromPte(pte) + (va & PageMask);
+ }
+
+ /// <summary>
/// Gets the kind of a given memory page.
/// This might indicate the type of resource that can be allocated on the page, and also texture tiling.
/// </summary>