perf(capture): overlap GPU readbacks with monotonic publish gate (slice 17)
Measure take ty-1824 on the slice-16 build: the downscale fix worked (conv ~47ms, ring allocs 0) but desktop band was still 88% frozen at 6.8 updates/s. Telemetry isolated the real wall — CreateCopyFromSurfaceAsync readback ~45ms of each conversion, serialized one-in-flight => ~17/s capture cap. Docs fact: pool-sized surfaces CLIP, not scale (Microsoft Learn), so readback stays native; the lever is concurrency. - MaxConcurrentConversions=3 with pool 2->5 buffers (in-flight frames fit) - new MonotonicGate (Interlocked compare-exchange): stale OLDER completions are dropped, never overwrite a newer LatestFrame (mirror of 1742 tear) - FrameRingBuffer.Rent/ConsumeAllocations now lock; downscale row scratch is per-conversion locals - Good Dog test PublishGate_TryPublish_OnlyStrictlyNewerWins; 296/296 green, 0 warnings; docs cited Microsoft screen-capture page + libyuv fixed-point. Local only, no push.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace ytLive.Services;
|
||||
|
||||
/// <summary>
|
||||
/// An atomic "publish only if strictly newer" gate for the capture's latest-wins
|
||||
/// hand-out. Screen capture conversions may now overlap (slice 17), so two
|
||||
/// conversions can finish briefly out of order; without a monotonic gate the slower
|
||||
/// (older) completion would overwrite the faster (newer) one's LatestFrame and the
|
||||
/// compositor would render STALE content — a time hole in the other direction.
|
||||
/// Sequence must be a strictly increasing per-source counter
|
||||
/// (<c>Interlocked.Increment</c> in <c>ScreenCaptureFrameSource</c>).
|
||||
/// </summary>
|
||||
internal sealed class MonotonicGate
|
||||
{
|
||||
private long _last;
|
||||
|
||||
/// <summary>Returns true iff <paramref name="seq"/> is strictly newer than every
|
||||
/// seq accepted so far (and records it).</summary>
|
||||
public bool TryPublish(long seq)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var current = Interlocked.Read(ref _last);
|
||||
if (seq <= current) return false;
|
||||
if (Interlocked.CompareExchange(ref _last, seq, current) == current) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user