diff options
author | riperiperi <rhy3756547@hotmail.com> | 2022-06-17 17:09:14 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-17 13:09:14 -0300 |
commit | 99ffc061d30c92f224c6b839290e181b6179893d (patch) | |
tree | f25bd915077d9ce1844c4efcb38e59c96ee5f70e /Ryujinx.Graphics.Gpu/Image/TexturePool.cs | |
parent | d987cacfb720f2f4bc18958fc26ac0893903c090 (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.cs | 92 |
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(); |