aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2022-06-17 17:09:14 +0100
committerGitHub <noreply@github.com>2022-06-17 13:09:14 -0300
commit99ffc061d30c92f224c6b839290e181b6179893d (patch)
treef25bd915077d9ce1844c4efcb38e59c96ee5f70e /Ryujinx.Graphics.Gpu/Image/TexturePool.cs
parentd987cacfb720f2f4bc18958fc26ac0893903c090 (diff)
Optimize Texture Binding and Shader Specialization Checks (#3399)1.1.149
* Changes 1 * Changes 2 * Better ModifiedSequence handling This should handle PreciseEvents properly, and simplifies a few things. * Minor changes, remove debug log * Handle stage.Info being null Hopefully fixes Catherine crash * Fix shader specialization fast texture lookup * Fix some things. * Address Feedback Part 1 * Make method static.
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Image/TexturePool.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Image/TexturePool.cs92
1 files changed, 71 insertions, 21 deletions
diff --git a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
index 10a6ff82..75974c43 100644
--- a/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TexturePool.cs
@@ -14,6 +14,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{
private readonly GpuChannel _channel;
private readonly ConcurrentQueue<Texture> _dereferenceQueue = new ConcurrentQueue<Texture>();
+ private TextureDescriptor _defaultDescriptor;
/// <summary>
/// Intrusive linked list node used on the texture pool cache.
@@ -33,30 +34,19 @@ namespace Ryujinx.Graphics.Gpu.Image
}
/// <summary>
- /// Gets the texture with the given ID.
+ /// Gets the texture descripor and texture with the given ID with no bounds check or synchronization.
/// </summary>
/// <param name="id">ID of the texture. This is effectively a zero-based index</param>
- /// <returns>The texture with the given ID</returns>
- public override Texture Get(int id)
+ /// <param name="texture">The texture with the given ID</param>
+ /// <returns>The texture descriptor with the given ID</returns>
+ private ref readonly TextureDescriptor GetInternal(int id, out Texture texture)
{
- if ((uint)id >= Items.Length)
- {
- return null;
- }
-
- if (SequenceNumber != Context.SequenceNumber)
- {
- SequenceNumber = Context.SequenceNumber;
-
- SynchronizeMemory();
- }
+ texture = Items[id];
- Texture texture = Items[id];
+ ref readonly TextureDescriptor descriptor = ref GetDescriptorRef(id);
if (texture == null)
{
- TextureDescriptor descriptor = GetDescriptor(id);
-
TextureInfo info = GetInfo(descriptor, out int layerSize);
ProcessDereferenceQueue();
@@ -66,7 +56,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// If this happens, then the texture address is invalid, we can't add it to the cache.
if (texture == null)
{
- return null;
+ return ref descriptor;
}
texture.IncrementReferenceCount(this, id);
@@ -82,8 +72,6 @@ namespace Ryujinx.Graphics.Gpu.Image
// Texture changed size at one point - it may be a different size than the sampler expects.
// This can be triggered when the size is changed by a size hint on copy or draw, but the texture has been sampled before.
- TextureDescriptor descriptor = GetDescriptor(id);
-
int baseLevel = descriptor.UnpackBaseLevel();
int width = Math.Max(1, descriptor.UnpackWidth() >> baseLevel);
int height = Math.Max(1, descriptor.UnpackHeight() >> baseLevel);
@@ -98,10 +86,72 @@ namespace Ryujinx.Graphics.Gpu.Image
texture.SynchronizeMemory();
}
+ return ref descriptor;
+ }
+
+ /// <summary>
+ /// Gets the texture with the given ID.
+ /// </summary>
+ /// <param name="id">ID of the texture. This is effectively a zero-based index</param>
+ /// <returns>The texture with the given ID</returns>
+ public override Texture Get(int id)
+ {
+ if ((uint)id >= Items.Length)
+ {
+ return null;
+ }
+
+ if (SequenceNumber != Context.SequenceNumber)
+ {
+ SequenceNumber = Context.SequenceNumber;
+
+ SynchronizeMemory();
+ }
+
+ GetInternal(id, out Texture texture);
+
return texture;
}
/// <summary>
+ /// Gets the texture descriptor and texture with the given ID.
+ /// </summary>
+ /// <remarks>
+ /// This method assumes that the pool has been manually synchronized before doing binding.
+ /// </remarks>
+ /// <param name="id">ID of the texture. This is effectively a zero-based index</param>
+ /// <param name="texture">The texture with the given ID</param>
+ /// <returns>The texture descriptor with the given ID</returns>
+ public ref readonly TextureDescriptor GetForBinding(int id, out Texture texture)
+ {
+ if ((uint)id >= Items.Length)
+ {
+ texture = null;
+ return ref _defaultDescriptor;
+ }
+
+ // When getting for binding, assume the pool has already been synchronized.
+
+ return ref GetInternal(id, out texture);
+ }
+
+ /// <summary>
+ /// Checks if the pool was modified, and returns the last sequence number where a modification was detected.
+ /// </summary>
+ /// <returns>A number that increments each time a modification is detected</returns>
+ public int CheckModified()
+ {
+ if (SequenceNumber != Context.SequenceNumber)
+ {
+ SequenceNumber = Context.SequenceNumber;
+
+ SynchronizeMemory();
+ }
+
+ return ModifiedSequenceNumber;
+ }
+
+ /// <summary>
/// Forcibly remove a texture from this pool's items.
/// If deferred, the dereference will be queued to occur on the render thread.
/// </summary>
@@ -175,7 +225,7 @@ namespace Ryujinx.Graphics.Gpu.Image
/// <param name="descriptor">The texture descriptor</param>
/// <param name="layerSize">Layer size for textures using a sub-range of mipmap levels, otherwise 0</param>
/// <returns>The texture information</returns>
- private TextureInfo GetInfo(TextureDescriptor descriptor, out int layerSize)
+ private TextureInfo GetInfo(in TextureDescriptor descriptor, out int layerSize)
{
int depthOrLayers = descriptor.UnpackDepth();
int levels = descriptor.UnpackLevels();