Improve linear texture compatibility rules (#2099)

* Improve linear texture compatibility rules

Fixes an issue where small or width-aligned (rather than byte aligned) textures would fail to create a view of existing data. Creates a copy dependency as size change may be risky.

* Minor cleanup

* Remove Size Change for Copy Depenedencies

The copy to the target (potentially different sized) texture can properly deal with cropping by itself.

* Move StrideAlignment and GobAlignment into Constants
This commit is contained in:
riperiperi 2021-03-19 01:17:38 +00:00 committed by GitHub
parent 39899c0407
commit 9b7335a63b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 15 deletions

View file

@ -69,5 +69,15 @@ namespace Ryujinx.Graphics.Gpu
/// Maximum size of gl_ClipDistance array in shaders. /// Maximum size of gl_ClipDistance array in shaders.
/// </summary> /// </summary>
public const int TotalClipDistances = 8; public const int TotalClipDistances = 8;
/// <summary>
/// Byte alignment for texture stride.
/// </summary>
public const int StrideAlignment = 32;
/// <summary>
/// Byte alignment for block linear textures
/// </summary>
public const int GobAlignment = 64;
} }
} }

View file

@ -8,9 +8,6 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
partial class Methods partial class Methods
{ {
private const int StrideAlignment = 32;
private const int GobAlignment = 64;
enum CopyFlags enum CopyFlags
{ {
SrcLinear = 1 << 7, SrcLinear = 1 << 7,
@ -32,14 +29,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
{ {
if (linear) if (linear)
{ {
int alignWidth = StrideAlignment / bpp; int alignWidth = Constants.StrideAlignment / bpp;
return tex.RegionX == 0 && return tex.RegionX == 0 &&
tex.RegionY == 0 && tex.RegionY == 0 &&
stride / bpp == BitUtils.AlignUp(cbp.XCount, alignWidth); stride / bpp == BitUtils.AlignUp(cbp.XCount, alignWidth);
} }
else else
{ {
int alignWidth = GobAlignment / bpp; int alignWidth = Constants.GobAlignment / bpp;
return tex.RegionX == 0 && return tex.RegionX == 0 &&
tex.RegionY == 0 && tex.RegionY == 0 &&
tex.Width == BitUtils.AlignUp(cbp.XCount, alignWidth) && tex.Width == BitUtils.AlignUp(cbp.XCount, alignWidth) &&

View file

@ -231,8 +231,21 @@ namespace Ryujinx.Graphics.Gpu.Image
result = TextureViewCompatibility.CopyOnly; result = TextureViewCompatibility.CopyOnly;
} }
return (size.Width == otherSize.Width && if (size.Width == otherSize.Width && size.Height == otherSize.Height)
size.Height == otherSize.Height) ? result : TextureViewCompatibility.Incompatible; {
return result;
}
else if (lhs.IsLinear && rhs.IsLinear)
{
// Copy between linear textures with matching stride.
int stride = BitUtils.AlignUp(Math.Max(1, lhs.Stride >> level), Constants.StrideAlignment);
return stride == rhs.Stride ? TextureViewCompatibility.CopyOnly : TextureViewCompatibility.Incompatible;
}
else
{
return TextureViewCompatibility.Incompatible;
}
} }
/// <summary> /// <summary>
@ -372,8 +385,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// For block linear textures, the stride is ignored. // For block linear textures, the stride is ignored.
if (rhs.IsLinear) if (rhs.IsLinear)
{ {
int width = Math.Max(1, lhs.Width >> level); int stride = Math.Max(1, lhs.Stride >> level);
int stride = width * lhs.FormatInfo.BytesPerPixel;
stride = BitUtils.AlignUp(stride, 32); stride = BitUtils.AlignUp(stride, 32);
return stride == rhs.Stride; return stride == rhs.Stride;

View file

@ -16,9 +16,6 @@ namespace Ryujinx.Graphics.Gpu.Image
/// </summary> /// </summary>
class TextureGroup : IDisposable class TextureGroup : IDisposable
{ {
private const int StrideAlignment = 32;
private const int GobAlignment = 64;
private delegate void HandlesCallbackDelegate(int baseHandle, int regionCount, bool split = false); private delegate void HandlesCallbackDelegate(int baseHandle, int regionCount, bool split = false);
/// <summary> /// <summary>

View file

@ -429,7 +429,7 @@ namespace Ryujinx.Graphics.Gpu.Image
// Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas) // Discount square textures that aren't depth-stencil like. (excludes game textures, cubemap faces, most 3D texture LUT, texture atlas)
// Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height. // Detect if the texture is possibly square. Widths may be aligned, so to remove the uncertainty we align both the width and height.
int widthAlignment = (info.IsLinear ? 32 : 64) / info.FormatInfo.BytesPerPixel; int widthAlignment = (info.IsLinear ? Constants.StrideAlignment : Constants.GobAlignment) / info.FormatInfo.BytesPerPixel;
bool possiblySquare = BitUtils.AlignUp(info.Width, widthAlignment) == BitUtils.AlignUp(info.Height, widthAlignment); bool possiblySquare = BitUtils.AlignUp(info.Width, widthAlignment) == BitUtils.AlignUp(info.Height, widthAlignment);
@ -977,8 +977,6 @@ namespace Ryujinx.Graphics.Gpu.Image
{ {
// Copy only compatibility, or target texture is already a view. // Copy only compatibility, or target texture is already a view.
ChangeSizeIfNeeded(overlapInfo, overlap, false, sizeHint); // Force a size match for copy
overlap.SynchronizeMemory(); overlap.SynchronizeMemory();
texture.CreateCopyDependency(overlap, oInfo.FirstLayer, oInfo.FirstLevel, false); texture.CreateCopyDependency(overlap, oInfo.FirstLayer, oInfo.FirstLevel, false);
} }