mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-06-29 15:16:25 +02:00
Vulkan: Defer guest barriers, and improve image barrier timings (#7012)
* More guarantees for buffer correct placement, defer guest requested buffers * Split RP on indirect barrier rn * Better handling for feedback loops. * Qualcomm barriers suck too * Fix condition * Remove unused field * Allow render pass barriers on turnip for now
This commit is contained in:
parent
f77bebac80
commit
1a919e99b2
18 changed files with 452 additions and 156 deletions
|
@ -55,6 +55,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
protected FramebufferParams FramebufferParams;
|
||||
private Auto<DisposableFramebuffer> _framebuffer;
|
||||
private RenderPassHolder _rpHolder;
|
||||
private Auto<DisposableRenderPass> _renderPass;
|
||||
private RenderPassHolder _nullRenderPass;
|
||||
private int _writtenAttachmentCount;
|
||||
|
@ -85,8 +86,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
private bool _tfActive;
|
||||
|
||||
private readonly PipelineColorBlendAttachmentState[] _storedBlend;
|
||||
|
||||
private ulong _drawCountSinceBarrier;
|
||||
public ulong DrawCount { get; private set; }
|
||||
public bool RenderPassActive { get; private set; }
|
||||
|
||||
|
@ -135,48 +134,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public unsafe void Barrier()
|
||||
{
|
||||
if (_drawCountSinceBarrier != DrawCount)
|
||||
{
|
||||
_drawCountSinceBarrier = DrawCount;
|
||||
|
||||
// Barriers are not supported inside a render pass on Apple GPUs.
|
||||
// As a workaround, end the render pass.
|
||||
if (Gd.Vendor == Vendor.Apple)
|
||||
{
|
||||
EndRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryBarrier memoryBarrier = new()
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
|
||||
};
|
||||
|
||||
PipelineStageFlags pipelineStageFlags = PipelineStageFlags.VertexShaderBit | PipelineStageFlags.FragmentShaderBit;
|
||||
|
||||
if (Gd.Capabilities.SupportsGeometryShader)
|
||||
{
|
||||
pipelineStageFlags |= PipelineStageFlags.GeometryShaderBit;
|
||||
}
|
||||
|
||||
if (Gd.Capabilities.SupportsTessellationShader)
|
||||
{
|
||||
pipelineStageFlags |= PipelineStageFlags.TessellationControlShaderBit | PipelineStageFlags.TessellationEvaluationShaderBit;
|
||||
}
|
||||
|
||||
Gd.Api.CmdPipelineBarrier(
|
||||
CommandBuffer,
|
||||
pipelineStageFlags,
|
||||
pipelineStageFlags,
|
||||
0,
|
||||
1,
|
||||
memoryBarrier,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null);
|
||||
Gd.Barriers.QueueMemoryBarrier();
|
||||
}
|
||||
|
||||
public void ComputeBarrier()
|
||||
|
@ -203,6 +161,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public void BeginTransformFeedback(PrimitiveTopology topology)
|
||||
{
|
||||
Gd.Barriers.EnableTfbBarriers(true);
|
||||
_tfEnabled = true;
|
||||
}
|
||||
|
||||
|
@ -249,7 +208,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
CreateRenderPass();
|
||||
}
|
||||
|
||||
Gd.Barriers.Flush(Cbs.CommandBuffer, RenderPassActive, EndRenderPassDelegate);
|
||||
Gd.Barriers.Flush(Cbs, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||
|
||||
BeginRenderPass();
|
||||
|
||||
|
@ -287,7 +246,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
CreateRenderPass();
|
||||
}
|
||||
|
||||
Gd.Barriers.Flush(Cbs.CommandBuffer, RenderPassActive, EndRenderPassDelegate);
|
||||
Gd.Barriers.Flush(Cbs, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||
|
||||
BeginRenderPass();
|
||||
|
||||
|
@ -299,24 +258,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public unsafe void CommandBufferBarrier()
|
||||
{
|
||||
MemoryBarrier memoryBarrier = new()
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = BufferHolder.DefaultAccessFlags,
|
||||
DstAccessMask = AccessFlags.IndirectCommandReadBit,
|
||||
};
|
||||
|
||||
Gd.Api.CmdPipelineBarrier(
|
||||
CommandBuffer,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.DrawIndirectBit,
|
||||
0,
|
||||
1,
|
||||
memoryBarrier,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null);
|
||||
Gd.Barriers.QueueCommandBufferBarrier();
|
||||
}
|
||||
|
||||
public void CopyBuffer(BufferHandle source, BufferHandle destination, int srcOffset, int dstOffset, int size)
|
||||
|
@ -722,6 +664,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public void EndTransformFeedback()
|
||||
{
|
||||
Gd.Barriers.EnableTfbBarriers(false);
|
||||
PauseTransformFeedbackInternal();
|
||||
_tfEnabled = false;
|
||||
}
|
||||
|
@ -1408,24 +1351,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public unsafe void TextureBarrier()
|
||||
{
|
||||
MemoryBarrier memoryBarrier = new()
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
|
||||
};
|
||||
|
||||
Gd.Api.CmdPipelineBarrier(
|
||||
CommandBuffer,
|
||||
PipelineStageFlags.FragmentShaderBit,
|
||||
PipelineStageFlags.FragmentShaderBit,
|
||||
0,
|
||||
1,
|
||||
memoryBarrier,
|
||||
0,
|
||||
null,
|
||||
0,
|
||||
null);
|
||||
Gd.Barriers.QueueTextureBarrier();
|
||||
}
|
||||
|
||||
public void TextureBarrierTiled()
|
||||
|
@ -1532,12 +1458,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
// Use the null framebuffer.
|
||||
_nullRenderPass ??= new RenderPassHolder(Gd, Device, new RenderPassCacheKey(), FramebufferParams);
|
||||
|
||||
_rpHolder = _nullRenderPass;
|
||||
_renderPass = _nullRenderPass.GetRenderPass();
|
||||
_framebuffer = _nullRenderPass.GetFramebuffer(Gd, Cbs, FramebufferParams);
|
||||
}
|
||||
else
|
||||
{
|
||||
(_renderPass, _framebuffer) = FramebufferParams.GetPassAndFramebuffer(Gd, Device, Cbs);
|
||||
(_rpHolder, _framebuffer) = FramebufferParams.GetPassAndFramebuffer(Gd, Device, Cbs);
|
||||
|
||||
_renderPass = _rpHolder.GetRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1564,7 +1493,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
}
|
||||
}
|
||||
|
||||
Gd.Barriers.Flush(Cbs.CommandBuffer, RenderPassActive, EndRenderPassDelegate);
|
||||
Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||
|
||||
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Compute);
|
||||
}
|
||||
|
@ -1629,7 +1558,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
}
|
||||
}
|
||||
|
||||
Gd.Barriers.Flush(Cbs.CommandBuffer, RenderPassActive, EndRenderPassDelegate);
|
||||
Gd.Barriers.Flush(Cbs, _program, RenderPassActive, _rpHolder, EndRenderPassDelegate);
|
||||
|
||||
_descriptorSetUpdater.UpdateAndBindDescriptorSets(Cbs, PipelineBindPoint.Graphics);
|
||||
|
||||
|
@ -1708,6 +1637,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
{
|
||||
if (RenderPassActive)
|
||||
{
|
||||
FramebufferParams.AddStoreOpUsage();
|
||||
|
||||
PauseTransformFeedbackInternal();
|
||||
Gd.Api.CmdEndRenderPass(CommandBuffer);
|
||||
SignalRenderPassEnd();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue