aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/FramebufferParams.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/FramebufferParams.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/FramebufferParams.cs203
1 files changed, 203 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Vulkan/FramebufferParams.cs b/Ryujinx.Graphics.Vulkan/FramebufferParams.cs
new file mode 100644
index 00000000..e5318e93
--- /dev/null
+++ b/Ryujinx.Graphics.Vulkan/FramebufferParams.cs
@@ -0,0 +1,203 @@
+using Ryujinx.Graphics.GAL;
+using Silk.NET.Vulkan;
+using System;
+using System.Linq;
+using VkFormat = Silk.NET.Vulkan.Format;
+
+namespace Ryujinx.Graphics.Vulkan
+{
+ class FramebufferParams
+ {
+ private readonly Device _device;
+ private readonly Auto<DisposableImageView>[] _attachments;
+ private readonly TextureView[] _colors;
+ private readonly TextureView _depthStencil;
+ private uint _validColorAttachments;
+
+ public uint Width { get; }
+ public uint Height { get; }
+ public uint Layers { get; }
+
+ public uint[] AttachmentSamples { get; }
+ public VkFormat[] AttachmentFormats { get; }
+ public int[] AttachmentIndices { get; }
+
+ public int AttachmentsCount { get; }
+ public int MaxColorAttachmentIndex { get; }
+ public bool HasDepthStencil { get; }
+ public int ColorAttachmentsCount => AttachmentsCount - (HasDepthStencil ? 1 : 0);
+
+ public FramebufferParams(
+ Device device,
+ Auto<DisposableImageView> view,
+ uint width,
+ uint height,
+ bool isDepthStencil,
+ VkFormat format)
+ {
+ _device = device;
+ _attachments = new[] { view };
+ _validColorAttachments = 1u;
+
+ Width = width;
+ Height = height;
+ Layers = 1;
+
+ AttachmentSamples = new[] { 1u };
+ AttachmentFormats = new[] { format };
+ AttachmentIndices = new[] { 0 };
+
+ AttachmentsCount = 1;
+
+ HasDepthStencil = isDepthStencil;
+ }
+
+ public FramebufferParams(Device device, ITexture[] colors, ITexture depthStencil)
+ {
+ _device = device;
+
+ int colorsCount = colors.Count(IsValidTextureView);
+
+ int count = colorsCount + (IsValidTextureView(depthStencil) ? 1 : 0);
+
+ _attachments = new Auto<DisposableImageView>[count];
+ _colors = new TextureView[colorsCount];
+
+ AttachmentSamples = new uint[count];
+ AttachmentFormats = new VkFormat[count];
+ AttachmentIndices = new int[count];
+ MaxColorAttachmentIndex = colors.Length - 1;
+
+ uint width = uint.MaxValue;
+ uint height = uint.MaxValue;
+ uint layers = uint.MaxValue;
+
+ int index = 0;
+ int bindIndex = 0;
+
+ foreach (ITexture color in colors)
+ {
+ if (IsValidTextureView(color))
+ {
+ var texture = (TextureView)color;
+
+ _attachments[index] = texture.GetImageViewForAttachment();
+ _colors[index] = texture;
+ _validColorAttachments |= 1u << bindIndex;
+
+ AttachmentSamples[index] = (uint)texture.Info.Samples;
+ AttachmentFormats[index] = texture.VkFormat;
+ AttachmentIndices[index] = bindIndex;
+
+ width = Math.Min(width, (uint)texture.Width);
+ height = Math.Min(height, (uint)texture.Height);
+ layers = Math.Min(layers, (uint)texture.Layers);
+
+ if (++index >= colorsCount)
+ {
+ break;
+ }
+ }
+
+ bindIndex++;
+ }
+
+ if (depthStencil is TextureView dsTexture && dsTexture.Valid)
+ {
+ _attachments[count - 1] = dsTexture.GetImageViewForAttachment();
+ _depthStencil = dsTexture;
+
+ AttachmentSamples[count - 1] = (uint)dsTexture.Info.Samples;
+ AttachmentFormats[count - 1] = dsTexture.VkFormat;
+
+ width = Math.Min(width, (uint)dsTexture.Width);
+ height = Math.Min(height, (uint)dsTexture.Height);
+ layers = Math.Min(layers, (uint)dsTexture.Layers);
+
+ HasDepthStencil = true;
+ }
+
+ if (count == 0)
+ {
+ width = height = layers = 1;
+ }
+
+ Width = width;
+ Height = height;
+ Layers = layers;
+
+ AttachmentsCount = count;
+ }
+
+ public Auto<DisposableImageView> GetAttachment(int index)
+ {
+ if ((uint)index >= _attachments.Length)
+ {
+ return null;
+ }
+
+ return _attachments[index];
+ }
+
+ public bool IsValidColorAttachment(int bindIndex)
+ {
+ return (uint)bindIndex < Constants.MaxRenderTargets && (_validColorAttachments & (1u << bindIndex)) != 0;
+ }
+
+ private static bool IsValidTextureView(ITexture texture)
+ {
+ return texture is TextureView view && view.Valid;
+ }
+
+ public ClearRect GetClearRect(Rectangle<int> scissor, int layer)
+ {
+ int x = scissor.X;
+ int y = scissor.Y;
+ int width = Math.Min((int)Width - scissor.X, scissor.Width);
+ int height = Math.Min((int)Height - scissor.Y, scissor.Height);
+
+ return new ClearRect(new Rect2D(new Offset2D(x, y), new Extent2D((uint)width, (uint)height)), (uint)layer, 1);
+ }
+
+ public unsafe Auto<DisposableFramebuffer> Create(Vk api, CommandBufferScoped cbs, Auto<DisposableRenderPass> renderPass)
+ {
+ ImageView* attachments = stackalloc ImageView[_attachments.Length];
+
+ for (int i = 0; i < _attachments.Length; i++)
+ {
+ attachments[i] = _attachments[i].Get(cbs).Value;
+ }
+
+ var framebufferCreateInfo = new FramebufferCreateInfo()
+ {
+ SType = StructureType.FramebufferCreateInfo,
+ RenderPass = renderPass.Get(cbs).Value,
+ AttachmentCount = (uint)_attachments.Length,
+ PAttachments = attachments,
+ Width = Width,
+ Height = Height,
+ Layers = Layers
+ };
+
+ api.CreateFramebuffer(_device, framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
+ return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments);
+ }
+
+ public void UpdateModifications()
+ {
+ if (_colors != null)
+ {
+ for (int index = 0; index < _colors.Length; index++)
+ {
+ _colors[index].Storage.SetModification(
+ AccessFlags.AccessColorAttachmentWriteBit,
+ PipelineStageFlags.PipelineStageColorAttachmentOutputBit);
+ }
+ }
+
+ _depthStencil?.Storage.SetModification(
+ AccessFlags.AccessDepthStencilAttachmentWriteBit,
+ PipelineStageFlags.PipelineStageColorAttachmentOutputBit);
+ }
+ }
+}