diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 432b108535..6b92c0aaf6 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -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))
{
diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index 3a0efcddaa..5af0471c02 100644
--- a/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/src/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -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;
}
+ ///
+ /// Checks if it's valid to alias a color format as a depth format.
+ ///
+ /// Source format to be checked
+ /// Target format to be checked
+ /// True if it's valid to alias the formats
+ private static bool IsValidColorAsDepthAlias(Format lhsFormat, Format rhsFormat)
+ {
+ return (lhsFormat == Format.R32Float && rhsFormat == Format.D32Float) ||
+ (lhsFormat == Format.R16Unorm && rhsFormat == Format.D16Unorm);
+ }
+
+ ///
+ /// Checks if it's valid to alias a depth format as a color format.
+ ///
+ /// Source format to be checked
+ /// Target format to be checked
+ /// True if it's valid to alias the formats
+ private static bool IsValidDepthAsColorAlias(Format lhsFormat, Format rhsFormat)
+ {
+ return (lhsFormat == Format.D32Float && rhsFormat == Format.R32Float) ||
+ (lhsFormat == Format.D16Unorm && rhsFormat == Format.R16Unorm);
+ }
+
///
/// Checks if aliasing of two formats that would normally be considered incompatible be allowed,
/// using copy dependencies.
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
index e33940cb13..128f481f67 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureCopy.cs
@@ -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)
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
index 0f5fe46a5f..7f1b1c3824 100644
--- a/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
+++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureView.cs
@@ -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);
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs
index 09128f0075..05dbd15cef 100644
--- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs
+++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs
@@ -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(