diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index e1f00606f..cfb7a3b76 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -1136,17 +1136,33 @@ namespace Ryujinx.Graphics.Gpu.Image
/// Texture view physical memory ranges
/// Layer size on the given texture
/// Host GPU capabilities
+ /// Indicates that multisample textures are allowed to match non-multisample requested textures
/// Texture view initial layer on this texture
/// Texture view first mipmap level on this texture
/// The level of compatiblilty a view with the given parameters created from this texture has
- public TextureViewCompatibility IsViewCompatible(TextureInfo info, MultiRange range, int layerSize, Capabilities caps, out int firstLayer, out int firstLevel)
+ public TextureViewCompatibility IsViewCompatible(TextureInfo info, MultiRange range, int layerSize, Capabilities caps, bool allowMs, out int firstLayer, out int firstLevel)
{
TextureViewCompatibility result = TextureViewCompatibility.Full;
result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewFormatCompatible(Info, info, caps));
if (result != TextureViewCompatibility.Incompatible)
{
- result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewTargetCompatible(Info, info));
+ bool msTargetCompatible = false;
+
+ if (allowMs)
+ {
+ msTargetCompatible = Info.Target == Target.Texture2DMultisample && info.Target == Target.Texture2D;
+ }
+
+ if (!msTargetCompatible)
+ {
+ result = TextureCompatibility.PropagateViewCompatibility(result, TextureCompatibility.ViewTargetCompatible(Info, info));
+
+ if (Info.SamplesInX != info.SamplesInX || Info.SamplesInY != info.SamplesInY)
+ {
+ result = TextureViewCompatibility.Incompatible;
+ }
+ }
if (result == TextureViewCompatibility.Full && Info.FormatInfo.Format != info.FormatInfo.Format && !_context.Capabilities.SupportsMismatchingViewFormat)
{
@@ -1156,11 +1172,6 @@ namespace Ryujinx.Graphics.Gpu.Image
result = TextureViewCompatibility.CopyOnly;
}
-
- if (Info.SamplesInX != info.SamplesInX || Info.SamplesInY != info.SamplesInY)
- {
- result = TextureViewCompatibility.Incompatible;
- }
}
firstLayer = 0;
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
index 162483081..4fa80c95d 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCache.cs
@@ -542,7 +542,14 @@ namespace Ryujinx.Graphics.Gpu.Image
for (int index = 0; index < overlapsCount; index++)
{
Texture overlap = _textureOverlaps[index];
- TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(info, range.Value, sizeInfo.LayerSize, _context.Capabilities, out int firstLayer, out int firstLevel);
+ TextureViewCompatibility overlapCompatibility = overlap.IsViewCompatible(
+ info,
+ range.Value,
+ sizeInfo.LayerSize,
+ _context.Capabilities,
+ flags.HasFlag(TextureSearchFlags.ForCopy),
+ out int firstLayer,
+ out int firstLevel);
if (overlapCompatibility == TextureViewCompatibility.Full)
{
@@ -650,7 +657,14 @@ namespace Ryujinx.Graphics.Gpu.Image
Texture overlap = _textureOverlaps[index];
bool overlapInCache = overlap.CacheNode != null;
- TextureViewCompatibility compatibility = texture.IsViewCompatible(overlap.Info, overlap.Range, overlap.LayerSize, _context.Capabilities, out int firstLayer, out int firstLevel);
+ TextureViewCompatibility compatibility = texture.IsViewCompatible(
+ overlap.Info,
+ overlap.Range,
+ overlap.LayerSize,
+ _context.Capabilities,
+ false,
+ out int firstLayer,
+ out int firstLevel);
if (overlap.IsView && compatibility == TextureViewCompatibility.Full)
{
@@ -1000,20 +1014,34 @@ namespace Ryujinx.Graphics.Gpu.Image
depthOrLayers = info.DepthOrLayers;
}
+ // 2D and 2D multisample textures are not considered compatible.
+ // This specific case is required for copies, where the source texture might be multisample.
+ // In this case, we inherit the parent texture multisample state.
+ Target target = info.Target;
+ int samplesInX = info.SamplesInX;
+ int samplesInY = info.SamplesInY;
+
+ if (target == Target.Texture2D && parent.Target == Target.Texture2DMultisample)
+ {
+ target = Target.Texture2DMultisample;
+ samplesInX = parent.Info.SamplesInX;
+ samplesInY = parent.Info.SamplesInY;
+ }
+
return new TextureInfo(
info.GpuAddress,
width,
height,
depthOrLayers,
info.Levels,
- info.SamplesInX,
- info.SamplesInY,
+ samplesInX,
+ samplesInY,
info.Stride,
info.IsLinear,
info.GobBlocksInY,
info.GobBlocksInZ,
info.GobBlocksInTileX,
- info.Target,
+ target,
info.FormatInfo,
info.DepthStencilMode,
info.SwizzleR,