[GPU] Fill metadata-shaped bounded fills on the host
This commit is contained in:
parent
b26c59460d
commit
002007c323
|
|
@ -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.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue