Implement copy dependency for depth and color textures (#4365)
* Implement copy dependency for depth and color textures * Revert changes added because R32 <-> D32 copies were illegal * Restore depth alias matches
This commit is contained in:
parent
a16d582a10
commit
841dd56f4c
5 changed files with 90 additions and 21 deletions
|
@ -733,9 +733,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
if (overlap.IsView)
|
||||
{
|
||||
overlapCompatibility = overlapCompatibility == TextureViewCompatibility.FormatAlias ?
|
||||
TextureViewCompatibility.Incompatible :
|
||||
TextureViewCompatibility.CopyOnly;
|
||||
overlapCompatibility = TextureViewCompatibility.CopyOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -813,7 +811,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
Texture overlap = _textureOverlaps[index];
|
||||
OverlapInfo oInfo = _overlapInfo[index];
|
||||
|
||||
if (oInfo.Compatibility <= TextureViewCompatibility.LayoutIncompatible || oInfo.Compatibility == TextureViewCompatibility.FormatAlias)
|
||||
if (oInfo.Compatibility <= TextureViewCompatibility.LayoutIncompatible)
|
||||
{
|
||||
if (!overlap.IsView && texture.DataOverlaps(overlap, oInfo.Compatibility))
|
||||
{
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
// D32F and R32F texture have the same representation internally,
|
||||
// however the R32F format is used to sample from depth textures.
|
||||
if (lhs.FormatInfo.Format == Format.D32Float && rhs.FormatInfo.Format == Format.R32Float && (forSampler || depthAlias))
|
||||
if (IsValidDepthAsColorAlias(lhs.FormatInfo.Format, rhs.FormatInfo.Format) && (forSampler || depthAlias))
|
||||
{
|
||||
return TextureMatchQuality.FormatAlias;
|
||||
}
|
||||
|
@ -239,14 +239,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
return TextureMatchQuality.FormatAlias;
|
||||
}
|
||||
|
||||
if (lhs.FormatInfo.Format == Format.D16Unorm && rhs.FormatInfo.Format == Format.R16Unorm)
|
||||
{
|
||||
return TextureMatchQuality.FormatAlias;
|
||||
}
|
||||
|
||||
if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
|
||||
lhs.FormatInfo.Format == Format.S8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
|
||||
else if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
|
||||
lhs.FormatInfo.Format == Format.S8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
|
||||
{
|
||||
return TextureMatchQuality.FormatAlias;
|
||||
}
|
||||
|
@ -632,12 +626,27 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
if (lhsFormat.Format.IsDepthOrStencil() || rhsFormat.Format.IsDepthOrStencil())
|
||||
{
|
||||
return FormatMatches(lhs, rhs, flags.HasFlag(TextureSearchFlags.ForSampler), flags.HasFlag(TextureSearchFlags.DepthAlias)) switch
|
||||
bool forSampler = flags.HasFlag(TextureSearchFlags.ForSampler);
|
||||
bool depthAlias = flags.HasFlag(TextureSearchFlags.DepthAlias);
|
||||
|
||||
TextureMatchQuality matchQuality = FormatMatches(lhs, rhs, forSampler, depthAlias);
|
||||
|
||||
if (matchQuality == TextureMatchQuality.Perfect)
|
||||
{
|
||||
TextureMatchQuality.Perfect => TextureViewCompatibility.Full,
|
||||
TextureMatchQuality.FormatAlias => TextureViewCompatibility.FormatAlias,
|
||||
_ => TextureViewCompatibility.Incompatible,
|
||||
};
|
||||
return TextureViewCompatibility.Full;
|
||||
}
|
||||
else if (matchQuality == TextureMatchQuality.FormatAlias)
|
||||
{
|
||||
return TextureViewCompatibility.FormatAlias;
|
||||
}
|
||||
else if (IsValidColorAsDepthAlias(lhsFormat.Format, rhsFormat.Format) || IsValidDepthAsColorAlias(lhsFormat.Format, rhsFormat.Format))
|
||||
{
|
||||
return TextureViewCompatibility.CopyOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
return TextureViewCompatibility.Incompatible;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsFormatHostIncompatible(lhs, caps) || IsFormatHostIncompatible(rhs, caps))
|
||||
|
@ -666,6 +675,30 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
return TextureViewCompatibility.Incompatible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if it's valid to alias a color format as a depth format.
|
||||
/// </summary>
|
||||
/// <param name="lhsFormat">Source format to be checked</param>
|
||||
/// <param name="rhsFormat">Target format to be checked</param>
|
||||
/// <returns>True if it's valid to alias the formats</returns>
|
||||
private static bool IsValidColorAsDepthAlias(Format lhsFormat, Format rhsFormat)
|
||||
{
|
||||
return (lhsFormat == Format.R32Float && rhsFormat == Format.D32Float) ||
|
||||
(lhsFormat == Format.R16Unorm && rhsFormat == Format.D16Unorm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if it's valid to alias a depth format as a color format.
|
||||
/// </summary>
|
||||
/// <param name="lhsFormat">Source format to be checked</param>
|
||||
/// <param name="rhsFormat">Target format to be checked</param>
|
||||
/// <returns>True if it's valid to alias the formats</returns>
|
||||
private static bool IsValidDepthAsColorAlias(Format lhsFormat, Format rhsFormat)
|
||||
{
|
||||
return (lhsFormat == Format.D32Float && rhsFormat == Format.R32Float) ||
|
||||
(lhsFormat == Format.D16Unorm && rhsFormat == Format.R16Unorm);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks if aliasing of two formats that would normally be considered incompatible be allowed,
|
||||
/// using copy dependencies.
|
||||
|
|
|
@ -367,7 +367,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
return to;
|
||||
}
|
||||
|
||||
private TextureView PboCopy(TextureView from, TextureView to, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int width, int height)
|
||||
public void PboCopy(TextureView from, TextureView to, int srcLayer, int dstLayer, int srcLevel, int dstLevel, int width, int height)
|
||||
{
|
||||
int dstWidth = width;
|
||||
int dstHeight = height;
|
||||
|
@ -445,8 +445,6 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
}
|
||||
|
||||
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
private void EnsurePbo(TextureView view)
|
||||
|
|
|
@ -140,6 +140,28 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
|
||||
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, 0, firstLayer, 0, firstLevel, layers, levels);
|
||||
}
|
||||
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
|
||||
{
|
||||
int layers = Math.Min(Info.GetLayers(), destinationView.Info.GetLayers() - firstLayer);
|
||||
int levels = Math.Min(Info.Levels, destinationView.Info.Levels - firstLevel);
|
||||
|
||||
for (int level = 0; level < levels; level++)
|
||||
{
|
||||
int srcWidth = Math.Max(1, Width >> level);
|
||||
int srcHeight = Math.Max(1, Height >> level);
|
||||
|
||||
int dstWidth = Math.Max(1, destinationView.Width >> (firstLevel + level));
|
||||
int dstHeight = Math.Max(1, destinationView.Height >> (firstLevel + level));
|
||||
|
||||
int minWidth = Math.Min(srcWidth, dstWidth);
|
||||
int minHeight = Math.Min(srcHeight, dstHeight);
|
||||
|
||||
for (int layer = 0; layer < layers; layer++)
|
||||
{
|
||||
_renderer.TextureCopy.PboCopy(this, destinationView, 0, firstLayer + layer, 0, firstLevel + level, minWidth, minHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderer.TextureCopy.CopyUnscaled(this, destinationView, 0, firstLayer, 0, firstLevel);
|
||||
|
@ -169,6 +191,13 @@ namespace Ryujinx.Graphics.OpenGL.Image
|
|||
{
|
||||
_renderer.TextureCopyIncompatible.CopyIncompatibleFormats(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||
}
|
||||
else if (destinationView.Format.IsDepthOrStencil() != Format.IsDepthOrStencil())
|
||||
{
|
||||
int minWidth = Math.Min(Width, destinationView.Width);
|
||||
int minHeight = Math.Min(Height, destinationView.Height);
|
||||
|
||||
_renderer.TextureCopy.PboCopy(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, minWidth, minHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderer.TextureCopy.CopyUnscaled(this, destinationView, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||
|
|
|
@ -211,6 +211,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
int levels = Math.Min(Info.Levels, dst.Info.Levels - firstLevel);
|
||||
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, 0, firstLayer, 0, firstLevel, layers, levels);
|
||||
}
|
||||
else if (src.Info.Format.IsDepthOrStencil() != dst.Info.Format.IsDepthOrStencil())
|
||||
{
|
||||
int layers = Math.Min(Info.GetLayers(), dst.Info.GetLayers() - firstLayer);
|
||||
int levels = Math.Min(Info.Levels, dst.Info.Levels - firstLevel);
|
||||
|
||||
_gd.HelperShader.CopyColor(_gd, cbs, src, dst, 0, firstLayer, 0, FirstLevel, layers, levels);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureCopy.Copy(
|
||||
|
@ -260,6 +267,10 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
{
|
||||
_gd.HelperShader.CopyIncompatibleFormats(_gd, cbs, src, dst, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||
}
|
||||
else if (src.Info.Format.IsDepthOrStencil() != dst.Info.Format.IsDepthOrStencil())
|
||||
{
|
||||
_gd.HelperShader.CopyColor(_gd, cbs, src, dst, srcLayer, dstLayer, srcLevel, dstLevel, 1, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextureCopy.Copy(
|
||||
|
|
Reference in a new issue