aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Image
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Image')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/Texture.cs4
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs79
-rw-r--r--src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs10
3 files changed, 77 insertions, 16 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
index 84808a84..f0df55e6 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -1610,6 +1610,8 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary>
public void UpdatePoolMappings()
{
+ ChangedMapping = true;
+
lock (_poolOwners)
{
ulong address = 0;
@@ -1685,8 +1687,6 @@ namespace Ryujinx.Graphics.Gpu.Image
{
Group.ClearModified(unmapRange);
}
-
- UpdatePoolMappings();
}
/// <summary>
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>
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index 5277e789..dbcb2e75 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -272,7 +272,15 @@ namespace Ryujinx.Graphics.Gpu.Image
ulong address = descriptor.UnpackAddress();
- MultiRange range = _channel.MemoryManager.GetPhysicalRegions(address, texture.Size);
+ if (!descriptor.Equals(ref DescriptorCache[request.ID]))
+ {
+ // If the pool entry has already been replaced, just remove the texture.
+
+ texture.DecrementReferenceCount();
+ continue;
+ }
+
+ MultiRange range = _channel.MemoryManager.Physical.TextureCache.UpdatePartiallyMapped(_channel.MemoryManager, address, texture);
// If the texture is not mapped at all, delete its reference.