Vulkan: Don't create preload command buffer outside a render pass (#3864)
* Vulkan: Don't create preload buffer outside a render pass The preload command buffer is used to avoid render pass splits and barriers when updating buffer data. However, when a render pass is not active (for example, at the start of a pass, or during compute invocations) buffer uploads can be performed at any time, so the optimization isn't as useful. This PR makes it so that the preload command buffer is only used for buffer updates outside of a render pass. It's still used for textures as I don't want to shake things up right now regarding how the preload buffer is obtained before some other changes, and texture updates are a lot rarer anyways. Improves performance slightly in Pokemon Scarlet/Violet (43 -> 48), as it was switching to compute, writing a bunch of buffers inline, then dispatching, then flushing commands... It uses 1 command buffer instead of 2 every time it does this now. Maybe it would be nice to find a faster way to sync without creating so many command buffers in a short period of time. * Address feedback
This commit is contained in:
parent
187372cbde
commit
131baebe2a
3 changed files with 17 additions and 9 deletions
|
@ -210,7 +210,10 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cbs != null && !(_buffer.HasCommandBufferDependency(cbs.Value) && _waitable.IsBufferRangeInUse(cbs.Value.CommandBufferIndex, offset, dataSize)))
|
if (cbs != null &&
|
||||||
|
_gd.PipelineInternal.RenderPassActive &&
|
||||||
|
!(_buffer.HasCommandBufferDependency(cbs.Value) &&
|
||||||
|
_waitable.IsBufferRangeInUse(cbs.Value.CommandBufferIndex, offset, dataSize)))
|
||||||
{
|
{
|
||||||
// If the buffer hasn't been used on the command buffer yet, try to preload the data.
|
// If the buffer hasn't been used on the command buffer yet, try to preload the data.
|
||||||
// This avoids ending and beginning render passes on each buffer data upload.
|
// This avoids ending and beginning render passes on each buffer data upload.
|
||||||
|
|
|
@ -49,7 +49,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private Auto<DisposableFramebuffer> _framebuffer;
|
private Auto<DisposableFramebuffer> _framebuffer;
|
||||||
private Auto<DisposableRenderPass> _renderPass;
|
private Auto<DisposableRenderPass> _renderPass;
|
||||||
private int _writtenAttachmentCount;
|
private int _writtenAttachmentCount;
|
||||||
private bool _renderPassActive;
|
|
||||||
|
|
||||||
private readonly DescriptorSetUpdater _descriptorSetUpdater;
|
private readonly DescriptorSetUpdater _descriptorSetUpdater;
|
||||||
|
|
||||||
|
@ -73,6 +72,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private PipelineColorBlendAttachmentState[] _storedBlend;
|
private PipelineColorBlendAttachmentState[] _storedBlend;
|
||||||
|
|
||||||
public ulong DrawCount { get; private set; }
|
public ulong DrawCount { get; private set; }
|
||||||
|
public bool RenderPassActive { get; private set; }
|
||||||
|
|
||||||
public unsafe PipelineBase(VulkanRenderer gd, Device device)
|
public unsafe PipelineBase(VulkanRenderer gd, Device device)
|
||||||
{
|
{
|
||||||
|
@ -838,6 +838,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
stages.CopyTo(_newState.Stages.AsSpan().Slice(0, stages.Length));
|
stages.CopyTo(_newState.Stages.AsSpan().Slice(0, stages.Length));
|
||||||
|
|
||||||
SignalStateChange();
|
SignalStateChange();
|
||||||
|
|
||||||
|
if (_program.IsCompute)
|
||||||
|
{
|
||||||
|
EndRenderPass();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Specialize<T>(in T data) where T : unmanaged
|
public void Specialize<T>(in T data) where T : unmanaged
|
||||||
|
@ -1451,7 +1456,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
private unsafe void BeginRenderPass()
|
private unsafe void BeginRenderPass()
|
||||||
{
|
{
|
||||||
if (!_renderPassActive)
|
if (!RenderPassActive)
|
||||||
{
|
{
|
||||||
var renderArea = new Rect2D(null, new Extent2D(FramebufferParams.Width, FramebufferParams.Height));
|
var renderArea = new Rect2D(null, new Extent2D(FramebufferParams.Width, FramebufferParams.Height));
|
||||||
var clearValue = new ClearValue();
|
var clearValue = new ClearValue();
|
||||||
|
@ -1467,18 +1472,18 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
};
|
};
|
||||||
|
|
||||||
Gd.Api.CmdBeginRenderPass(CommandBuffer, renderPassBeginInfo, SubpassContents.Inline);
|
Gd.Api.CmdBeginRenderPass(CommandBuffer, renderPassBeginInfo, SubpassContents.Inline);
|
||||||
_renderPassActive = true;
|
RenderPassActive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndRenderPass()
|
public void EndRenderPass()
|
||||||
{
|
{
|
||||||
if (_renderPassActive)
|
if (RenderPassActive)
|
||||||
{
|
{
|
||||||
PauseTransformFeedbackInternal();
|
PauseTransformFeedbackInternal();
|
||||||
Gd.Api.CmdEndRenderPass(CommandBuffer);
|
Gd.Api.CmdEndRenderPass(CommandBuffer);
|
||||||
SignalRenderPassEnd();
|
SignalRenderPassEnd();
|
||||||
_renderPassActive = false;
|
RenderPassActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
public bool HasMinimalLayout { get; }
|
public bool HasMinimalLayout { get; }
|
||||||
public bool UsePushDescriptors { get; }
|
public bool UsePushDescriptors { get; }
|
||||||
|
public bool IsCompute { get; }
|
||||||
|
|
||||||
public uint Stages { get; }
|
public uint Stages { get; }
|
||||||
|
|
||||||
|
@ -47,7 +48,6 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
private VulkanRenderer _gd;
|
private VulkanRenderer _gd;
|
||||||
private Device _device;
|
private Device _device;
|
||||||
private bool _initialized;
|
private bool _initialized;
|
||||||
private bool _isCompute;
|
|
||||||
|
|
||||||
private ProgramPipelineState _state;
|
private ProgramPipelineState _state;
|
||||||
private DisposableRenderPass _dummyRenderPass;
|
private DisposableRenderPass _dummyRenderPass;
|
||||||
|
@ -91,7 +91,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
if (shader.StageFlags == ShaderStageFlags.ShaderStageComputeBit)
|
if (shader.StageFlags == ShaderStageFlags.ShaderStageComputeBit)
|
||||||
{
|
{
|
||||||
_isCompute = true;
|
IsCompute = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internalShaders[i] = shader;
|
internalShaders[i] = shader;
|
||||||
|
@ -163,7 +163,7 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (_isCompute)
|
if (IsCompute)
|
||||||
{
|
{
|
||||||
CreateBackgroundComputePipeline();
|
CreateBackgroundComputePipeline();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue