[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.
This commit is contained in:
parent
7085532257
commit
792953c90b
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -20,4 +20,5 @@ public sealed class SurfaceMetadata
|
|||
public uint ClearMask;
|
||||
public uint FillValue = 0xffffffff;
|
||||
public ulong FillSize;
|
||||
public ulong Size;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue