Implement safe depth-stencil blit using stencil export extension (#4356)
* Implement safe depth-stencil blit using stencil export extension * Delete depth-stencil blit with buffer path
This commit is contained in:
parent
43081c16c4
commit
7528f94536
10 changed files with 330 additions and 213 deletions
|
@ -362,21 +362,16 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
levels,
|
||||
linearFilter);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (srcFormat == GAL.Format.D32FloatS8Uint && srcFormat == dstFormat && SupportsBlitFromD32FS8ToD32FAndS8())
|
||||
{
|
||||
BlitDepthStencilWithBuffer(_gd, cbs, src, dst, srcRegion, dstRegion);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool isDepthOrStencil = dst.Info.Format.IsDepthOrStencil();
|
||||
|
||||
if (VulkanConfiguration.UseSlowSafeBlitOnAmd &&
|
||||
(_gd.Vendor == Vendor.Amd || _gd.IsMoltenVk) &&
|
||||
src.Info.Target == Target.Texture2D &&
|
||||
dst.Info.Target == Target.Texture2D &&
|
||||
!dst.Info.Format.IsDepthOrStencil())
|
||||
dst.Info.Target == Target.Texture2D)
|
||||
{
|
||||
_gd.HelperShader.Blit(
|
||||
_gd,
|
||||
|
@ -387,6 +382,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
dst.VkFormat,
|
||||
srcRegion,
|
||||
dstRegion,
|
||||
isDepthOrStencil,
|
||||
linearFilter);
|
||||
|
||||
return;
|
||||
|
@ -395,7 +391,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
Auto<DisposableImage> srcImage;
|
||||
Auto<DisposableImage> dstImage;
|
||||
|
||||
if (dst.Info.Format.IsDepthOrStencil())
|
||||
if (isDepthOrStencil)
|
||||
{
|
||||
srcImage = src.Storage.CreateAliasedColorForDepthStorageUnsafe(srcFormat).GetImage();
|
||||
dstImage = dst.Storage.CreateAliasedColorForDepthStorageUnsafe(dstFormat).GetImage();
|
||||
|
@ -426,189 +422,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
ImageAspectFlags.ColorBit);
|
||||
}
|
||||
|
||||
private static void BlitDepthStencilWithBuffer(
|
||||
VulkanRenderer gd,
|
||||
CommandBufferScoped cbs,
|
||||
TextureView src,
|
||||
TextureView dst,
|
||||
Extents2D srcRegion,
|
||||
Extents2D dstRegion)
|
||||
{
|
||||
int drBaseX = Math.Min(dstRegion.X1, dstRegion.X2);
|
||||
int drBaseY = Math.Min(dstRegion.Y1, dstRegion.Y2);
|
||||
int drWidth = Math.Abs(dstRegion.X2 - dstRegion.X1);
|
||||
int drHeight = Math.Abs(dstRegion.Y2 - dstRegion.Y1);
|
||||
|
||||
var drOriginZero = new Extents2D(
|
||||
dstRegion.X1 - drBaseX,
|
||||
dstRegion.Y1 - drBaseY,
|
||||
dstRegion.X2 - drBaseX,
|
||||
dstRegion.Y2 - drBaseY);
|
||||
|
||||
var d32SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.D32Float, 4);
|
||||
var d32DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.D32Float, 4, drWidth, drHeight);
|
||||
var s8SrcStorageInfo = TextureStorage.NewCreateInfoWith(ref src._info, GAL.Format.S8Uint, 1);
|
||||
var s8DstStorageInfo = TextureStorage.NewCreateInfoWith(ref dst._info, GAL.Format.S8Uint, 1, drWidth, drHeight);
|
||||
|
||||
using var d32SrcStorage = gd.CreateTextureStorage(d32SrcStorageInfo, src.Storage.ScaleFactor);
|
||||
using var d32DstStorage = gd.CreateTextureStorage(d32DstStorageInfo, dst.Storage.ScaleFactor);
|
||||
using var s8SrcStorage = gd.CreateTextureStorage(s8SrcStorageInfo, src.Storage.ScaleFactor);
|
||||
using var s8DstStorage = gd.CreateTextureStorage(s8DstStorageInfo, dst.Storage.ScaleFactor);
|
||||
|
||||
void SlowBlit(TextureStorage srcTemp, TextureStorage dstTemp, ImageAspectFlags aspectFlags)
|
||||
{
|
||||
int levels = Math.Min(src.Info.Levels, dst.Info.Levels);
|
||||
|
||||
int srcSize = 0;
|
||||
int dstSize = 0;
|
||||
|
||||
for (int l = 0; l < levels; l++)
|
||||
{
|
||||
srcSize += srcTemp.Info.GetMipSize2D(l);
|
||||
dstSize += dstTemp.Info.GetMipSize2D(l);
|
||||
}
|
||||
|
||||
using var srcTempBuffer = gd.BufferManager.Create(gd, srcSize, deviceLocal: true);
|
||||
using var dstTempBuffer = gd.BufferManager.Create(gd, dstSize, deviceLocal: true);
|
||||
|
||||
src.Storage.CopyFromOrToBuffer(
|
||||
cbs.CommandBuffer,
|
||||
srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
|
||||
src.GetImage().Get(cbs).Value,
|
||||
srcSize,
|
||||
to: true,
|
||||
0,
|
||||
0,
|
||||
src.FirstLayer,
|
||||
src.FirstLevel,
|
||||
1,
|
||||
levels,
|
||||
true,
|
||||
aspectFlags,
|
||||
false);
|
||||
|
||||
BufferHolder.InsertBufferBarrier(
|
||||
gd,
|
||||
cbs.CommandBuffer,
|
||||
srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
|
||||
AccessFlags.TransferWriteBit,
|
||||
AccessFlags.TransferReadBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
0,
|
||||
srcSize);
|
||||
|
||||
srcTemp.CopyFromOrToBuffer(
|
||||
cbs.CommandBuffer,
|
||||
srcTempBuffer.GetBuffer().Get(cbs, 0, srcSize).Value,
|
||||
srcTemp.GetImage().Get(cbs).Value,
|
||||
srcSize,
|
||||
to: false,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
levels,
|
||||
true,
|
||||
aspectFlags,
|
||||
false);
|
||||
|
||||
InsertImageBarrier(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
srcTemp.GetImage().Get(cbs).Value,
|
||||
AccessFlags.TransferWriteBit,
|
||||
AccessFlags.TransferReadBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
aspectFlags,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
levels);
|
||||
|
||||
TextureCopy.Blit(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
srcTemp.GetImage().Get(cbs).Value,
|
||||
dstTemp.GetImage().Get(cbs).Value,
|
||||
srcTemp.Info,
|
||||
dstTemp.Info,
|
||||
srcRegion,
|
||||
drOriginZero,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
levels,
|
||||
false,
|
||||
aspectFlags,
|
||||
aspectFlags);
|
||||
|
||||
InsertImageBarrier(
|
||||
gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
dstTemp.GetImage().Get(cbs).Value,
|
||||
AccessFlags.TransferWriteBit,
|
||||
AccessFlags.TransferReadBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
aspectFlags,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
levels);
|
||||
|
||||
dstTemp.CopyFromOrToBuffer(
|
||||
cbs.CommandBuffer,
|
||||
dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
|
||||
dstTemp.GetImage().Get(cbs).Value,
|
||||
dstSize,
|
||||
to: true,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
levels,
|
||||
true,
|
||||
aspectFlags,
|
||||
false);
|
||||
|
||||
BufferHolder.InsertBufferBarrier(
|
||||
gd,
|
||||
cbs.CommandBuffer,
|
||||
dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
|
||||
AccessFlags.TransferWriteBit,
|
||||
AccessFlags.TransferReadBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
0,
|
||||
dstSize);
|
||||
|
||||
dst.Storage.CopyFromOrToBuffer(
|
||||
cbs.CommandBuffer,
|
||||
dstTempBuffer.GetBuffer().Get(cbs, 0, dstSize).Value,
|
||||
dst.GetImage().Get(cbs).Value,
|
||||
dstSize,
|
||||
to: false,
|
||||
drBaseX,
|
||||
drBaseY,
|
||||
dst.FirstLayer,
|
||||
dst.FirstLevel,
|
||||
1,
|
||||
levels,
|
||||
true,
|
||||
aspectFlags,
|
||||
false);
|
||||
}
|
||||
|
||||
SlowBlit(d32SrcStorage, d32DstStorage, ImageAspectFlags.DepthBit);
|
||||
SlowBlit(s8SrcStorage, s8DstStorage, ImageAspectFlags.StencilBit);
|
||||
}
|
||||
|
||||
public static unsafe void InsertImageBarrier(
|
||||
Vk api,
|
||||
CommandBuffer commandBuffer,
|
||||
|
@ -649,13 +462,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
memoryBarrier);
|
||||
}
|
||||
|
||||
private bool SupportsBlitFromD32FS8ToD32FAndS8()
|
||||
{
|
||||
var formatFeatureFlags = FormatFeatureFlags.BlitSrcBit | FormatFeatureFlags.BlitDstBit;
|
||||
return _gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.D32Float) &&
|
||||
_gd.FormatCapabilities.OptimalFormatSupports(formatFeatureFlags, GAL.Format.S8Uint);
|
||||
}
|
||||
|
||||
public TextureView GetView(GAL.Format format)
|
||||
{
|
||||
if (format == Info.Format)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue