diff options
author | riperiperi <rhy3756547@hotmail.com> | 2024-02-17 03:21:37 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-17 00:21:37 -0300 |
commit | 31ed061beae779b0a750e1344c76a75af8275f91 (patch) | |
tree | e98519a8ab7bf6bc804d950c3ffc8c6c107928fd /src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs | |
parent | 4218311e6aa2a6b134e56f4206f9ef87d863419e (diff) |
Vulkan: Improve texture barrier usage, timing and batching (#6240)1.1.1199
* WIP barrier batch
* Add store op to image usage barrier
* Dispose the barrier batch
* Fix encoding?
* Handle read and write on the load op barrier.
Load op consumes read accesses but does not add one, as the only other operation that can read is another load.
* Simplify null check
* Insert barriers on program change in case stale bindings are reintroduced
* Not sure how I messed this one up
* Improve location of bindings barrier update
This is also important for emergency deferred clear
* Update src/Ryujinx.Graphics.Vulkan/BarrierBatch.cs
Co-authored-by: Mary Guillemard <thog@protonmail.com>
---------
Co-authored-by: Mary Guillemard <thog@protonmail.com>
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs | 102 |
1 files changed, 81 insertions, 21 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index d40b201d..946e3bc1 100644 --- a/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -35,6 +35,36 @@ namespace Ryujinx.Graphics.Vulkan } } + private record struct TextureRef + { + public ShaderStage Stage; + public TextureStorage Storage; + public Auto<DisposableImageView> View; + public Auto<DisposableSampler> Sampler; + + public TextureRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view, Auto<DisposableSampler> sampler) + { + Stage = stage; + Storage = storage; + View = view; + Sampler = sampler; + } + } + + private record struct ImageRef + { + public ShaderStage Stage; + public TextureStorage Storage; + public Auto<DisposableImageView> View; + + public ImageRef(ShaderStage stage, TextureStorage storage, Auto<DisposableImageView> view) + { + Stage = stage; + Storage = storage; + View = view; + } + } + private readonly VulkanRenderer _gd; private readonly Device _device; private readonly PipelineBase _pipeline; @@ -42,9 +72,8 @@ namespace Ryujinx.Graphics.Vulkan private readonly BufferRef[] _uniformBufferRefs; private readonly BufferRef[] _storageBufferRefs; - private readonly Auto<DisposableImageView>[] _textureRefs; - private readonly Auto<DisposableSampler>[] _samplerRefs; - private readonly Auto<DisposableImageView>[] _imageRefs; + private readonly TextureRef[] _textureRefs; + private readonly ImageRef[] _imageRefs; private readonly TextureBuffer[] _bufferTextureRefs; private readonly TextureBuffer[] _bufferImageRefs; private readonly Format[] _bufferImageFormats; @@ -95,9 +124,8 @@ namespace Ryujinx.Graphics.Vulkan _uniformBufferRefs = new BufferRef[Constants.MaxUniformBufferBindings]; _storageBufferRefs = new BufferRef[Constants.MaxStorageBufferBindings]; - _textureRefs = new Auto<DisposableImageView>[Constants.MaxTextureBindings * 2]; - _samplerRefs = new Auto<DisposableSampler>[Constants.MaxTextureBindings * 2]; - _imageRefs = new Auto<DisposableImageView>[Constants.MaxImageBindings * 2]; + _textureRefs = new TextureRef[Constants.MaxTextureBindings * 2]; + _imageRefs = new ImageRef[Constants.MaxImageBindings * 2]; _bufferTextureRefs = new TextureBuffer[Constants.MaxTextureBindings * 2]; _bufferImageRefs = new TextureBuffer[Constants.MaxImageBindings * 2]; _bufferImageFormats = new Format[Constants.MaxImageBindings * 2]; @@ -229,6 +257,33 @@ namespace Ryujinx.Graphics.Vulkan }); } + public void InsertBindingBarriers(CommandBufferScoped cbs) + { + foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.TextureSetIndex]) + { + if (segment.Type == ResourceType.TextureAndSampler) + { + for (int i = 0; i < segment.Count; i++) + { + ref var texture = ref _textureRefs[segment.Binding + i]; + texture.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, texture.Stage.ConvertToPipelineStageFlags()); + } + } + } + + foreach (ResourceBindingSegment segment in _program.BindingSegments[PipelineBase.ImageSetIndex]) + { + if (segment.Type == ResourceType.Image) + { + for (int i = 0; i < segment.Count; i++) + { + ref var image = ref _imageRefs[segment.Binding + i]; + image.Storage?.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, image.Stage.ConvertToPipelineStageFlags()); + } + } + } + } + public void AdvancePdSequence() { if (++_pdSequence == 0) @@ -258,7 +313,12 @@ namespace Ryujinx.Graphics.Vulkan _dirty = DirtyFlags.All; } - public void SetImage(int binding, ITexture image, Format imageFormat) + public void SetImage( + CommandBufferScoped cbs, + ShaderStage stage, + int binding, + ITexture image, + Format imageFormat) { if (image is TextureBuffer imageBuffer) { @@ -267,11 +327,13 @@ namespace Ryujinx.Graphics.Vulkan } else if (image is TextureView view) { - _imageRefs[binding] = view.GetView(imageFormat).GetIdentityImageView(); + view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags()); + + _imageRefs[binding] = new(stage, view.Storage, view.GetView(imageFormat).GetIdentityImageView()); } else { - _imageRefs[binding] = null; + _imageRefs[binding] = default; _bufferImageRefs[binding] = null; _bufferImageFormats[binding] = default; } @@ -281,7 +343,7 @@ namespace Ryujinx.Graphics.Vulkan public void SetImage(int binding, Auto<DisposableImageView> image) { - _imageRefs[binding] = image; + _imageRefs[binding] = new(ShaderStage.Compute, null, image); SignalDirty(DirtyFlags.Image); } @@ -366,15 +428,13 @@ namespace Ryujinx.Graphics.Vulkan } else if (texture is TextureView view) { - view.Storage.InsertWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags()); + view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags()); - _textureRefs[binding] = view.GetImageView(); - _samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler(); + _textureRefs[binding] = new(stage, view.Storage, view.GetImageView(), ((SamplerHolder)sampler)?.GetSampler()); } else { - _textureRefs[binding] = null; - _samplerRefs[binding] = null; + _textureRefs[binding] = default; _bufferTextureRefs[binding] = null; } @@ -390,10 +450,9 @@ namespace Ryujinx.Graphics.Vulkan { if (texture is TextureView view) { - view.Storage.InsertWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags()); + view.Storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stage.ConvertToPipelineStageFlags()); - _textureRefs[binding] = view.GetIdentityImageView(); - _samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler(); + _textureRefs[binding] = new(stage, view.Storage, view.GetIdentityImageView(), ((SamplerHolder)sampler)?.GetSampler()); SignalDirty(DirtyFlags.Texture); } @@ -608,9 +667,10 @@ namespace Ryujinx.Graphics.Vulkan for (int i = 0; i < count; i++) { ref var texture = ref textures[i]; + ref var refs = ref _textureRefs[binding + i]; - texture.ImageView = _textureRefs[binding + i]?.Get(cbs).Value ?? default; - texture.Sampler = _samplerRefs[binding + i]?.Get(cbs).Value ?? default; + texture.ImageView = refs.View?.Get(cbs).Value ?? default; + texture.Sampler = refs.Sampler?.Get(cbs).Value ?? default; if (texture.ImageView.Handle == 0) { @@ -645,7 +705,7 @@ namespace Ryujinx.Graphics.Vulkan for (int i = 0; i < count; i++) { - images[i].ImageView = _imageRefs[binding + i]?.Get(cbs).Value ?? default; + images[i].ImageView = _imageRefs[binding + i].View?.Get(cbs).Value ?? default; } tu.Push<DescriptorImageInfo>(images[..count]); |