diff --git a/Ryujinx.Graphics.Gpu/Image/Pool.cs b/Ryujinx.Graphics.Gpu/Image/Pool.cs
index c2c1a9a1..c5aef77f 100644
--- a/Ryujinx.Graphics.Gpu/Image/Pool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Pool.cs
@@ -8,14 +8,16 @@ namespace Ryujinx.Graphics.Gpu.Image
///
/// Represents a pool of GPU resources, such as samplers or textures.
///
- /// Type of the GPU resource
- abstract class Pool : IDisposable
+ /// Type of the GPU resource
+ /// Type of the descriptor
+ abstract class Pool : IDisposable where T2 : unmanaged
{
protected const int DescriptorSize = 0x20;
protected GpuContext Context;
- protected T[] Items;
+ protected T1[] Items;
+ protected T2[] DescriptorCache;
///
/// The maximum ID value of resources on the pool (inclusive).
@@ -47,7 +49,8 @@ namespace Ryujinx.Graphics.Gpu.Image
ulong size = (ulong)(uint)count * DescriptorSize;
- Items = new T[count];
+ Items = new T1[count];
+ DescriptorCache = new T2[count];
Address = address;
Size = size;
@@ -56,12 +59,23 @@ namespace Ryujinx.Graphics.Gpu.Image
_modifiedDelegate = RegionModified;
}
+
+ ///
+ /// Gets the descriptor for a given ID.
+ ///
+ /// ID of the descriptor. This is effectively a zero-based index
+ /// The descriptor
+ public T2 GetDescriptor(int id)
+ {
+ return Context.PhysicalMemory.Read(Address + (ulong)id * DescriptorSize);
+ }
+
///
/// Gets the GPU resource with the given ID.
///
/// ID of the resource. This is effectively a zero-based index
/// The GPU resource with the given ID
- public abstract T Get(int id);
+ public abstract T1 Get(int id);
///
/// Synchronizes host memory with guest memory.
@@ -97,7 +111,7 @@ namespace Ryujinx.Graphics.Gpu.Image
protected abstract void InvalidateRangeImpl(ulong address, ulong size);
- protected abstract void Delete(T item);
+ protected abstract void Delete(T1 item);
///
/// Performs the disposal of all resources stored on the pool.
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs b/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
index 2c28b743..64a146fb 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerDescriptor.cs
@@ -1,4 +1,6 @@
using Ryujinx.Graphics.GAL;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
namespace Ryujinx.Graphics.Gpu.Image
{
@@ -244,5 +246,15 @@ namespace Ryujinx.Graphics.Gpu.Image
{
return ((Word2 >> 12) & 0xfff) * Frac8ToF32;
}
+
+ ///
+ /// Check if two descriptors are equal.
+ ///
+ /// The descriptor to compare against
+ /// True if they are equal, false otherwise
+ public bool Equals(ref SamplerDescriptor other)
+ {
+ return Unsafe.As>(ref this).Equals(Unsafe.As>(ref other));
+ }
}
}
diff --git a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
index ca13a7d6..1395aea2 100644
--- a/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/SamplerPool.cs
@@ -3,7 +3,7 @@ namespace Ryujinx.Graphics.Gpu.Image
///
/// Sampler pool.
///
- class SamplerPool : Pool
+ class SamplerPool : Pool
{
private int _sequenceNumber;
@@ -38,11 +38,13 @@ namespace Ryujinx.Graphics.Gpu.Image
if (sampler == null)
{
- SamplerDescriptor descriptor = Context.PhysicalMemory.Read(Address + (ulong)id * DescriptorSize);
+ SamplerDescriptor descriptor = GetDescriptor(id);
sampler = new Sampler(Context, descriptor);
Items[id] = sampler;
+
+ DescriptorCache[id] = descriptor;
}
return sampler;
@@ -65,6 +67,14 @@ namespace Ryujinx.Graphics.Gpu.Image
if (sampler != null)
{
+ SamplerDescriptor descriptor = GetDescriptor(id);
+
+ // If the descriptors are the same, the sampler is still valid.
+ if (descriptor.Equals(ref DescriptorCache[id]))
+ {
+ continue;
+ }
+
sampler.Dispose();
Items[id] = null;
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
index 76d97bf8..e85df136 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureDescriptor.cs
@@ -1,4 +1,6 @@
using Ryujinx.Graphics.Gpu.Shader.Cache.Definition;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
namespace Ryujinx.Graphics.Gpu.Image
{
@@ -248,5 +250,15 @@ namespace Ryujinx.Graphics.Gpu.Image
return result;
}
+
+ ///
+ /// Check if two descriptors are equal.
+ ///
+ /// The descriptor to compare against
+ /// True if they are equal, false otherwise
+ public bool Equals(ref TextureDescriptor other)
+ {
+ return Unsafe.As>(ref this).Equals(Unsafe.As>(ref other));
+ }
}
}
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index dfcd8a52..58e881ca 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -1,6 +1,5 @@
using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
-using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Texture;
using System;
using System.Collections.Generic;
@@ -10,7 +9,7 @@ namespace Ryujinx.Graphics.Gpu.Image
///
/// Texture pool.
///
- class TexturePool : Pool
+ class TexturePool : Pool
{
private int _sequenceNumber;
@@ -65,6 +64,8 @@ namespace Ryujinx.Graphics.Gpu.Image
texture.IncrementReferenceCount();
Items[id] = texture;
+
+ DescriptorCache[id] = descriptor;
}
else
{
@@ -91,16 +92,6 @@ namespace Ryujinx.Graphics.Gpu.Image
return texture;
}
- ///
- /// Gets the texture descriptor from a given texture ID.
- ///
- /// ID of the texture. This is effectively a zero-based index
- /// The texture descriptor
- public TextureDescriptor GetDescriptor(int id)
- {
- return Context.PhysicalMemory.Read(Address + (ulong)id * DescriptorSize);
- }
-
///
/// Implementation of the texture pool range invalidation.
///
@@ -122,8 +113,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// If the descriptors are the same, the texture is the same,
// we don't need to remove as it was not modified. Just continue.
- if (texture.Info.GpuAddress == descriptor.UnpackAddress() &&
- texture.IsExactMatch(GetInfo(descriptor, out _), TextureSearchFlags.Strict) != TextureMatchQuality.NoMatch)
+ if (descriptor.Equals(ref DescriptorCache[id]))
{
continue;
}