See merge request ryubing/ryujinx!202
This commit is contained in:
LotP
2025-10-30 20:55:58 -05:00
parent ab7aeee67b
commit 92b61f9d73
43 changed files with 686 additions and 315 deletions

View File

@@ -58,6 +58,8 @@ namespace Ryujinx.Graphics.Vulkan
private Dictionary<ulong, StagingBufferReserved> _mirrors;
private bool _useMirrors;
private Action _decrementReferenceCount;
public BufferHolder(VulkanRenderer gd, Device device, VkBuffer buffer, MemoryAllocation allocation, int size, BufferAllocationType type, BufferAllocationType currentType)
{
_gd = gd;
@@ -75,6 +77,8 @@ namespace Ryujinx.Graphics.Vulkan
_flushLock = new ReaderWriterLockSlim();
_useMirrors = gd.IsTBDR;
_decrementReferenceCount = _buffer.DecrementReferenceCount;
}
public BufferHolder(VulkanRenderer gd, Device device, VkBuffer buffer, Auto<MemoryAllocation> allocation, int size, BufferAllocationType type, BufferAllocationType currentType, int offset)
@@ -444,7 +448,7 @@ namespace Ryujinx.Graphics.Vulkan
_flushLock.ExitReadLock();
return PinnedSpan<byte>.UnsafeFromSpan(result, _buffer.DecrementReferenceCount);
return PinnedSpan<byte>.UnsafeFromSpan(result, _decrementReferenceCount);
}
BackgroundResource resource = _gd.BackgroundResources.Get();

View File

