Add barriers around vkCmdCopyImage

Write->Read barrier for src image (we want to wait for a write to read it)
Write->Read barrier for dst image (we want to wait for the copy to complete before use)
This commit is contained in:
riperiperi 2021-12-19 02:16:45 +00:00
parent d3e7606a74
commit 066094241a
2 changed files with 40 additions and 9 deletions

View file

@ -246,6 +246,23 @@ namespace Ryujinx.Graphics.Vulkan
int width = Math.Min(srcWidth, dstWidth); int width = Math.Min(srcWidth, dstWidth);
int height = Math.Min(srcHeight, dstHeight); int height = Math.Min(srcHeight, dstHeight);
ImageAspectFlags srcAspect = srcInfo.Format.ConvertAspectFlags();
ImageAspectFlags dstAspect = dstInfo.Format.ConvertAspectFlags();
TextureView.InsertImageBarrier(
api,
commandBuffer,
srcImage,
AccessFlags.AccessTransferWriteBit,
AccessFlags.AccessTransferReadBit,
PipelineStageFlags.PipelineStageAllCommandsBit,
PipelineStageFlags.PipelineStageTransferBit,
srcAspect,
srcViewLayer + srcLayer,
srcViewLevel + srcLevel,
srcLayers,
levels);
for (int level = 0; level < levels; level++) for (int level = 0; level < levels; level++)
{ {
// Stop copy if we are already out of the levels range. // Stop copy if we are already out of the levels range.
@ -255,13 +272,13 @@ namespace Ryujinx.Graphics.Vulkan
} }
var srcSl = new ImageSubresourceLayers( var srcSl = new ImageSubresourceLayers(
srcInfo.Format.ConvertAspectFlags(), srcAspect,
(uint)(srcViewLevel + srcLevel + level), (uint)(srcViewLevel + srcLevel + level),
(uint)(srcViewLayer + srcLayer), (uint)(srcViewLayer + srcLayer),
(uint)srcLayers); (uint)srcLayers);
var dstSl = new ImageSubresourceLayers( var dstSl = new ImageSubresourceLayers(
dstInfo.Format.ConvertAspectFlags(), dstAspect,
(uint)(dstViewLevel + dstLevel + level), (uint)(dstViewLevel + dstLevel + level),
(uint)(dstViewLayer + dstLayer), (uint)(dstViewLayer + dstLayer),
(uint)dstLayers); (uint)dstLayers);
@ -283,6 +300,20 @@ namespace Ryujinx.Graphics.Vulkan
srcDepth = Math.Max(1, srcDepth >> 1); srcDepth = Math.Max(1, srcDepth >> 1);
} }
} }
TextureView.InsertImageBarrier(
api,
commandBuffer,
dstImage,
AccessFlags.AccessTransferWriteBit,
AccessFlags.AccessTransferReadBit,
PipelineStageFlags.PipelineStageTransferBit,
PipelineStageFlags.PipelineStageAllCommandsBit,
dstAspect,
dstViewLayer + dstLayer,
dstViewLevel + dstLevel,
dstLayers,
levels);
} }
} }
} }

View file

@ -153,8 +153,6 @@ namespace Ryujinx.Graphics.Vulkan
public void CopyTo(ITexture destination, int firstLayer, int firstLevel) public void CopyTo(ITexture destination, int firstLayer, int firstLevel)
{ {
_gd.FlushAllCommands();
var src = this; var src = this;
var dst = (TextureView)destination; var dst = (TextureView)destination;
@ -163,7 +161,9 @@ namespace Ryujinx.Graphics.Vulkan
return; return;
} }
using var cbs = _gd.CommandBufferPool.Rent(); _gd.PipelineInternal.EndRenderPass();
var cbs = _gd.PipelineInternal.CurrentCommandBuffer;
var srcImage = src.GetImage().Get(cbs).Value; var srcImage = src.GetImage().Get(cbs).Value;
var dstImage = dst.GetImage().Get(cbs).Value; var dstImage = dst.GetImage().Get(cbs).Value;
@ -471,7 +471,7 @@ namespace Ryujinx.Graphics.Vulkan
aspectFlags); aspectFlags);
InsertImageBarrier( InsertImageBarrier(
gd, gd.Api,
cbs.CommandBuffer, cbs.CommandBuffer,
srcTemp.GetImage().Get(cbs).Value, srcTemp.GetImage().Get(cbs).Value,
AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferWriteBit,
@ -504,7 +504,7 @@ namespace Ryujinx.Graphics.Vulkan
aspectFlags); aspectFlags);
InsertImageBarrier( InsertImageBarrier(
gd, gd.Api,
cbs.CommandBuffer, cbs.CommandBuffer,
dstTemp.GetImage().Get(cbs).Value, dstTemp.GetImage().Get(cbs).Value,
AccessFlags.AccessTransferWriteBit, AccessFlags.AccessTransferWriteBit,
@ -564,7 +564,7 @@ namespace Ryujinx.Graphics.Vulkan
} }
public static unsafe void InsertImageBarrier( public static unsafe void InsertImageBarrier(
VulkanGraphicsDevice gd, Vk api,
CommandBuffer commandBuffer, CommandBuffer commandBuffer,
Image image, Image image,
AccessFlags srcAccessMask, AccessFlags srcAccessMask,
@ -590,7 +590,7 @@ namespace Ryujinx.Graphics.Vulkan
SubresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, (uint)levels, (uint)firstLayer, (uint)layers) SubresourceRange = new ImageSubresourceRange(aspectFlags, (uint)firstLevel, (uint)levels, (uint)firstLayer, (uint)layers)
}; };
gd.Api.CmdPipelineBarrier( api.CmdPipelineBarrier(
commandBuffer, commandBuffer,
srcStageMask, srcStageMask,
dstStageMask, dstStageMask,