[GPU] Fill metadata-shaped bounded fills on the host

This commit is contained in:
ParantezTech 2026-10-11 06:11:55 +03:00
parent b26c59460d
commit 002007c323
2 changed files with 24 additions and 11 deletions

View File

@ -361,7 +361,10 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
}
}
public void FillBuffer(ulong guestAddress, ulong size, uint value, bool isGds)
public void FillBuffer(ulong guestAddress, ulong size, uint value, bool isGds) =>
FillBuffer(guestAddress, size, value, isGds, publishFill: false);
private void FillBuffer(ulong guestAddress, ulong size, uint value, bool isGds, bool publishFill)
{
if ((guestAddress & 3) != 0 || size == 0 || (size & 3) != 0 || size > ulong.MaxValue - guestAddress)
{
@ -410,14 +413,14 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
images.InvalidateMemoryFromGpu(guestAddress, size);
var bufferIdentifier = FindBuffer(guestAddress, size);
var (destination, destinationOffset) = ObtainBuffer(guestAddress, size, true, true, bufferIdentifier);
destination.Fill(destinationOffset, size, value);
if (images.OverlapsDccMetadata(guestAddress, size) && TryWriteFillToBacking(guestAddress, size, value))
if (Diagnostics.DccWriterTrace.Enabled)
{
Diagnostics.DccWriterTrace.CurrentKind = "fill";
}
var (destination, destinationOffset) = ObtainBuffer(guestAddress, size, true, true, bufferIdentifier);
destination.Fill(destinationOffset, size, value);
if ((publishFill || images.OverlapsDccMetadata(guestAddress, size)) && TryWriteFillToBacking(guestAddress, size, value))
{
_gpuModifiedRanges.Remove(guestAddress, size);
Interlocked.Increment(ref _gpuModifiedVersion);
@ -466,7 +469,7 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
if (guestAddress == 0 || (guestAddress & 3) != 0 || size == 0 || (size & 3) != 0 || size > ulong.MaxValue - guestAddress ||
HasGpuDirtyBytes(guestAddress, size))
{
FillBuffer(guestAddress, size, value, false);
FillBuffer(guestAddress, size, value, false, publishFill: true);
return;
}
@ -476,7 +479,7 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
var region = images.QueryRegion(guestAddress, size);
if (region.GpuImageBytes)
{
FillBuffer(guestAddress, size, value, false);
FillBuffer(guestAddress, size, value, false, publishFill: true);
return;
}
@ -489,7 +492,7 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
destination.Fill(destinationOffset, size, value);
if (!TryWriteFillToBacking(guestAddress, size, value))
{
FillBuffer(guestAddress, size, value, false);
FillBuffer(guestAddress, size, value, false, publishFill: true);
}
}
@ -645,14 +648,14 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
var srcId = srcMemory ? FindBuffer(srcVaddr, size) : default;
var dstId = dstMemory ? FindBuffer(dstVaddr, size) : default;
var (src, srcOffset) = srcMemory ? ObtainBuffer(srcVaddr, size, false, true, srcId) : (_gds, srcVaddr);
var (dst, dstOffset) = dstMemory ? ObtainBuffer(dstVaddr, size, true, true, dstId) : (_gds, dstVaddr);
if (ReferenceEquals(src, dst) && srcOffset < dstOffset + size && dstOffset < srcOffset + size)
{
if (Diagnostics.DccWriterTrace.Enabled)
{
Diagnostics.DccWriterTrace.CurrentKind = $"copy_from_0x{srcVaddr:X}";
}
var (dst, dstOffset) = dstMemory ? ObtainBuffer(dstVaddr, size, true, true, dstId) : (_gds, dstVaddr);
if (ReferenceEquals(src, dst) && srcOffset < dstOffset + size && dstOffset < srcOffset + size)
{
throw SubmissionScheduler.Fatal("The resolved Vulkan copy ranges overlap.");
}

View File

@ -1299,7 +1299,7 @@ internal static unsafe partial class VulkanVideoPresenter
public bool TryFillDccMetadata(ulong address, ulong size, uint fillValue)
{
if (!_imageCache.OverlapsDccMetadata(address, size))
if (!_imageCache.OverlapsDccMetadata(address, size) && !IsMetadataShapedFill(address, size, fillValue))
{
return false;
}
@ -1308,6 +1308,16 @@ internal static unsafe partial class VulkanVideoPresenter
return true;
}
private bool IsMetadataShapedFill(ulong address, ulong size, uint fillValue)
{
const ulong metadataBlockSize = 0x1000;
const ulong maxMetadataFill = 0x100000;
return address != 0 && size != 0 && size <= maxMetadataFill &&
address % metadataBlockSize == 0 && size % metadataBlockSize == 0 &&
fillValue == (fillValue & 0xFF) * 0x01010101u &&
!_imageCache.QueryRegion(address, size).ImageBytes;
}
public bool TryCopyWordsOnHost(ulong destination, ulong source, ulong sourceWords, ulong words) =>
_bufferCache.TryCopyWordsOnHost(destination, source, sourceWords, words);
}