@@ -1,6 +1,7 @@
using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan;
using System;
using System.Collections.Generic;
using System.Linq;
using Format = Ryujinx.Graphics.GAL.Format;
using VkFormat = Silk.NET.Vulkan.Format;
@@ -10,26 +11,27 @@ namespace Ryujinx.Graphics.Vulkan
class FramebufferParams
{
private readonly Device _device;
private readonly Auto<DisposableImageView>[] _attachments;
private readonly TextureView[] _colors;
private readonly TextureView _depthStencil;
private readonly TextureView[] _colorsCanonical;
private readonly TextureView _baseAttachment;
private readonly uint _validColorAttachments;
private Auto<DisposableImageView>[] _attachments;
private TextureView[] _colors;
private TextureView _depthStencil;
private TextureView[] _colorsCanonical;
private TextureView _baseAttachment;
private uint _validColorAttachments;
private int _totalCount;
public uint Width { get; }
public uint Height { get; }
public uint Layers { get; }
public uint Width { get; private set; }
public uint Height { get; private set; }
public uint Layers { get; private set; }
public uint[] AttachmentSamples { get; }
public VkFormat[] AttachmentFormats { get; }
public int[] AttachmentIndices { get; }
public uint AttachmentIntegerFormatMask { get; }
public bool LogicOpsAllowed { get; }
public uint[] AttachmentSamples { get; private set; }
public VkFormat[] AttachmentFormats { get; private set; }
public int[] AttachmentIndices { get; private set; }
public uint AttachmentIntegerFormatMask { get; private set; }
public bool LogicOpsAllowed { get; private set; }
public int AttachmentsCount { get; }
public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[^1] : -1;
public bool HasDepthStencil { get; }
public int AttachmentsCount { get; private set; }
public int MaxColorAttachmentIndex => ColorAttachmentsCount > 0 ? AttachmentIndices[ColorAttachmentsCount - 1] : -1;
public bool HasDepthStencil { get; private set; }
public int ColorAttachmentsCount => AttachmentsCount - (HasDepthStencil ? 1 : 0);
public FramebufferParams(Device device, TextureView view, uint width, uint height)
@@ -50,7 +52,7 @@ namespace Ryujinx.Graphics.Vulkan
else
{
_colors = [view];
_colorsCanonical = _colors;
_colorsCanonical = [view];
}
Width = width;
@@ -64,6 +66,7 @@ namespace Ryujinx.Graphics.Vulkan
LogicOpsAllowed = !format.IsFloatOrSrgb();
AttachmentsCount = 1;
_totalCount = 1;
HasDepthStencil = isDepthStencil;
}
@@ -133,7 +136,7 @@ namespace Ryujinx.Graphics.Vulkan
AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
LogicOpsAllowed = !allFormatsFloatOrSrgb;
if (depthStencil is TextureView dsTexture && dsTexture.Valid)
if (depthStencil is TextureView { Valid: true } dsTexture)
{
_attachments[count - 1] = dsTexture.GetImageViewForAttachment();
_depthStencil = dsTexture;
@@ -159,11 +162,151 @@ namespace Ryujinx.Graphics.Vulkan
Layers = layers;
AttachmentsCount = count;
_totalCount = colors.Length;
}
public FramebufferParams Update(ITexture[] colors, ITexture depthStencil)
{
int colorsCount = colors.Count(IsValidTextureView);
int count = colorsCount + (IsValidTextureView(depthStencil) ? 1 : 0);
Array.Clear(_attachments);
Array.Clear(_colors);
if (_attachments.Length < count)
{
Array.Resize(ref _attachments, count);
}
if (_colors.Length < colorsCount)
{
Array.Resize(ref _colors, colorsCount);
}
if (_colorsCanonical.Length < colors.Length)
{
Array.Resize(ref _colorsCanonical, colors.Length);
}
for (int i = 0; i < colors.Length; i++)
{
ITexture color = colors[i];
if (color is TextureView { Valid: true } view)
{
_colorsCanonical[i] = view;
}
else
{
_colorsCanonical[i] = null;
}
}
Array.Clear(AttachmentSamples);
Array.Clear(AttachmentFormats);
Array.Clear(AttachmentIndices);
if (AttachmentSamples.Length < count)
{
uint[] attachmentSamples = AttachmentSamples;
Array.Resize(ref attachmentSamples, count);
AttachmentSamples = attachmentSamples;
}
if (AttachmentFormats.Length < count)
{
VkFormat[] attachmentFormats = AttachmentFormats;
Array.Resize(ref attachmentFormats, count);
AttachmentFormats = attachmentFormats;
}
if (AttachmentIndices.Length < colorsCount)
{
int[] attachmentIndices = AttachmentIndices;
Array.Resize(ref attachmentIndices, colorsCount);
AttachmentIndices = attachmentIndices;
}
uint width = uint.MaxValue;
uint height = uint.MaxValue;
uint layers = uint.MaxValue;
int index = 0;
uint attachmentIntegerFormatMask = 0;
bool allFormatsFloatOrSrgb = colorsCount != 0;
_validColorAttachments = 0;
_baseAttachment = null;
for (int bindIndex = 0; bindIndex < colors.Length; bindIndex++)
{
TextureView texture = _colorsCanonical[bindIndex];
if (texture is not null)
{
_attachments[index] = texture.GetImageViewForAttachment();
_colors[index] = texture;
_validColorAttachments |= 1u << bindIndex;
_baseAttachment = texture;
AttachmentSamples[index] = (uint)texture.Info.Samples;
AttachmentFormats[index] = texture.VkFormat;
AttachmentIndices[index] = bindIndex;
Format format = texture.Info.Format;
if (format.IsInteger())
{
attachmentIntegerFormatMask |= 1u << bindIndex;
}
allFormatsFloatOrSrgb &= format.IsFloatOrSrgb();
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;
}
}
}
AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
LogicOpsAllowed = !allFormatsFloatOrSrgb;
_depthStencil = null;
HasDepthStencil = false;
if (depthStencil is TextureView { Valid: true } dsTexture)
{
_attachments[count - 1] = dsTexture.GetImageViewForAttachment();
_depthStencil = dsTexture;
_baseAttachment ??= 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;
_totalCount = colors.Length;
return this;
}
public Auto<DisposableImageView> GetAttachment(int index)
{
if ((uint)index >= _attachments.Length)
if ((uint)index >= AttachmentsCount)
{
return null;
}
@@ -183,7 +326,7 @@ namespace Ryujinx.Graphics.Vulkan
public ComponentType GetAttachmentComponentType(int index)
{
if (_colors != null && (uint)index < _colors.Length)
if (_colors != null && (uint)index < ColorAttachmentsCount)
{
Format format = _colors[index].Info.Format;
@@ -218,7 +361,7 @@ namespace Ryujinx.Graphics.Vulkan
private static bool IsValidTextureView(ITexture texture)
{
return texture is TextureView view && view.Valid;
return texture is TextureView { Valid: true };
}
public ClearRect GetClearRect(Rectangle<int> scissor, int layer, int layerCount)
@@ -233,9 +376,9 @@ namespace Ryujinx.Graphics.Vulkan
public unsafe Auto<DisposableFramebuffer> Create(Vk api, CommandBufferScoped cbs, Auto<DisposableRenderPass> renderPass)
{
ImageView* attachments = stackalloc ImageView[_attachments.Length];
ImageView* attachments = stackalloc ImageView[AttachmentsCount];
for (int i = 0; i < _attachments.Length; i++)
for (int i = 0; i < AttachmentsCount; i++)
{
attachments[i] = _attachments[i].Get(cbs).Value;
}
@@ -244,7 +387,7 @@ namespace Ryujinx.Graphics.Vulkan
{
SType = StructureType.FramebufferCreateInfo,
RenderPass = renderPass.Get(cbs).Value,
AttachmentCount = (uint)_attachments.Length,
AttachmentCount = (uint)AttachmentsCount,
PAttachments = attachments,
Width = Width,
Height = Height,
@@ -252,14 +395,13 @@ namespace Ryujinx.Graphics.Vulkan
};
api.CreateFramebuffer(_device, in framebufferCreateInfo, null, out Framebuffer framebuffer).ThrowOnError();
return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments);
return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments[..AttachmentsCount]);
}
public TextureView[] GetAttachmentViews()
{
TextureView[] result = new TextureView[_attachments.Length];
_colors?.CopyTo(result, 0);
TextureView[] result = new TextureView[AttachmentsCount];
_colors?.AsSpan(..ColorAttachmentsCount).CopyTo(result.AsSpan());
if (_depthStencil != null)
{
@@ -278,8 +420,11 @@ namespace Ryujinx.Graphics.Vulkan
{
if (_colors != null)
{
foreach (TextureView color in _colors)
int count = ColorAttachmentsCount;
for (int i = 0; i < count; i++)
{
TextureView color = _colors[i];
// If Clear or DontCare were used, this would need to be write bit.
color.Storage?.QueueLoadOpBarrier(cbs, false);
}
@@ -294,8 +439,11 @@ namespace Ryujinx.Graphics.Vulkan
{
if (_colors != null)
{
foreach (TextureView color in _colors)
int count = ColorAttachmentsCount;
for (int i = 0; i < count; i++)
{
TextureView color = _colors[i];
color.Storage?.AddStoreOpUsage(false);
}
}
@@ -307,7 +455,7 @@ namespace Ryujinx.Graphics.Vulkan
{
_depthStencil?.Storage.ClearBindings();
for (int i = 0; i < _colorsCanonical.Length; i++)
for (int i = 0; i < _totalCount; i++)
{
_colorsCanonical[i]?.Storage.ClearBindings();
}
@@ -317,7 +465,7 @@ namespace Ryujinx.Graphics.Vulkan
{
_depthStencil?.Storage.AddBinding(_depthStencil);
for (int i = 0; i < _colorsCanonical.Length; i++)
for (int i = 0; i < _totalCount; i++)
{
TextureView color = _colorsCanonical[i];
color?.Storage.AddBinding(color);

View File

@@ -1,6 +1,7 @@
using Ryujinx.Common.Memory;
using Silk.NET.Vulkan;
using System;
using System.Buffers;
namespace Ryujinx.Graphics.Vulkan
{
@@ -11,7 +12,7 @@ namespace Ryujinx.Graphics.Vulkan
{
private const int BufferUsageTrackingGranularity = 4096;
private readonly FenceHolder[] _fences;
public FenceHolder[] Fences { get; }
private readonly BufferUsageBitmap _bufferUsageBitmap;
/// <summary>
@@ -19,7 +20,7 @@ namespace Ryujinx.Graphics.Vulkan
/// </summary>
public MultiFenceHolder()
{
_fences = new FenceHolder[CommandBufferPool.MaxCommandBuffers];
Fences = ArrayPool<FenceHolder>.Shared.Rent(CommandBufferPool.MaxCommandBuffers);
}
/// <summary>
@@ -28,7 +29,7 @@ namespace Ryujinx.Graphics.Vulkan
/// <param name="size">Size of the buffer</param>
public MultiFenceHolder(int size)
{
_fences = new FenceHolder[CommandBufferPool.MaxCommandBuffers];
Fences = ArrayPool<FenceHolder>.Shared.Rent(CommandBufferPool.MaxCommandBuffers);
_bufferUsageBitmap = new BufferUsageBitmap(size, BufferUsageTrackingGranularity);
}
@@ -90,7 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
/// <returns>True if the command buffer's previous fence value was null</returns>
public bool AddFence(int cbIndex, FenceHolder fence)
{
ref FenceHolder fenceRef = ref _fences[cbIndex];
ref FenceHolder fenceRef = ref Fences[cbIndex];
if (fenceRef == null)
{
@@ -107,7 +108,7 @@ namespace Ryujinx.Graphics.Vulkan
/// <param name="cbIndex">Command buffer index of the command buffer that owns the fence</param>
public void RemoveFence(int cbIndex)
{
_fences[cbIndex] = null;
Fences[cbIndex] = null;
}
/// <summary>
@@ -117,7 +118,7 @@ namespace Ryujinx.Graphics.Vulkan
/// <returns>True if referenced, false otherwise</returns>
public bool HasFence(int cbIndex)
{
return _fences[cbIndex] != null;
return Fences[cbIndex] != null;
}
/// <summary>
@@ -227,9 +228,9 @@ namespace Ryujinx.Graphics.Vulkan
{
int count = 0;
for (int i = 0; i < _fences.Length; i++)
for (int i = 0; i < Fences.Length; i++)
{
FenceHolder fence = _fences[i];
FenceHolder fence = Fences[i];
if (fence != null)
{
@@ -251,9 +252,9 @@ namespace Ryujinx.Graphics.Vulkan
{
int count = 0;
for (int i = 0; i < _fences.Length; i++)
for (int i = 0; i < Fences.Length; i++)
{
FenceHolder fence = _fences[i];
FenceHolder fence = Fences[i];
if (fence != null && _bufferUsageBitmap.OverlapsWith(i, offset, size))
{

View File

@@ -1453,7 +1453,7 @@ namespace Ryujinx.Graphics.Vulkan
FramebufferParams?.ClearBindings();
}
FramebufferParams = new FramebufferParams(Device, colors, depthStencil);
FramebufferParams = FramebufferParams?.Update(colors, depthStencil) ?? new FramebufferParams(Device, colors, depthStencil);
if (IsMainPipeline)
{
@@ -1471,18 +1471,18 @@ namespace Ryujinx.Graphics.Vulkan
protected void UpdatePipelineAttachmentFormats()
{
Span<Silk.NET.Vulkan.Format> dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
FramebufferParams.AttachmentFormats.AsSpan(..FramebufferParams.AttachmentsCount).CopyTo(dstAttachmentFormats);
_newState.Internal.AttachmentIntegerFormatMask = FramebufferParams.AttachmentIntegerFormatMask;
_newState.Internal.LogicOpsAllowed = FramebufferParams.LogicOpsAllowed;
for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++)
for (int i = FramebufferParams.AttachmentsCount; i < dstAttachmentFormats.Length; i++)
{
dstAttachmentFormats[i] = 0;
}
_newState.ColorBlendAttachmentStateCount = (uint)(FramebufferParams.MaxColorAttachmentIndex + 1);
_newState.HasDepthStencil = FramebufferParams.HasDepthStencil;
_newState.SamplesCount = FramebufferParams.AttachmentSamples.Length != 0 ? FramebufferParams.AttachmentSamples[0] : 1;
_newState.SamplesCount = FramebufferParams.AttachmentsCount != 0 ? FramebufferParams.AttachmentSamples[0] : 1;
}
protected unsafe void CreateRenderPass()

View File

@@ -178,17 +178,16 @@ namespace Ryujinx.Graphics.Vulkan
{
if (_forcedFences.Count > 0)
{
_forcedFences.RemoveAll((entry) =>
for (int i = 0; i < _forcedFences.Count; i++)
{
if (entry.Texture.Disposed)
if (_forcedFences[i].Texture.Disposed)
{
return true;
_forcedFences.RemoveAt(i--);
continue;
}
entry.Texture.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, entry.StageFlags);
return false;
});
_forcedFences[i].Texture.QueueWriteToReadBarrier(cbs, AccessFlags.ShaderReadBit, _forcedFences[i].StageFlags);
}
}
}

View File

@@ -1,5 +1,6 @@
using Ryujinx.Common.Logging;
using Silk.NET.Vulkan;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@@ -192,6 +193,7 @@ namespace Ryujinx.Graphics.Vulkan
{
_firstHandle = first.ID + 1;
_handles.RemoveAt(0);
ArrayPool<FenceHolder>.Shared.Return(first.Waitable.Fences);
first.Waitable = null;
}
}