Better handling for feedback loops.
This commit is contained in:
parent
658ad40c16
commit
7ab99e8ea1
5 changed files with 58 additions and 5 deletions
|
@ -298,19 +298,41 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
// Generally, we want to avoid this from happening in the future, so flag the texture to immediately
|
// Generally, we want to avoid this from happening in the future, so flag the texture to immediately
|
||||||
// emit a barrier whenever the current render pass is bound again.
|
// emit a barrier whenever the current render pass is bound again.
|
||||||
|
|
||||||
|
bool anyIsNonAttachment = false;
|
||||||
|
|
||||||
foreach (BarrierWithStageFlags<ImageMemoryBarrier, TextureStorage> barrier in _imageBarriers)
|
foreach (BarrierWithStageFlags<ImageMemoryBarrier, TextureStorage> barrier in _imageBarriers)
|
||||||
{
|
{
|
||||||
rpHolder.AddForcedFence(barrier.Resource, barrier.Flags.Dest);
|
// If the binding is an attachment, don't add it as a forced fence.
|
||||||
|
bool isAttachment = rpHolder.ContainsAttachment(barrier.Resource);
|
||||||
|
|
||||||
|
if (!isAttachment)
|
||||||
|
{
|
||||||
|
rpHolder.AddForcedFence(barrier.Resource, barrier.Flags.Dest);
|
||||||
|
anyIsNonAttachment = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_gd.IsTBDR)
|
if (_gd.IsTBDR)
|
||||||
{
|
{
|
||||||
if (!_gd.IsMoltenVk)
|
if (!_gd.IsMoltenVk)
|
||||||
{
|
{
|
||||||
// TBDR GPUs are sensitive to barriers, so we need to end the pass to ensure the data is available.
|
if (!anyIsNonAttachment)
|
||||||
// Metal already has hazard tracking so MVK doesn't need this.
|
{
|
||||||
endRenderPass();
|
// This case is a feedback loop. To prevent this from causing an absolute performance disaster,
|
||||||
inRenderPass = false;
|
// remove the barriers entirely.
|
||||||
|
// If this is not here, there will be a lot of single draw render passes.
|
||||||
|
// TODO: explicit handling for feedback loops, likely outside this class.
|
||||||
|
|
||||||
|
_queuedBarrierCount -= _imageBarriers.Count;
|
||||||
|
_imageBarriers.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TBDR GPUs are sensitive to barriers, so we need to end the pass to ensure the data is available.
|
||||||
|
// Metal already has hazard tracking so MVK doesn't need this.
|
||||||
|
endRenderPass();
|
||||||
|
inRenderPass = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -289,6 +289,19 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
gd.Barriers.Flush(cbs, false, null, null);
|
gd.Barriers.Flush(cbs, false, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddStoreOpUsage()
|
||||||
|
{
|
||||||
|
if (_colors != null)
|
||||||
|
{
|
||||||
|
foreach (var color in _colors)
|
||||||
|
{
|
||||||
|
color.Storage?.AddStoreOpUsage(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_depthStencil?.Storage?.AddStoreOpUsage(true);
|
||||||
|
}
|
||||||
|
|
||||||
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
public (RenderPassHolder rpHolder, Auto<DisposableFramebuffer> framebuffer) GetPassAndFramebuffer(
|
||||||
VulkanRenderer gd,
|
VulkanRenderer gd,
|
||||||
Device device,
|
Device device,
|
||||||
|
|
|
@ -1639,6 +1639,8 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
if (RenderPassActive)
|
if (RenderPassActive)
|
||||||
{
|
{
|
||||||
|
FramebufferParams.AddStoreOpUsage();
|
||||||
|
|
||||||
PauseTransformFeedbackInternal();
|
PauseTransformFeedbackInternal();
|
||||||
Gd.Api.CmdEndRenderPass(CommandBuffer);
|
Gd.Api.CmdEndRenderPass(CommandBuffer);
|
||||||
SignalRenderPassEnd();
|
SignalRenderPassEnd();
|
||||||
|
|
|
@ -192,6 +192,11 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool ContainsAttachment(TextureStorage storage)
|
||||||
|
{
|
||||||
|
return _textures.Any(view => view.Storage == storage);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
// Dispose all framebuffers.
|
// Dispose all framebuffers.
|
||||||
|
|
|
@ -435,6 +435,17 @@ namespace Ryujinx.Graphics.Vulkan
|
||||||
return FormatCapabilities.IsD24S8(Info.Format) && VkFormat == VkFormat.D32SfloatS8Uint;
|
return FormatCapabilities.IsD24S8(Info.Format) && VkFormat == VkFormat.D32SfloatS8Uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddStoreOpUsage(bool depthStencil)
|
||||||
|
{
|
||||||
|
_lastModificationStage = depthStencil ?
|
||||||
|
PipelineStageFlags.LateFragmentTestsBit :
|
||||||
|
PipelineStageFlags.ColorAttachmentOutputBit;
|
||||||
|
|
||||||
|
_lastModificationAccess = depthStencil ?
|
||||||
|
AccessFlags.DepthStencilAttachmentWriteBit :
|
||||||
|
AccessFlags.ColorAttachmentWriteBit;
|
||||||
|
}
|
||||||
|
|
||||||
public void QueueLoadOpBarrier(CommandBufferScoped cbs, bool depthStencil)
|
public void QueueLoadOpBarrier(CommandBufferScoped cbs, bool depthStencil)
|
||||||
{
|
{
|
||||||
PipelineStageFlags srcStageFlags = _lastReadStage | _lastModificationStage;
|
PipelineStageFlags srcStageFlags = _lastReadStage | _lastModificationStage;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue