aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-05-01 19:32:32 +0100
committerGitHub <noreply@github.com>2023-05-01 15:32:32 -0300
commit36f10df775cf0c678548b97346432095823dfd8a (patch)
tree7a9c18eb0c50751082e5d8ad6d0b60c00e653e38 /src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
parent680e54802234c37b9e46633db328b3ecd1dd1f86 (diff)
GPU: Fix errors handling texture remapping (#4745)1.1.740
* GPU: Fix errors handling texture remapping - Fixes an error where a pool entry and memory mapping changing at the same time could cause a texture to rebind its data from the wrong GPU VA (data swaps) - Fixes an error where the texture pool could act on a mapping change before the mapping has actually been changed ("Unmapped" event happens before change, we need to signal it changed _after_ it completes) TODO: remove textures from partially mapped list... if they aren't. * Add Remap actions for handling post-mapping behaviours * Remove unused code. * Address feedback * Nit
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs79
1 files changed, 66 insertions, 13 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index c3243cf2..97d78a34 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
- /// Handles removal of textures written to a memory region being unmapped.
+ /// Handles marking of textures written to a memory region being (partially) remapped.
/// </summary>
/// <param name="sender">Sender object</param>
/// <param name="e">Event arguments</param>
@@ -80,26 +80,41 @@ namespace Ryujinx.Graphics.Gpu.Image
overlapCount = _textures.FindOverlaps(unmapped, ref overlaps);
}
- for (int i = 0; i < overlapCount; i++)
+ if (overlapCount > 0)
{
- overlaps[i].Unmapped(unmapped);
+ for (int i = 0; i < overlapCount; i++)
+ {
+ overlaps[i].Unmapped(unmapped);
+ }
}
- // If any range was previously unmapped, we also need to purge
- // all partially mapped texture, as they might be fully mapped now.
- for (int i = 0; i < unmapped.Count; i++)
+ lock (_partiallyMappedTextures)
{
- if (unmapped.GetSubRange(i).Address == MemoryManager.PteUnmapped)
+ if (overlapCount > 0 || _partiallyMappedTextures.Count > 0)
{
- lock (_partiallyMappedTextures)
+ e.AddRemapAction(() =>
{
- foreach (var texture in _partiallyMappedTextures)
+ lock (_partiallyMappedTextures)
{
- texture.Unmapped(unmapped);
- }
- }
+ if (overlapCount > 0)
+ {
+ for (int i = 0; i < overlapCount; i++)
+ {
+ _partiallyMappedTextures.Add(overlaps[i]);
+ }
+ }
- break;
+ // Any texture that has been unmapped at any point or is partially unmapped
+ // should update their pool references after the remap completes.
+
+ MultiRange unmapped = ((MemoryManager)sender).GetPhysicalRegions(e.Address, e.Size);
+
+ foreach (var texture in _partiallyMappedTextures)
+ {
+ texture.UpdatePoolMappings();
+ }
+ }
+ });
}
}
}
@@ -1136,6 +1151,44 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
+ /// Queries a texture's memory range and marks it as partially mapped or not.
+ /// Partially mapped textures re-evaluate their memory range after each time GPU memory is mapped.
+ /// </summary>
+ /// <param name="memoryManager">GPU memory manager where the texture is mapped</param>
+ /// <param name="address">The virtual address of the texture</param>
+ /// <param name="texture">The texture to be marked</param>
+ /// <returns>The physical regions for the texture, found when evaluating whether the texture was partially mapped</returns>
+ public MultiRange UpdatePartiallyMapped(MemoryManager memoryManager, ulong address, Texture texture)
+ {
+ MultiRange range;
+ lock (_partiallyMappedTextures)
+ {
+ range = memoryManager.GetPhysicalRegions(address, texture.Size);
+ bool partiallyMapped = false;
+
+ for (int i = 0; i < range.Count; i++)
+ {
+ if (range.GetSubRange(i).Address == MemoryManager.PteUnmapped)
+ {
+ partiallyMapped = true;
+ break;
+ }
+ }
+
+ if (partiallyMapped)
+ {
+ _partiallyMappedTextures.Add(texture);
+ }
+ else
+ {
+ _partiallyMappedTextures.Remove(texture);
+ }
+ }
+
+ return range;
+ }
+
+ /// <summary>
/// Adds a texture to the short duration cache. This typically keeps it alive for two ticks.
/// </summary>
/// <param name="texture">Texture to add to the short cache</param>