aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/ImageArray.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/ImageArray.cs')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/ImageArray.cs179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/ImageArray.cs b/src/Ryujinx.Graphics.Vulkan/ImageArray.cs
new file mode 100644
index 00000000..38a5b6b4
--- /dev/null
+++ b/src/Ryujinx.Graphics.Vulkan/ImageArray.cs
@@ -0,0 +1,179 @@
+using Ryujinx.Graphics.GAL;
+using Silk.NET.Vulkan;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Vulkan
+{
+ class ImageArray : IImageArray
+ {
+ private readonly VulkanRenderer _gd;
+
+ private record struct TextureRef
+ {
+ public TextureStorage Storage;
+ public TextureView View;
+ public GAL.Format ImageFormat;
+ }
+
+ private readonly TextureRef[] _textureRefs;
+ private readonly TextureBuffer[] _bufferTextureRefs;
+
+ private readonly DescriptorImageInfo[] _textures;
+ private readonly BufferView[] _bufferTextures;
+
+ private HashSet<TextureStorage> _storages;
+
+ private int _cachedCommandBufferIndex;
+ private int _cachedSubmissionCount;
+
+ private readonly bool _isBuffer;
+
+ public bool Bound;
+
+ public ImageArray(VulkanRenderer gd, int size, bool isBuffer)
+ {
+ _gd = gd;
+
+ if (isBuffer)
+ {
+ _bufferTextureRefs = new TextureBuffer[size];
+ _bufferTextures = new BufferView[size];
+ }
+ else
+ {
+ _textureRefs = new TextureRef[size];
+ _textures = new DescriptorImageInfo[size];
+ }
+
+ _storages = null;
+
+ _cachedCommandBufferIndex = -1;
+ _cachedSubmissionCount = 0;
+
+ _isBuffer = isBuffer;
+ }
+
+ public void SetFormats(int index, GAL.Format[] imageFormats)
+ {
+ for (int i = 0; i < imageFormats.Length; i++)
+ {
+ _textureRefs[index + i].ImageFormat = imageFormats[i];
+ }
+
+ SetDirty();
+ }
+
+ public void SetImages(int index, ITexture[] images)
+ {
+ for (int i = 0; i < images.Length; i++)
+ {
+ ITexture image = images[i];
+
+ if (image is TextureBuffer textureBuffer)
+ {
+ _bufferTextureRefs[index + i] = textureBuffer;
+ }
+ else if (image is TextureView view)
+ {
+ _textureRefs[index + i].Storage = view.Storage;
+ _textureRefs[index + i].View = view;
+ }
+ else if (!_isBuffer)
+ {
+ _textureRefs[index + i].Storage = null;
+ _textureRefs[index + i].View = default;
+ }
+ else
+ {
+ _bufferTextureRefs[index + i] = null;
+ }
+ }
+
+ SetDirty();
+ }
+
+ private void SetDirty()
+ {
+ _cachedCommandBufferIndex = -1;
+ _storages = null;
+
+ _gd.PipelineInternal.ForceImageDirty();
+ }
+
+ public void QueueWriteToReadBarriers(CommandBufferScoped cbs, PipelineStageFlags stageFlags)
+ {
+ HashSet<TextureStorage> storages = _storages;
+
+ if (storages == null)
+ {
+ storages = new HashSet<TextureStorage>();
+
+ for (int index = 0; index < _textureRefs.Length; index++)
+ {
+ if (_textureRefs[index].Storage != null)
+ {
+ storages.Add(_textureRefs[index].Storage);
+ }
+ }
+
+ _storages = storages;
+ }
+
+ foreach (TextureStorage storage in storages)
+ {
+ storage.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, stageFlags);
+ }
+ }
+
+ public ReadOnlySpan<DescriptorImageInfo> GetImageInfos(VulkanRenderer gd, CommandBufferScoped cbs, TextureView dummyTexture)
+ {
+ int submissionCount = gd.CommandBufferPool.GetSubmissionCount(cbs.CommandBufferIndex);
+
+ Span<DescriptorImageInfo> textures = _textures;
+
+ if (cbs.CommandBufferIndex == _cachedCommandBufferIndex && submissionCount == _cachedSubmissionCount)
+ {
+ return textures;
+ }
+
+ _cachedCommandBufferIndex = cbs.CommandBufferIndex;
+ _cachedSubmissionCount = submissionCount;
+
+ for (int i = 0; i < textures.Length; i++)
+ {
+ ref var texture = ref textures[i];
+ ref var refs = ref _textureRefs[i];
+
+ if (i > 0 && _textureRefs[i - 1].View == refs.View && _textureRefs[i - 1].ImageFormat == refs.ImageFormat)
+ {
+ texture = textures[i - 1];
+
+ continue;
+ }
+
+ texture.ImageLayout = ImageLayout.General;
+ texture.ImageView = refs.View?.GetView(refs.ImageFormat).GetIdentityImageView().Get(cbs).Value ?? default;
+
+ if (texture.ImageView.Handle == 0)
+ {
+ texture.ImageView = dummyTexture.GetImageView().Get(cbs).Value;
+ }
+ }
+
+ return textures;
+ }
+
+ public ReadOnlySpan<BufferView> GetBufferViews(CommandBufferScoped cbs)
+ {
+ Span<BufferView> bufferTextures = _bufferTextures;
+
+ for (int i = 0; i < bufferTextures.Length; i++)
+ {
+ bufferTextures[i] = _bufferTextureRefs[i]?.GetBufferView(cbs, _textureRefs[i].ImageFormat, true) ?? default;
+ }
+
+ return bufferTextures;
+ }
+ }
+}