diff --git a/src/SharpEmu.Libs/Agc/AgcExports.cs b/src/SharpEmu.Libs/Agc/AgcExports.cs index f535c649..1b58a13a 100644 --- a/src/SharpEmu.Libs/Agc/AgcExports.cs +++ b/src/SharpEmu.Libs/Agc/AgcExports.cs @@ -11307,7 +11307,9 @@ public static partial class AgcExports } } - if (evaluationHandledByCpu) + // Rejected/CPU-handled dispatches never hand evaluation's pooled buffers to a + // consumer that would return them; reclaim here to keep GuestDataPool.Shared bounded. + if (evaluationHandledByCpu || !gpuDispatch) { ReturnPooledEvaluationArrays(evaluation); } diff --git a/src/SharpEmu.Libs/Gpu/GuestDataPool.cs b/src/SharpEmu.Libs/Gpu/GuestDataPool.cs index a9d395dc..af0740f7 100644 --- a/src/SharpEmu.Libs/Gpu/GuestDataPool.cs +++ b/src/SharpEmu.Libs/Gpu/GuestDataPool.cs @@ -23,6 +23,10 @@ internal static class GuestDataPool public static void Trim() => ((BoundedByteArrayPool)Shared).Trim(); + /// Outstanding lease count and idle cached bytes, for leak diagnostics. + public static (int LeaseCount, ulong CachedBytes) DiagnosticStats() => + ((BoundedByteArrayPool)Shared).Stats(); + private sealed class BoundedByteArrayPool : ArrayPool { private readonly object _gate = new(); @@ -119,6 +123,14 @@ internal static class GuestDataPool } } + public (int LeaseCount, ulong CachedBytes) Stats() + { + lock (_gate) + { + return (_leases.Count, _cachedBytes); + } + } + private int GetAllocationLength(int minimumLength) { if (minimumLength <= 16) diff --git a/src/SharpEmu.Libs/VideoOut/VideoOutExports.cs b/src/SharpEmu.Libs/VideoOut/VideoOutExports.cs index c5895ced..ca2689c9 100644 --- a/src/SharpEmu.Libs/VideoOut/VideoOutExports.cs +++ b/src/SharpEmu.Libs/VideoOut/VideoOutExports.cs @@ -1300,10 +1300,12 @@ public static class VideoOutExports var submitted = Interlocked.Exchange(ref _submittedFrameCount, 0); var presentedCount = Interlocked.Exchange(ref _presentedFrameCount, 0); var (draws, drawMs, pipelines, spirvCompiles) = GuestGpu.Current.ReadAndResetPerfCounters(); + var (poolLeases, poolCachedBytes) = SharpEmu.Libs.Gpu.GuestDataPool.DiagnosticStats(); Console.Error.WriteLine( $"[LOADER][PERF] videoout submitted_fps={submitted / elapsedSeconds:F1} " + $"presented_fps={presentedCount / elapsedSeconds:F1} " + - $"draws={draws} draw_ms={drawMs:F0} pipelines={pipelines} spirv={spirvCompiles}"); + $"draws={draws} draw_ms={drawMs:F0} pipelines={pipelines} spirv={spirvCompiles} " + + $"pool_leases={poolLeases} pool_cached_mb={poolCachedBytes / 1024.0 / 1024.0:F1}"); } private static readonly bool _flipPacingDisabled = string.Equals(