diff --git a/src/Ryujinx.Graphics.GAL/IImageArray.cs b/src/Ryujinx.Graphics.GAL/IImageArray.cs index 30cff50b15..d119aa9fbd 100644 --- a/src/Ryujinx.Graphics.GAL/IImageArray.cs +++ b/src/Ryujinx.Graphics.GAL/IImageArray.cs @@ -1,6 +1,8 @@ +using System; + namespace Ryujinx.Graphics.GAL { - public interface IImageArray + public interface IImageArray : IDisposable { void SetFormats(int index, Format[] imageFormats); void SetImages(int index, ITexture[] images); diff --git a/src/Ryujinx.Graphics.GAL/ITextureArray.cs b/src/Ryujinx.Graphics.GAL/ITextureArray.cs index 35c2116b54..9ee79dacbb 100644 --- a/src/Ryujinx.Graphics.GAL/ITextureArray.cs +++ b/src/Ryujinx.Graphics.GAL/ITextureArray.cs @@ -1,6 +1,8 @@ +using System; + namespace Ryujinx.Graphics.GAL { - public interface ITextureArray + public interface ITextureArray : IDisposable { void SetSamplers(int index, ISampler[] samplers); void SetTextures(int index, ITexture[] textures); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs b/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs index edaae3042d..ef227d4a54 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/CommandHelper.cs @@ -66,6 +66,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading Register(CommandType.CounterEventDispose); Register(CommandType.CounterEventFlush); + Register(CommandType.ImageArrayDispose); Register(CommandType.ImageArraySetFormats); Register(CommandType.ImageArraySetImages); @@ -88,6 +89,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading Register(CommandType.TextureSetDataSliceRegion); Register(CommandType.TextureSetStorage); + Register(CommandType.TextureArrayDispose); Register(CommandType.TextureArraySetSamplers); Register(CommandType.TextureArraySetTextures); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs b/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs index 7586953526..cf3f5d6c14 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/CommandType.cs @@ -26,6 +26,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading CounterEventDispose, CounterEventFlush, + ImageArrayDispose, ImageArraySetFormats, ImageArraySetImages, @@ -48,6 +49,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading TextureSetDataSliceRegion, TextureSetStorage, + TextureArrayDispose, TextureArraySetSamplers, TextureArraySetTextures, diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArrayDisposeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArrayDisposeCommand.cs new file mode 100644 index 0000000000..ac2ac933b7 --- /dev/null +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/ImageArray/ImageArrayDisposeCommand.cs @@ -0,0 +1,21 @@ +using Ryujinx.Graphics.GAL.Multithreading.Model; +using Ryujinx.Graphics.GAL.Multithreading.Resources; + +namespace Ryujinx.Graphics.GAL.Multithreading.Commands.ImageArray +{ + struct ImageArrayDisposeCommand : IGALCommand, IGALCommand + { + public readonly CommandType CommandType => CommandType.ImageArrayDispose; + private TableRef _imageArray; + + public void Set(TableRef imageArray) + { + _imageArray = imageArray; + } + + public static void Run(ref ImageArrayDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer) + { + command._imageArray.Get(threaded).Base.Dispose(); + } + } +} diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArrayDisposeCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArrayDisposeCommand.cs new file mode 100644 index 0000000000..fec1c48f0d --- /dev/null +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArrayDisposeCommand.cs @@ -0,0 +1,21 @@ +using Ryujinx.Graphics.GAL.Multithreading.Model; +using Ryujinx.Graphics.GAL.Multithreading.Resources; + +namespace Ryujinx.Graphics.GAL.Multithreading.Commands.TextureArray +{ + struct TextureArrayDisposeCommand : IGALCommand, IGALCommand + { + public readonly CommandType CommandType => CommandType.TextureArrayDispose; + private TableRef _textureArray; + + public void Set(TableRef textureArray) + { + _textureArray = textureArray; + } + + public static void Run(ref TextureArrayDisposeCommand command, ThreadedRenderer threaded, IRenderer renderer) + { + command._textureArray.Get(threaded).Base.Dispose(); + } + } +} diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureAndSamplerArray/TextureArraySetSamplersCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArraySetSamplersCommand.cs similarity index 100% rename from src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureAndSamplerArray/TextureArraySetSamplersCommand.cs rename to src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArraySetSamplersCommand.cs diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureAndSamplerArray/TextureArraySetTexturesCommand.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArraySetTexturesCommand.cs similarity index 100% rename from src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureAndSamplerArray/TextureArraySetTexturesCommand.cs rename to src/Ryujinx.Graphics.GAL/Multithreading/Commands/TextureArray/TextureArraySetTexturesCommand.cs diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs index d26ee1fbd5..19bc6f233a 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedImageArray.cs @@ -21,6 +21,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } + public void Dispose() + { + _renderer.New().Set(Ref(this)); + _renderer.QueueCommand(); + } + public void SetFormats(int index, Format[] imageFormats) { _renderer.New().Set(Ref(this), index, Ref(imageFormats)); diff --git a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs index 82405a1f69..4334c70484 100644 --- a/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs +++ b/src/Ryujinx.Graphics.GAL/Multithreading/Resources/ThreadedTextureArray.cs @@ -22,6 +22,12 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Resources return new TableRef(_renderer, reference); } + public void Dispose() + { + _renderer.New().Set(Ref(this)); + _renderer.QueueCommand(); + } + public void SetSamplers(int index, ISampler[] samplers) { _renderer.New().Set(Ref(this), index, Ref(samplers.ToArray())); diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs index 18e28b3dd7..01e34c7771 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureBindingsArrayCache.cs @@ -1113,6 +1113,15 @@ namespace Ryujinx.Graphics.Gpu.Image nextNode = nextNode.Next; _cacheFromBuffer.Remove(toRemove.Value.Key); _lruCache.Remove(toRemove); + + if (toRemove.Value.Key.IsImage) + { + toRemove.Value.ImageArray.Dispose(); + } + else + { + toRemove.Value.TextureArray.Dispose(); + } } } @@ -1124,11 +1133,20 @@ namespace Ryujinx.Graphics.Gpu.Image { List keysToRemove = null; - foreach (CacheEntryFromPoolKey key in _cacheFromPool.Keys) + foreach ((CacheEntryFromPoolKey key, CacheEntry entry) in _cacheFromPool) { if (key.MatchesPool(pool)) { (keysToRemove ??= new()).Add(key); + + if (key.IsImage) + { + entry.ImageArray.Dispose(); + } + else + { + entry.TextureArray.Dispose(); + } } } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs b/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs index 1c5acedf3a..6198823d9d 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/ImageArray.cs @@ -63,5 +63,9 @@ namespace Ryujinx.Graphics.OpenGL.Image } } } + + public void Dispose() + { + } } } diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureArray.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureArray.cs index d70b0a0081..41ac058c1c 100644 --- a/src/Ryujinx.Graphics.OpenGL/Image/TextureArray.cs +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureArray.cs @@ -48,5 +48,9 @@ namespace Ryujinx.Graphics.OpenGL.Image } } } + + public void Dispose() + { + } } } diff --git a/src/Ryujinx.Graphics.Vulkan/ImageArray.cs b/src/Ryujinx.Graphics.Vulkan/ImageArray.cs index 3c7f321ff7..e42750d3ce 100644 --- a/src/Ryujinx.Graphics.Vulkan/ImageArray.cs +++ b/src/Ryujinx.Graphics.Vulkan/ImageArray.cs @@ -2,11 +2,10 @@ using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; using System; using System.Collections.Generic; -using System.Diagnostics; namespace Ryujinx.Graphics.Vulkan { - class ImageArray : IImageArray + class ImageArray : ResourceArray, IImageArray { private readonly VulkanRenderer _gd; @@ -25,19 +24,11 @@ namespace Ryujinx.Graphics.Vulkan private HashSet _storages; - private DescriptorSet[] _cachedDescriptorSets; - private int _cachedCommandBufferIndex; private int _cachedSubmissionCount; - private ShaderCollection _cachedDscProgram; - private int _cachedDscSetIndex; - private int _cachedDscIndex; - private readonly bool _isBuffer; - private int _bindCount; - public ImageArray(VulkanRenderer gd, int size, bool isBuffer) { _gd = gd; @@ -104,12 +95,7 @@ namespace Ryujinx.Graphics.Vulkan { _cachedCommandBufferIndex = -1; _storages = null; - _cachedDescriptorSets = null; - - if (_bindCount != 0) - { - _gd.PipelineInternal.ForceImageDirty(); - } + SetDirty(_gd); } public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags) @@ -195,7 +181,7 @@ namespace Ryujinx.Graphics.Vulkan int setIndex, TextureView dummyTexture) { - if (_cachedDescriptorSets != null) + if (TryGetCachedDescriptorSets(cbs, program, setIndex, out DescriptorSet[] sets)) { // We still need to ensure the current command buffer holds a reference to all used textures. @@ -208,12 +194,9 @@ namespace Ryujinx.Graphics.Vulkan GetBufferViews(cbs); } - return _cachedDescriptorSets; + return sets; } - _cachedDscProgram?.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex); - var dsc = program.GetNewManualDescriptorSetCollection(cbs.CommandBufferIndex, setIndex, out _cachedDscIndex).Get(cbs); - DescriptorSetTemplate template = program.Templates[setIndex]; DescriptorSetTemplateWriter tu = templateUpdater.Begin(template); @@ -227,24 +210,9 @@ namespace Ryujinx.Graphics.Vulkan tu.Push(GetBufferViews(cbs)); } - var sets = dsc.GetSets(); templateUpdater.Commit(_gd, device, sets[0]); - _cachedDescriptorSets = sets; - _cachedDscProgram = program; - _cachedDscSetIndex = setIndex; return sets; } - - public void IncrementBindCount() - { - _bindCount++; - } - - public void DecrementBindCount() - { - int newBindCount = --_bindCount; - Debug.Assert(newBindCount >= 0); - } } } diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCacheEntry.cs b/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCacheEntry.cs index 7d0948d6e6..fc7ddafa4f 100644 --- a/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCacheEntry.cs +++ b/src/Ryujinx.Graphics.Vulkan/PipelineLayoutCacheEntry.cs @@ -3,6 +3,7 @@ using Silk.NET.Vulkan; using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Runtime.InteropServices; namespace Ryujinx.Graphics.Vulkan @@ -31,20 +32,37 @@ namespace Ryujinx.Graphics.Vulkan private struct ManualDescriptorSetEntry { public Auto DescriptorSet; - public int CbIndex; - public int CbSubmissionCount; + public uint CbRefMask; public bool InUse; - public ManualDescriptorSetEntry(Auto descriptorSet, int cbIndex, int cbSubmissionCount, bool inUse) + public ManualDescriptorSetEntry(Auto descriptorSet, int cbIndex) { DescriptorSet = descriptorSet; - CbIndex = cbIndex; - CbSubmissionCount = cbSubmissionCount; - InUse = inUse; + CbRefMask = 1u << cbIndex; + InUse = true; + } + } + + private struct PendingManualDsConsumption + { + public FenceHolder Fence { get; } + public int CommandBufferIndex { get; } + public int SetIndex { get; } + public int CacheIndex { get; } + + public PendingManualDsConsumption(FenceHolder fence, int commandBufferIndex, int setIndex, int cacheIndex) + { + Fence = fence; + CommandBufferIndex = commandBufferIndex; + SetIndex = setIndex; + CacheIndex = cacheIndex; + fence.Get(); } } private readonly List[] _manualDsCache; + private readonly Queue _pendingManualDsConsumptions; + private readonly Queue[] _freeManualDsCacheEntries; private readonly Dictionary _pdTemplates; private readonly ResourceDescriptorCollection _pdDescriptors; @@ -70,6 +88,8 @@ namespace Ryujinx.Graphics.Vulkan _dsCacheCursor = new int[setsCount]; _manualDsCache = new List[setsCount]; + _pendingManualDsConsumptions = new Queue(); + _freeManualDsCacheEntries = new Queue[setsCount]; } public PipelineLayoutCacheEntry( @@ -144,29 +164,32 @@ namespace Ryujinx.Graphics.Vulkan return list[index]; } - public Auto GetNewManualDescriptorSetCollection(int commandBufferIndex, int setIndex, out int cacheIndex) + public Auto GetNewManualDescriptorSetCollection(CommandBufferScoped cbs, int setIndex, out int cacheIndex) { - int submissionCount = _gd.CommandBufferPool.GetSubmissionCount(commandBufferIndex); + FreeCompletedManualDescriptorSets(); var list = _manualDsCache[setIndex] ??= new(); var span = CollectionsMarshal.AsSpan(list); - for (int index = 0; index < span.Length; index++) + Queue freeQueue = _freeManualDsCacheEntries[setIndex]; + + // Do we have at least one freed descriptor set? If so, just use that. + if (freeQueue != null && freeQueue.TryDequeue(out int freeIndex)) { - ref ManualDescriptorSetEntry entry = ref span[index]; + ref ManualDescriptorSetEntry entry = ref span[freeIndex]; - if (!entry.InUse && (entry.CbIndex != commandBufferIndex || entry.CbSubmissionCount != submissionCount)) - { - entry.InUse = true; - entry.CbIndex = commandBufferIndex; - entry.CbSubmissionCount = submissionCount; + Debug.Assert(!entry.InUse && entry.CbRefMask == 0); - cacheIndex = index; + entry.InUse = true; + entry.CbRefMask = 1u << cbs.CommandBufferIndex; + cacheIndex = freeIndex; - return entry.DescriptorSet; - } + _pendingManualDsConsumptions.Enqueue(new PendingManualDsConsumption(cbs.GetFence(), cbs.CommandBufferIndex, setIndex, freeIndex)); + + return entry.DescriptorSet; } + // Otherwise create a new descriptor set, and add to our pending queue for command buffer consumption tracking. var dsc = _descriptorSetManager.AllocateDescriptorSet( _gd.Api, DescriptorSetLayouts[setIndex], @@ -176,17 +199,64 @@ namespace Ryujinx.Graphics.Vulkan false); cacheIndex = list.Count; - list.Add(new ManualDescriptorSetEntry(dsc, commandBufferIndex, submissionCount, inUse: true)); + list.Add(new ManualDescriptorSetEntry(dsc, cbs.CommandBufferIndex)); + _pendingManualDsConsumptions.Enqueue(new PendingManualDsConsumption(cbs.GetFence(), cbs.CommandBufferIndex, setIndex, cacheIndex)); return dsc; } + public void UpdateManualDescriptorSetCollectionOwnership(CommandBufferScoped cbs, int setIndex, int cacheIndex) + { + FreeCompletedManualDescriptorSets(); + + var list = _manualDsCache[setIndex]; + var span = CollectionsMarshal.AsSpan(list); + ref var entry = ref span[cacheIndex]; + + uint cbMask = 1u << cbs.CommandBufferIndex; + + if ((entry.CbRefMask & cbMask) == 0) + { + entry.CbRefMask |= cbMask; + + _pendingManualDsConsumptions.Enqueue(new PendingManualDsConsumption(cbs.GetFence(), cbs.CommandBufferIndex, setIndex, cacheIndex)); + } + } + + private void FreeCompletedManualDescriptorSets() + { + FenceHolder signalledFence = null; + while (_pendingManualDsConsumptions.TryPeek(out var pds) && (pds.Fence == signalledFence || pds.Fence.IsSignaled())) + { + signalledFence = pds.Fence; // Already checked - don't need to do it again. + var dequeued = _pendingManualDsConsumptions.Dequeue(); + Debug.Assert(dequeued.Fence == pds.Fence); + pds.Fence.Put(); + + var span = CollectionsMarshal.AsSpan(_manualDsCache[dequeued.SetIndex]); + ref var entry = ref span[dequeued.CacheIndex]; + entry.CbRefMask &= ~(1u << dequeued.CommandBufferIndex); + + if (!entry.InUse && entry.CbRefMask == 0) + { + // If not in use by any array, and not bound to any command buffer, the descriptor set can be re-used immediately. + (_freeManualDsCacheEntries[dequeued.SetIndex] ??= new()).Enqueue(dequeued.CacheIndex); + } + } + } + public void ReleaseManualDescriptorSetCollection(int setIndex, int cacheIndex) { var list = _manualDsCache[setIndex]; var span = CollectionsMarshal.AsSpan(list); span[cacheIndex].InUse = false; + + if (span[cacheIndex].CbRefMask == 0) + { + // This is no longer in use by any array, so if not bound to any command buffer, the descriptor set can be re-used immediately. + (_freeManualDsCacheEntries[setIndex] ??= new()).Enqueue(cacheIndex); + } } private static Span GetDescriptorPoolSizes(Span output, ResourceDescriptorCollection setDescriptor, uint multiplier) @@ -291,6 +361,11 @@ namespace Ryujinx.Graphics.Vulkan _gd.Api.DestroyDescriptorSetLayout(_device, DescriptorSetLayouts[i], null); } + while (_pendingManualDsConsumptions.TryDequeue(out var pds)) + { + pds.Fence.Put(); + } + _descriptorSetManager.Dispose(); } } diff --git a/src/Ryujinx.Graphics.Vulkan/ResourceArray.cs b/src/Ryujinx.Graphics.Vulkan/ResourceArray.cs new file mode 100644 index 0000000000..0880a10f07 --- /dev/null +++ b/src/Ryujinx.Graphics.Vulkan/ResourceArray.cs @@ -0,0 +1,74 @@ +using Silk.NET.Vulkan; +using System; +using System.Diagnostics; + +namespace Ryujinx.Graphics.Vulkan +{ + class ResourceArray : IDisposable + { + private DescriptorSet[] _cachedDescriptorSets; + + private ShaderCollection _cachedDscProgram; + private int _cachedDscSetIndex; + private int _cachedDscIndex; + + private int _bindCount; + + protected void SetDirty(VulkanRenderer gd) + { + ReleaseDescriptorSet(); + + if (_bindCount != 0) + { + gd.PipelineInternal.ForceTextureDirty(); + } + } + + public bool TryGetCachedDescriptorSets(CommandBufferScoped cbs, ShaderCollection program, int setIndex, out DescriptorSet[] sets) + { + if (_cachedDescriptorSets != null) + { + _cachedDscProgram.UpdateManualDescriptorSetCollectionOwnership(cbs, _cachedDscSetIndex, _cachedDscIndex); + + sets = _cachedDescriptorSets; + + return true; + } + + var dsc = program.GetNewManualDescriptorSetCollection(cbs, setIndex, out _cachedDscIndex).Get(cbs); + + sets = dsc.GetSets(); + + _cachedDescriptorSets = sets; + _cachedDscProgram = program; + _cachedDscSetIndex = setIndex; + + return false; + } + + public void IncrementBindCount() + { + _bindCount++; + } + + public void DecrementBindCount() + { + int newBindCount = --_bindCount; + Debug.Assert(newBindCount >= 0); + } + + private void ReleaseDescriptorSet() + { + if (_cachedDescriptorSets != null) + { + _cachedDscProgram.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex); + _cachedDescriptorSets = null; + } + } + + public void Dispose() + { + ReleaseDescriptorSet(); + } + } +} diff --git a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs index f2d648a517..f9637789e3 100644 --- a/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs +++ b/src/Ryujinx.Graphics.Vulkan/ShaderCollection.cs @@ -604,9 +604,14 @@ namespace Ryujinx.Graphics.Vulkan return _plce.GetNewDescriptorSetCollection(setIndex, out isNew); } - public Auto GetNewManualDescriptorSetCollection(int commandBufferIndex, int setIndex, out int cacheIndex) + public Auto GetNewManualDescriptorSetCollection(CommandBufferScoped cbs, int setIndex, out int cacheIndex) { - return _plce.GetNewManualDescriptorSetCollection(commandBufferIndex, setIndex, out cacheIndex); + return _plce.GetNewManualDescriptorSetCollection(cbs, setIndex, out cacheIndex); + } + + public void UpdateManualDescriptorSetCollectionOwnership(CommandBufferScoped cbs, int setIndex, int cacheIndex) + { + _plce.UpdateManualDescriptorSetCollectionOwnership(cbs, setIndex, cacheIndex); } public void ReleaseManualDescriptorSetCollection(int setIndex, int cacheIndex) diff --git a/src/Ryujinx.Graphics.Vulkan/TextureArray.cs b/src/Ryujinx.Graphics.Vulkan/TextureArray.cs index fe834225c5..31c408d64f 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureArray.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureArray.cs @@ -2,11 +2,10 @@ using Ryujinx.Graphics.GAL; using Silk.NET.Vulkan; using System; using System.Collections.Generic; -using System.Diagnostics; namespace Ryujinx.Graphics.Vulkan { - class TextureArray : ITextureArray + class TextureArray : ResourceArray, ITextureArray { private readonly VulkanRenderer _gd; @@ -25,19 +24,11 @@ namespace Ryujinx.Graphics.Vulkan private HashSet _storages; - private DescriptorSet[] _cachedDescriptorSets; - private int _cachedCommandBufferIndex; private int _cachedSubmissionCount; - private ShaderCollection _cachedDscProgram; - private int _cachedDscSetIndex; - private int _cachedDscIndex; - private readonly bool _isBuffer; - private int _bindCount; - public TextureArray(VulkanRenderer gd, int size, bool isBuffer) { _gd = gd; @@ -113,12 +104,7 @@ namespace Ryujinx.Graphics.Vulkan { _cachedCommandBufferIndex = -1; _storages = null; - _cachedDescriptorSets = null; - - if (_bindCount != 0) - { - _gd.PipelineInternal.ForceTextureDirty(); - } + SetDirty(_gd); } public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags) @@ -211,7 +197,7 @@ namespace Ryujinx.Graphics.Vulkan TextureView dummyTexture, SamplerHolder dummySampler) { - if (_cachedDescriptorSets != null) + if (TryGetCachedDescriptorSets(cbs, program, setIndex, out DescriptorSet[] sets)) { // We still need to ensure the current command buffer holds a reference to all used textures. @@ -224,12 +210,9 @@ namespace Ryujinx.Graphics.Vulkan GetBufferViews(cbs); } - return _cachedDescriptorSets; + return sets; } - _cachedDscProgram?.ReleaseManualDescriptorSetCollection(_cachedDscSetIndex, _cachedDscIndex); - var dsc = program.GetNewManualDescriptorSetCollection(cbs.CommandBufferIndex, setIndex, out _cachedDscIndex).Get(cbs); - DescriptorSetTemplate template = program.Templates[setIndex]; DescriptorSetTemplateWriter tu = templateUpdater.Begin(template); @@ -243,24 +226,9 @@ namespace Ryujinx.Graphics.Vulkan tu.Push(GetBufferViews(cbs)); } - var sets = dsc.GetSets(); templateUpdater.Commit(_gd, device, sets[0]); - _cachedDescriptorSets = sets; - _cachedDscProgram = program; - _cachedDscSetIndex = setIndex; return sets; } - - public void IncrementBindCount() - { - _bindCount++; - } - - public void DecrementBindCount() - { - int newBindCount = --_bindCount; - Debug.Assert(newBindCount >= 0); - } } }