From 002007c323c3c17d69068e5ff729c2675aa7f477 Mon Sep 17 00:00:00 2001 From: ParantezTech <12572227+par274@users.noreply.github.com> Date: Sun, 11 Oct 2026 06:11:55 +0300 Subject: [PATCH] [GPU] Fill metadata-shaped bounded fills on the host --- .../Gpu/Buffers/GuestBufferCache.cs | 23 +++++++++++-------- .../VulkanVideoPresenter.Rendering.cs | 12 +++++++++- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/SharpEmu.Libs/Gpu/Buffers/GuestBufferCache.cs b/src/SharpEmu.Libs/Gpu/Buffers/GuestBufferCache.cs index 1fc7ad5..1a77b94 100644 --- a/src/SharpEmu.Libs/Gpu/Buffers/GuestBufferCache.cs +++ b/src/SharpEmu.Libs/Gpu/Buffers/GuestBufferCache.cs @@ -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."); } diff --git a/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Rendering.cs b/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Rendering.cs index 61d3317..e602ca2 100644 --- a/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Rendering.cs +++ b/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Rendering.cs @@ -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); }