From 792953c90bc5d37370110745ca65714fff34aa4b Mon Sep 17 00:00:00 2001 From: ParantezTech <12572227+par274@users.noreply.github.com> Date: Fri, 2 Oct 2026 18:48:02 +0300 Subject: [PATCH] [Gpu] Track the extent of DCC metadata and answer overlap queries A color target records the size of its DCC metadata, and the image cache can tell whether a guest range overlaps registered DCC metadata. --- src/SharpEmu.Libs/Gpu/Buffers/IGuestImageCache.cs | 2 ++ .../Gpu/Images/GuestImageCache.Collection.cs | 6 ++++++ .../Gpu/Images/GuestImageCache.Metadata.cs | 15 +++++++++++++++ src/SharpEmu.Libs/Gpu/Images/GuestImageCache.cs | 5 ++++- src/SharpEmu.Libs/Gpu/Images/SurfaceMetadata.cs | 1 + 5 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/SharpEmu.Libs/Gpu/Buffers/IGuestImageCache.cs b/src/SharpEmu.Libs/Gpu/Buffers/IGuestImageCache.cs index 79703c9..e6b247b 100644 --- a/src/SharpEmu.Libs/Gpu/Buffers/IGuestImageCache.cs +++ b/src/SharpEmu.Libs/Gpu/Buffers/IGuestImageCache.cs @@ -13,6 +13,8 @@ public interface IGuestImageCache bool ClearMetadata(ulong address); + bool OverlapsDccMetadata(ulong address, ulong size); + void InvalidateMemory(ulong address, ulong size); void InvalidateMemoryFromGpu(ulong address, ulong size); diff --git a/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Collection.cs b/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Collection.cs index 9b8e456..89c3250 100644 --- a/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Collection.cs +++ b/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Collection.cs @@ -257,6 +257,12 @@ public sealed partial class GuestImageCache metadata.ClearMask = 0; } + internal void RegisterDccMetadataForTest(ulong address, ulong size) + { + using var held = _lock.Hold(); + _surfaceMetadata[address] = new SurfaceMetadata { Kind = SurfaceMetadataKind.Dcc, Size = size }; + } + internal RegionLockScope HoldLockForTest() => new(_lock); internal readonly struct RegionLockScope : IDisposable diff --git a/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Metadata.cs b/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Metadata.cs index 8d97137..a0424cb 100644 --- a/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Metadata.cs +++ b/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.Metadata.cs @@ -29,6 +29,21 @@ public sealed partial class GuestImageCache public bool IsMetadataCleared(ulong address, uint slice) => IsMetadataCleared(address, slice, out _); + public bool OverlapsDccMetadata(ulong address, ulong size) + { + using var held = _lock.Hold(); + foreach (var (start, metadata) in _surfaceMetadata) + { + if (metadata.Kind == SurfaceMetadataKind.Dcc && metadata.Size != 0 && + address < start + metadata.Size && start < address + size) + { + return true; + } + } + + return false; + } + // A broad clear applies to CMask, FMask and HTile; DCC needs a validated fill value. public bool ClearMetadata(ulong address) { diff --git a/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.cs b/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.cs index 1f19615..2391fc6 100644 --- a/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.cs +++ b/src/SharpEmu.Libs/Gpu/Images/GuestImageCache.cs @@ -321,7 +321,8 @@ public sealed unsafe partial class GuestImageCache : IGuestImageCache, IGuestIma var address = request.Description.Metadata.Range.Address; if (!_surfaceMetadata.TryGetValue(address, out var metadata)) { - _surfaceMetadata.Add(address, new SurfaceMetadata { Kind = SurfaceMetadataKind.Dcc }); + metadata = new SurfaceMetadata { Kind = SurfaceMetadataKind.Dcc }; + _surfaceMetadata.Add(address, metadata); } else if (metadata.Kind == SurfaceMetadataKind.PendingDcc) { @@ -331,6 +332,8 @@ public sealed unsafe partial class GuestImageCache : IGuestImageCache, IGuestIma { throw SubmissionScheduler.Fatal($"A color target reuses metadata that is not DCC: address=0x{address:X16} kind={metadata.Kind}."); } + + metadata.Size = Math.Max(metadata.Size, request.Description.DccSliceSize * request.Description.TransferLayers); } TakeGpuOwnership(image); diff --git a/src/SharpEmu.Libs/Gpu/Images/SurfaceMetadata.cs b/src/SharpEmu.Libs/Gpu/Images/SurfaceMetadata.cs index bb57433..f547685 100644 --- a/src/SharpEmu.Libs/Gpu/Images/SurfaceMetadata.cs +++ b/src/SharpEmu.Libs/Gpu/Images/SurfaceMetadata.cs @@ -20,4 +20,5 @@ public sealed class SurfaceMetadata public uint ClearMask; public uint FillValue = 0xffffffff; public ulong FillSize; + public ulong Size; }