diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index d0216dc65..27c66afcf 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -182,7 +182,11 @@ namespace Ryujinx.Graphics.Gpu.Image { foreach (TextureIncompatibleOverlap overlap in _incompatibleOverlaps) { - if (overlap.Compatibility <= TextureViewCompatibility.LayoutIncompatible) + // LayoutIncompatible and better may still use a regular texture copy dependency. + // Fully Incompatible pairs are not copy compatible in general, but may still qualify for an + // exact raw byte copy dependency (checked internally by CreateCopyDependency) when they map + // to exactly the same guest memory, such as differently typed/sized aliases of the same data. + if (overlap.Compatibility <= TextureViewCompatibility.Incompatible) { CreateCopyDependency(overlap.Group, false, overlap.Compatibility); } @@ -226,7 +230,6 @@ namespace Ryujinx.Graphics.Gpu.Image } } - /// /// Flushes incompatible overlaps if the storage format requires it, and they have been modified. /// This allows unsupported host formats to accept data written to format aliased textures. @@ -659,7 +662,7 @@ namespace Ryujinx.Graphics.Gpu.Image bool canImport = Storage.Info.IsLinear && Storage.Info.Stride >= Storage.Info.Width * Storage.Info.FormatInfo.BytesPerPixel; - IntPtr hostPointer = canImport ? _physicalMemory.GetHostPointer(Storage.Range) : 0; + nint hostPointer = canImport ? _physicalMemory.GetHostPointer(Storage.Range) : 0; if (hostPointer != 0 && _context.Renderer.PrepareHostMapping(hostPointer, Storage.Size)) { @@ -1049,7 +1052,7 @@ namespace Ryujinx.Graphics.Gpu.Image int endOffset = _allOffsets[viewEnd] + _sliceSizes[lastLevel]; int size = endOffset - offset; - List result = new(); + List result = []; for (int i = 0; i < TextureRange.Count; i++) { @@ -1163,7 +1166,6 @@ namespace Ryujinx.Graphics.Gpu.Image SignalAllDirty(); } - /// /// Removes a view from the group, removing it from all overlap lists. /// @@ -1385,7 +1387,7 @@ namespace Ryujinx.Graphics.Gpu.Image if (_is3D) { - List handlesList = new(); + List handlesList = []; for (int i = 0; i < levelHandles; i++) { @@ -1468,8 +1470,8 @@ namespace Ryujinx.Graphics.Gpu.Image // Get the location of each texture within its storage, so we can find the handles to apply the dependency to. // This can consist of multiple disjoint regions, for example if this is a mip slice of an array texture. - List<(int BaseHandle, int RegionCount)> targetRange = new(); - List<(int BaseHandle, int RegionCount)> otherRange = new(); + List<(int BaseHandle, int RegionCount)> targetRange = []; + List<(int BaseHandle, int RegionCount)> otherRange = []; EvaluateRelevantHandles(firstLayer, firstLevel, other.Info.GetSlices(), other.Info.Levels, (baseHandle, regionCount, _, _) => { @@ -1601,7 +1603,15 @@ namespace Ryujinx.Graphics.Gpu.Image TextureInfo info = Storage.Info; TextureInfo otherInfo = other.Storage.Info; - bool textureCopy = TextureCompatibility.ViewLayoutCompatible(info, otherInfo, level, otherLevel) && + // ViewLayoutCompatible/CopySizeMatches only reason about textures with some genuine + // format relationship (LayoutIncompatible or better) - they are not aware of, and must + // never be used to justify, a plain texture-to-texture copy (which some backends + // implement via a reinterpreting view) between fully Incompatible aliases such as a + // depth format and an unrelated color format. For Incompatible pairs, only the strict + // raw byte copy dependency below (which explicitly excludes depth/stencil formats) may + // be used. + bool textureCopy = compatibility != TextureViewCompatibility.Incompatible && + TextureCompatibility.ViewLayoutCompatible(info, otherInfo, level, otherLevel) && TextureCompatibility.CopySizeMatches(info, otherInfo, level, otherLevel); if (textureCopy || rawCopy) @@ -1659,9 +1669,12 @@ namespace Ryujinx.Graphics.Gpu.Image { if (!_incompatibleOverlaps.Any(overlap => overlap.Group == other.Group)) { - if (copy && other.Compatibility <= TextureViewCompatibility.LayoutIncompatible) + if (copy && other.Compatibility <= TextureViewCompatibility.Incompatible) { // Any of the group's views may share compatibility, even if the parents do not fully. + // Fully Incompatible groups are also let through here, since CreateCopyDependency will + // fall back to an exact raw byte copy dependency for them when the strict requirements + // for one are met (see CanCreateRawCopyDependency). CreateCopyDependency(other.Group, false, other.Compatibility); } @@ -1803,4 +1816,3 @@ namespace Ryujinx.Graphics.Gpu.Image } } } - diff --git a/src/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs b/src/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs index 7aef9775c..95eaf86e2 100644 --- a/src/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs +++ b/src/Ryujinx.Graphics.Gpu/Image/TextureGroupHandle.cs @@ -717,6 +717,7 @@ namespace Ryujinx.Graphics.Gpu.Image } DeferredCopy = old.DeferredCopy; + DeferredCopyRaw = old.DeferredCopyRaw; } }