diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
index af7ac038f..8e92685bc 100644
--- a/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/MethodCopyTexture.cs
@@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Gpu.State;
using System;
@@ -28,16 +29,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
// When the source texture that was found has a depth format,
// we must enforce the target texture also has a depth format,
// as copies between depth and color formats are not allowed.
- dstCopyTexture.Format = srcTexture.Format switch
- {
- Format.S8Uint => RtFormat.S8Uint,
- Format.D16Unorm => RtFormat.D16Unorm,
- Format.D24X8Unorm => RtFormat.D24Unorm,
- Format.D32Float => RtFormat.D32Float,
- Format.D24UnormS8Uint => RtFormat.D24UnormS8Uint,
- Format.D32FloatS8Uint => RtFormat.D32FloatS8Uint,
- _ => dstCopyTexture.Format
- };
+ dstCopyTexture.Format = TextureCompatibility.DeriveDepthFormat(dstCopyTexture.Format, srcTexture.Format);
Texture dstTexture = TextureManager.FindOrCreateTexture(dstCopyTexture, srcTexture.ScaleMode == Image.TextureScaleMode.Scaled);
diff --git a/Ryujinx.Graphics.Gpu/Image/Texture.cs b/Ryujinx.Graphics.Gpu/Image/Texture.cs
index a312a8b7e..2a61b441c 100644
--- a/Ryujinx.Graphics.Gpu/Image/Texture.cs
+++ b/Ryujinx.Graphics.Gpu/Image/Texture.cs
@@ -659,32 +659,31 @@ namespace Ryujinx.Graphics.Gpu.Image
}
///
- /// Performs a comparison of this texture information, with the specified texture information.
- /// This performs a strict comparison, used to check if two textures are equal.
+ /// This performs a strict comparison, used to check if this texture is equal to the one supplied.
///
- /// Texture information to compare with
+ /// Texture information to compare against
/// Comparison flags
/// True if the textures are strictly equal or similar, false otherwise
public bool IsPerfectMatch(TextureInfo info, TextureSearchFlags flags)
{
- if (!FormatMatches(info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0))
+ if (!TextureCompatibility.FormatMatches(Info, info, (flags & TextureSearchFlags.ForSampler) != 0, (flags & TextureSearchFlags.ForCopy) != 0))
{
return false;
}
- if (!LayoutMatches(info))
+ if (!TextureCompatibility.LayoutMatches(Info, info))
{
return false;
}
- if (!SizeMatches(info, (flags & TextureSearchFlags.Strict) == 0))
+ if (!TextureCompatibility.SizeMatches(Info, info))
{
return false;
}
if ((flags & TextureSearchFlags.ForSampler) != 0 || (flags & TextureSearchFlags.Strict) != 0)
{
- if (!SamplerParamsMatches(info))
+ if (!TextureCompatibility.SamplerParamsMatches(Info, info))
{
return false;
}
@@ -694,12 +693,12 @@ namespace Ryujinx.Graphics.Gpu.Image
{
bool msTargetCompatible = Info.Target == Target.Texture2DMultisample && info.Target == Target.Texture2D;
- if (!msTargetCompatible && !TargetAndSamplesCompatible(info))
+ if (!msTargetCompatible && !TextureCompatibility.TargetAndSamplesCompatible(Info, info))
{
return false;
}
}
- else if (!TargetAndSamplesCompatible(info))
+ else if (!TextureCompatibility.TargetAndSamplesCompatible(Info, info))
{
return false;
}
@@ -707,153 +706,6 @@ namespace Ryujinx.Graphics.Gpu.Image
return Info.Address == info.Address && Info.Levels == info.Levels;
}
- ///
- /// Checks if the texture format matches with the specified texture information.
- ///
- /// Texture information to compare with
- /// Indicates that the texture will be used for shader sampling
- /// Indicates that the texture will be used as copy source or target
- /// True if the format matches, with the given comparison rules
- private bool FormatMatches(TextureInfo info, bool forSampler, bool forCopy)
- {
- // D32F and R32F texture have the same representation internally,
- // however the R32F format is used to sample from depth textures.
- if (Info.FormatInfo.Format == Format.D32Float && info.FormatInfo.Format == Format.R32Float && (forSampler || forCopy))
- {
- return true;
- }
-
- if (forCopy)
- {
- // The 2D engine does not support depth-stencil formats, so it will instead
- // use equivalent color formats. We must also consider them as compatible.
- if (Info.FormatInfo.Format == Format.S8Uint && info.FormatInfo.Format == Format.R8Unorm)
- {
- return true;
- }
-
- if (Info.FormatInfo.Format == Format.D16Unorm && info.FormatInfo.Format == Format.R16Unorm)
- {
- return true;
- }
-
- if ((Info.FormatInfo.Format == Format.D24UnormS8Uint ||
- Info.FormatInfo.Format == Format.D24X8Unorm) && info.FormatInfo.Format == Format.B8G8R8A8Unorm)
- {
- return true;
- }
- }
-
- return Info.FormatInfo.Format == info.FormatInfo.Format;
- }
-
- ///
- /// Checks if the texture layout specified matches with this texture layout.
- /// The layout information is composed of the Stride for linear textures, or GOB block size
- /// for block linear textures.
- ///
- /// Texture information to compare with
- /// True if the layout matches, false otherwise
- private bool LayoutMatches(TextureInfo info)
- {
- if (Info.IsLinear != info.IsLinear)
- {
- return false;
- }
-
- // For linear textures, gob block sizes are ignored.
- // For block linear textures, the stride is ignored.
- if (info.IsLinear)
- {
- return Info.Stride == info.Stride;
- }
- else
- {
- return Info.GobBlocksInY == info.GobBlocksInY &&
- Info.GobBlocksInZ == info.GobBlocksInZ;
- }
- }
-
- ///
- /// Checks if the texture sizes of the supplied texture information matches this texture.
- ///
- /// Texture information to compare with
- /// True if the size matches, false otherwise
- public bool SizeMatches(TextureInfo info)
- {
- return SizeMatches(info, alignSizes: false);
- }
-
- ///
- /// Checks if the texture sizes of the supplied texture information matches the given level of
- /// this texture.
- ///
- /// Texture information to compare with
- /// Mipmap level of this texture to compare with
- /// True if the size matches with the level, false otherwise
- public bool SizeMatches(TextureInfo info, int level)
- {
- return Math.Max(1, Info.Width >> level) == info.Width &&
- Math.Max(1, Info.Height >> level) == info.Height &&
- Math.Max(1, Info.GetDepth() >> level) == info.GetDepth();
- }
-
- ///
- /// Checks if the texture sizes of the supplied texture information matches this texture.
- ///
- /// Texture information to compare with
- /// True to align the sizes according to the texture layout for comparison
- /// True if the sizes matches, false otherwise
- private bool SizeMatches(TextureInfo info, bool alignSizes)
- {
- if (Info.GetLayers() != info.GetLayers())
- {
- return false;
- }
-
- if (alignSizes)
- {
- Size size0 = GetAlignedSize(Info);
- Size size1 = GetAlignedSize(info);
-
- return size0.Width == size1.Width &&
- size0.Height == size1.Height &&
- size0.Depth == size1.Depth;
- }
- else
- {
- return Info.Width == info.Width &&
- Info.Height == info.Height &&
- Info.GetDepth() == info.GetDepth();
- }
- }
-
- ///
- /// Checks if the texture shader sampling parameters matches.
- ///
- /// Texture information to compare with
- /// True if the texture shader sampling parameters matches, false otherwise
- private bool SamplerParamsMatches(TextureInfo info)
- {
- return Info.DepthStencilMode == info.DepthStencilMode &&
- Info.SwizzleR == info.SwizzleR &&
- Info.SwizzleG == info.SwizzleG &&
- Info.SwizzleB == info.SwizzleB &&
- Info.SwizzleA == info.SwizzleA;
- }
-
- ///
- /// Check if the texture target and samples count (for multisampled textures) matches.
- ///
- /// Texture information to compare with
- /// True if the texture target and samples count matches, false otherwise
- private bool TargetAndSamplesCompatible(TextureInfo info)
- {
- return Info.Target == info.Target &&
- Info.SamplesInX == info.SamplesInX &&
- Info.SamplesInY == info.SamplesInY;
- }
-
///
/// Check if it's possible to create a view, with the given parameters, from this texture.
///
@@ -903,22 +755,22 @@ namespace Ryujinx.Graphics.Gpu.Image
return false;
}
- if (!ViewLayoutCompatible(info, firstLevel))
+ if (!TextureCompatibility.ViewLayoutCompatible(Info, info, firstLevel))
{
return false;
}
- if (!ViewFormatCompatible(info))
+ if (!TextureCompatibility.ViewFormatCompatible(Info, info))
{
return false;
}
- if (!ViewSizeMatches(info, firstLevel, isCopy))
+ if (!TextureCompatibility.ViewSizeMatches(Info, info, firstLevel, isCopy))
{
return false;
}
- if (!ViewTargetCompatible(info, isCopy))
+ if (!TextureCompatibility.ViewTargetCompatible(Info, info, isCopy))
{
return false;
}
@@ -927,167 +779,6 @@ namespace Ryujinx.Graphics.Gpu.Image
Info.SamplesInY == info.SamplesInY;
}
- ///
- /// Check if it's possible to create a view with the specified layout.
- /// The layout information is composed of the Stride for linear textures, or GOB block size
- /// for block linear textures.
- ///
- /// Texture information of the texture view
- /// Start level of the texture view, in relation with this texture
- /// True if the layout is compatible, false otherwise
- private bool ViewLayoutCompatible(TextureInfo info, int level)
- {
- if (Info.IsLinear != info.IsLinear)
- {
- return false;
- }
-
- // For linear textures, gob block sizes are ignored.
- // For block linear textures, the stride is ignored.
- if (info.IsLinear)
- {
- int width = Math.Max(1, Info.Width >> level);
-
- int stride = width * Info.FormatInfo.BytesPerPixel;
-
- stride = BitUtils.AlignUp(stride, 32);
-
- return stride == info.Stride;
- }
- else
- {
- int height = Math.Max(1, Info.Height >> level);
- int depth = Math.Max(1, Info.GetDepth() >> level);
-
- (int gobBlocksInY, int gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(
- height,
- depth,
- Info.FormatInfo.BlockHeight,
- Info.GobBlocksInY,
- Info.GobBlocksInZ);
-
- return gobBlocksInY == info.GobBlocksInY &&
- gobBlocksInZ == info.GobBlocksInZ;
- }
- }
-
- ///
- /// Checks if the view format is compatible with this texture format.
- /// In general, the formats are considered compatible if the bytes per pixel values are equal,
- /// but there are more complex rules for some formats, like compressed or depth-stencil formats.
- /// This follows the host API copy compatibility rules.
- ///
- /// Texture information of the texture view
- /// True if the formats are compatible, false otherwise
- private bool ViewFormatCompatible(TextureInfo info)
- {
- return TextureCompatibility.FormatCompatible(Info.FormatInfo, info.FormatInfo);
- }
-
- ///
- /// Checks if the size of a given texture view is compatible with this texture.
- ///
- /// Texture information of the texture view
- /// Mipmap level of the texture view in relation to this texture
- /// True to check for copy compatibility rather than view compatibility
- /// True if the sizes are compatible, false otherwise
- private bool ViewSizeMatches(TextureInfo info, int level, bool isCopy)
- {
- Size size = GetAlignedSize(Info, level);
-
- Size otherSize = GetAlignedSize(info);
-
- // For copies, we can copy a subset of the 3D texture slices,
- // so the depth may be different in this case.
- if (!isCopy && info.Target == Target.Texture3D && size.Depth != otherSize.Depth)
- {
- return false;
- }
-
- return size.Width == otherSize.Width &&
- size.Height == otherSize.Height;
- }
-
- ///
- /// Check if the target of the specified texture view information is compatible with this
- /// texture.
- /// This follows the host API target compatibility rules.
- ///
- /// Texture information of the texture view
- /// True to check for copy rather than view compatibility
- /// True if the targets are compatible, false otherwise
- private bool ViewTargetCompatible(TextureInfo info, bool isCopy)
- {
- switch (Info.Target)
- {
- case Target.Texture1D:
- case Target.Texture1DArray:
- return info.Target == Target.Texture1D ||
- info.Target == Target.Texture1DArray;
-
- case Target.Texture2D:
- return info.Target == Target.Texture2D ||
- info.Target == Target.Texture2DArray;
-
- case Target.Texture2DArray:
- case Target.Cubemap:
- case Target.CubemapArray:
- return info.Target == Target.Texture2D ||
- info.Target == Target.Texture2DArray ||
- info.Target == Target.Cubemap ||
- info.Target == Target.CubemapArray;
-
- case Target.Texture2DMultisample:
- case Target.Texture2DMultisampleArray:
- return info.Target == Target.Texture2DMultisample ||
- info.Target == Target.Texture2DMultisampleArray;
-
- case Target.Texture3D:
- return info.Target == Target.Texture3D ||
- (info.Target == Target.Texture2D && isCopy);
- }
-
- return false;
- }
-
- ///
- /// Gets the aligned sizes of the specified texture information.
- /// The alignment depends on the texture layout and format bytes per pixel.
- ///
- /// Texture information to calculate the aligned size from
- /// Mipmap level for texture views
- /// The aligned texture size
- private static Size GetAlignedSize(TextureInfo info, int level = 0)
- {
- int width = Math.Max(1, info.Width >> level);
- int height = Math.Max(1, info.Height >> level);
-
- if (info.IsLinear)
- {
- return SizeCalculator.GetLinearAlignedSize(
- width,
- height,
- info.FormatInfo.BlockWidth,
- info.FormatInfo.BlockHeight,
- info.FormatInfo.BytesPerPixel);
- }
- else
- {
- int depth = Math.Max(1, info.GetDepth() >> level);
-
- return SizeCalculator.GetBlockLinearAlignedSize(
- width,
- height,
- depth,
- info.FormatInfo.BlockWidth,
- info.FormatInfo.BlockHeight,
- info.FormatInfo.BytesPerPixel,
- info.GobBlocksInY,
- info.GobBlocksInZ,
- info.GobBlocksInTileX);
- }
- }
-
///
/// Gets a texture of the specified target type from this texture.
/// This can be used to get an array texture from a non-array texture and vice-versa.
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
index 408f6e2ac..b64a85a5d 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureCompatibility.cs
@@ -1,4 +1,8 @@
+using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.State;
+using Ryujinx.Graphics.Texture;
+using System;
namespace Ryujinx.Graphics.Gpu.Image
{
@@ -22,6 +26,26 @@ namespace Ryujinx.Graphics.Gpu.Image
Bc7
}
+ ///
+ /// Finds the appropriate depth format for a copy texture if the source texture has a depth format.
+ ///
+ /// Destination CopyTexture Format
+ /// Source Texture Format
+ /// Derived RtFormat if srcTextureFormat is a depth format, otherwise return dstTextureFormat.
+ public static RtFormat DeriveDepthFormat(RtFormat dstTextureFormat, Format srcTextureFormat)
+ {
+ return srcTextureFormat switch
+ {
+ Format.S8Uint => RtFormat.S8Uint,
+ Format.D16Unorm => RtFormat.D16Unorm,
+ Format.D24X8Unorm => RtFormat.D24Unorm,
+ Format.D32Float => RtFormat.D32Float,
+ Format.D24UnormS8Uint => RtFormat.D24UnormS8Uint,
+ Format.D32FloatS8Uint => RtFormat.D32FloatS8Uint,
+ _ => dstTextureFormat
+ };
+ }
+
///
/// Checks if two formats are compatible, according to the host API copy format compatibility rules.
///
@@ -53,6 +77,321 @@ namespace Ryujinx.Graphics.Gpu.Image
}
}
+ ///
+ /// Checks if the texture format matches with the specified texture information.
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// Indicates that the texture will be used for shader sampling
+ /// Indicates that the texture will be used as copy source or target
+ /// True if the format matches, with the given comparison rules
+ public static bool FormatMatches(TextureInfo lhs, TextureInfo rhs, bool forSampler, bool forCopy)
+ {
+ // 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 || forCopy))
+ {
+ return true;
+ }
+
+ if (forCopy)
+ {
+ // The 2D engine does not support depth-stencil formats, so it will instead
+ // use equivalent color formats. We must also consider them as compatible.
+ if (lhs.FormatInfo.Format == Format.S8Uint && rhs.FormatInfo.Format == Format.R8Unorm)
+ {
+ return true;
+ }
+
+ if (lhs.FormatInfo.Format == Format.D16Unorm && rhs.FormatInfo.Format == Format.R16Unorm)
+ {
+ return true;
+ }
+
+ if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
+ lhs.FormatInfo.Format == Format.D24X8Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
+ {
+ return true;
+ }
+ }
+
+ return lhs.FormatInfo.Format == rhs.FormatInfo.Format;
+ }
+
+ ///
+ /// Checks if the texture layout specified matches with this texture layout.
+ /// The layout information is composed of the Stride for linear textures, or GOB block size
+ /// for block linear textures.
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// True if the layout matches, false otherwise
+ public static bool LayoutMatches(TextureInfo lhs, TextureInfo rhs)
+ {
+ if (lhs.IsLinear != rhs.IsLinear)
+ {
+ return false;
+ }
+
+ // For linear textures, gob block sizes are ignored.
+ // For block linear textures, the stride is ignored.
+ if (rhs.IsLinear)
+ {
+ return lhs.Stride == rhs.Stride;
+ }
+ else
+ {
+ return lhs.GobBlocksInY == rhs.GobBlocksInY &&
+ lhs.GobBlocksInZ == rhs.GobBlocksInZ;
+ }
+ }
+
+ ///
+ /// Checks if the view sizes of a two given texture informations match.
+ ///
+ /// Texture information of the texture view
+ /// Texture information of the texture view to match against
+ /// Mipmap level of the texture view in relation to this texture
+ /// True to check for copy compatibility rather than view compatibility
+ /// True if the sizes are compatible, false otherwise
+ public static bool ViewSizeMatches(TextureInfo lhs, TextureInfo rhs, int level, bool isCopy)
+ {
+ Size size = GetAlignedSize(lhs, level);
+
+ Size otherSize = GetAlignedSize(rhs);
+
+ // For copies, we can copy a subset of the 3D texture slices,
+ // so the depth may be different in this case.
+ if (!isCopy && rhs.Target == Target.Texture3D && size.Depth != otherSize.Depth)
+ {
+ return false;
+ }
+
+ return size.Width == otherSize.Width &&
+ size.Height == otherSize.Height;
+ }
+
+ ///
+ /// Checks if the texture sizes of the supplied texture informations match.
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// True if the size matches, false otherwise
+ public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs)
+ {
+ return SizeMatches(lhs, rhs, alignSizes: false);
+ }
+
+ ///
+ /// Checks if the texture sizes of the supplied texture informations match the given level
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// Mipmap level of this texture to compare with
+ /// True if the size matches with the level, false otherwise
+ public static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, int level)
+ {
+ return Math.Max(1, lhs.Width >> level) == rhs.Width &&
+ Math.Max(1, lhs.Height >> level) == rhs.Height &&
+ Math.Max(1, lhs.GetDepth() >> level) == rhs.GetDepth();
+ }
+
+ ///
+ /// Checks if the texture sizes of the supplied texture informations match.
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// True to align the sizes according to the texture layout for comparison
+ /// True if the sizes matches, false otherwise
+ private static bool SizeMatches(TextureInfo lhs, TextureInfo rhs, bool alignSizes)
+ {
+ if (lhs.GetLayers() != rhs.GetLayers())
+ {
+ return false;
+ }
+
+ if (alignSizes)
+ {
+ Size size0 = GetAlignedSize(lhs);
+ Size size1 = GetAlignedSize(rhs);
+
+ return size0.Width == size1.Width &&
+ size0.Height == size1.Height &&
+ size0.Depth == size1.Depth;
+ }
+ else
+ {
+ return lhs.Width == rhs.Width &&
+ lhs.Height == rhs.Height &&
+ lhs.GetDepth() == rhs.GetDepth();
+ }
+ }
+
+ ///
+ /// Gets the aligned sizes of the specified texture information.
+ /// The alignment depends on the texture layout and format bytes per pixel.
+ ///
+ /// Texture information to calculate the aligned size from
+ /// Mipmap level for texture views
+ /// The aligned texture size
+ public static Size GetAlignedSize(TextureInfo info, int level = 0)
+ {
+ int width = Math.Max(1, info.Width >> level);
+ int height = Math.Max(1, info.Height >> level);
+
+ if (info.IsLinear)
+ {
+ return SizeCalculator.GetLinearAlignedSize(
+ width,
+ height,
+ info.FormatInfo.BlockWidth,
+ info.FormatInfo.BlockHeight,
+ info.FormatInfo.BytesPerPixel);
+ }
+ else
+ {
+ int depth = Math.Max(1, info.GetDepth() >> level);
+
+ return SizeCalculator.GetBlockLinearAlignedSize(
+ width,
+ height,
+ depth,
+ info.FormatInfo.BlockWidth,
+ info.FormatInfo.BlockHeight,
+ info.FormatInfo.BytesPerPixel,
+ info.GobBlocksInY,
+ info.GobBlocksInZ,
+ info.GobBlocksInTileX);
+ }
+ }
+
+ ///
+ /// Check if it's possible to create a view with the layout of the second texture information from the first.
+ /// The layout information is composed of the Stride for linear textures, or GOB block size
+ /// for block linear textures.
+ ///
+ /// Texture information of the texture view
+ /// Texture information of the texture view to compare against
+ /// Start level of the texture view, in relation with the first texture
+ /// True if the layout is compatible, false otherwise
+ public static bool ViewLayoutCompatible(TextureInfo lhs, TextureInfo rhs, int level)
+ {
+ if (lhs.IsLinear != rhs.IsLinear)
+ {
+ return false;
+ }
+
+ // For linear textures, gob block sizes are ignored.
+ // For block linear textures, the stride is ignored.
+ if (rhs.IsLinear)
+ {
+ int width = Math.Max(1, lhs.Width >> level);
+ int stride = width * lhs.FormatInfo.BytesPerPixel;
+ stride = BitUtils.AlignUp(stride, 32);
+
+ return stride == rhs.Stride;
+ }
+ else
+ {
+ int height = Math.Max(1, lhs.Height >> level);
+ int depth = Math.Max(1, lhs.GetDepth() >> level);
+
+ (int gobBlocksInY, int gobBlocksInZ) = SizeCalculator.GetMipGobBlockSizes(
+ height,
+ depth,
+ lhs.FormatInfo.BlockHeight,
+ lhs.GobBlocksInY,
+ lhs.GobBlocksInZ);
+
+ return gobBlocksInY == rhs.GobBlocksInY &&
+ gobBlocksInZ == rhs.GobBlocksInZ;
+ }
+ }
+
+ ///
+ /// Checks if the view format of the first texture format is compatible with the format of the second.
+ /// In general, the formats are considered compatible if the bytes per pixel values are equal,
+ /// but there are more complex rules for some formats, like compressed or depth-stencil formats.
+ /// This follows the host API copy compatibility rules.
+ ///
+ /// Texture information of the texture view
+ /// Texture information of the texture view
+ /// True if the formats are compatible, false otherwise
+ public static bool ViewFormatCompatible(TextureInfo lhs, TextureInfo rhs)
+ {
+ return FormatCompatible(lhs.FormatInfo, rhs.FormatInfo);
+ }
+
+ ///
+ /// Check if the target of the first texture view information is compatible with the target of the second texture view information.
+ /// This follows the host API target compatibility rules.
+ ///
+ /// Texture information of the texture viewTexture information of the texture view
+ /// True to check for copy rather than view compatibility
+ /// True if the targets are compatible, false otherwise
+ public static bool ViewTargetCompatible(TextureInfo lhs, TextureInfo rhs, bool isCopy)
+ {
+ switch (lhs.Target)
+ {
+ case Target.Texture1D:
+ case Target.Texture1DArray:
+ return rhs.Target == Target.Texture1D ||
+ rhs.Target == Target.Texture1DArray;
+
+ case Target.Texture2D:
+ return rhs.Target == Target.Texture2D ||
+ rhs.Target == Target.Texture2DArray;
+
+ case Target.Texture2DArray:
+ case Target.Cubemap:
+ case Target.CubemapArray:
+ return rhs.Target == Target.Texture2D ||
+ rhs.Target == Target.Texture2DArray ||
+ rhs.Target == Target.Cubemap ||
+ rhs.Target == Target.CubemapArray;
+
+ case Target.Texture2DMultisample:
+ case Target.Texture2DMultisampleArray:
+ return rhs.Target == Target.Texture2DMultisample ||
+ rhs.Target == Target.Texture2DMultisampleArray;
+
+ case Target.Texture3D:
+ return rhs.Target == Target.Texture3D ||
+ (rhs.Target == Target.Texture2D && isCopy);
+ }
+
+ return false;
+ }
+
+ ///
+ /// Checks if the texture shader sampling parameters of two texture informations match.
+ ///
+ /// Texture information to compare
+ /// Texture information to compare with
+ /// True if the texture shader sampling parameters matches, false otherwise
+ public static bool SamplerParamsMatches(TextureInfo lhs, TextureInfo rhs)
+ {
+ return lhs.DepthStencilMode == rhs.DepthStencilMode &&
+ lhs.SwizzleR == rhs.SwizzleR &&
+ lhs.SwizzleG == rhs.SwizzleG &&
+ lhs.SwizzleB == rhs.SwizzleB &&
+ lhs.SwizzleA == rhs.SwizzleA;
+ }
+
+ ///
+ /// Check if the texture target and samples count (for multisampled textures) matches.
+ ///
+ /// Texture information to compare with
+ /// Texture information to compare with
+ /// True if the texture target and samples count matches, false otherwise
+ public static bool TargetAndSamplesCompatible(TextureInfo lhs, TextureInfo rhs)
+ {
+ return lhs.Target == rhs.Target &&
+ lhs.SamplesInX == rhs.SamplesInX &&
+ lhs.SamplesInY == rhs.SamplesInY;
+ }
+
///
/// Gets the texture format class, for compressed textures, or Unclassified otherwise.
///
diff --git a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
index c69f69c62..cab76da1b 100644
--- a/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
+++ b/Ryujinx.Graphics.Gpu/Image/TextureManager.cs
@@ -634,7 +634,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// deletion.
_cache.Lift(overlap);
}
- else if (!overlap.SizeMatches(info))
+ else if (!TextureCompatibility.SizeMatches(overlap.Info, info))
{
// If this is used for sampling, the size must match,
// otherwise the shader would sample garbage data.
@@ -707,7 +707,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// The size only matters (and is only really reliable) when the
// texture is used on a sampler, because otherwise the size will be
// aligned.
- if (!overlap.SizeMatches(info, firstLevel) && isSamplerTexture)
+ if (!TextureCompatibility.SizeMatches(overlap.Info, info, firstLevel) && isSamplerTexture)
{
texture.ChangeSize(info.Width, info.Height, info.DepthOrLayers);
}