fix #424: a zero-area viewport skips the frame before any GPU work (alt-tab out of exclusive fullscreen crashed the pack-on client)
GLFW auto-iconifies an exclusive-fullscreen window on focus loss; for one frame the window size reads 0x0 while the swapchain is still created, so GameWindow.OnRender's PrepareFrame guard let a zero-area RenderFrameInput through. The retail path tolerated it silently; the render-pack controller correctly rejects a zero activation extent, which surfaced the latent frame as an unhandled ArgumentOutOfRangeException during the owner's VM6/VM3 gate. RenderFrameOrchestrator.Render now returns RenderFrameOutcome.ZeroArea before BeginFrame when either dimension is <= 0 (no GPU frame, phase, measurement, diagnostics or recovery runs) and GameWindow skips NoteFrameClosed for it. Test: ZeroAreaViewport_SkipsTheFrameBeforeAnyGpuWork. Verify: App hermetic lane 6,059/0 (Release). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
b017391b98
commit
38def07edb
4 changed files with 84 additions and 3 deletions
|
|
@ -59,6 +59,31 @@ public sealed class RenderFrameOrchestratorTests
|
|||
Assert.Equal(outcome, phases.ObservedOutcome);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, 1080)]
|
||||
[InlineData(1920, 0)]
|
||||
[InlineData(0, 0)]
|
||||
[InlineData(-1, 1080)]
|
||||
public void ZeroAreaViewport_SkipsTheFrameBeforeAnyGpuWork(int width, int height)
|
||||
{
|
||||
// Campaign VM VM7 owner gate (2026-08-23): alt-tabbing out of
|
||||
// exclusive fullscreen auto-iconifies the window; for one frame the
|
||||
// size reads 0x0 while the swapchain is still current, and the
|
||||
// zero-area frame crashed the client in
|
||||
// RenderPackActivationExtent.Validate. The rule lives here, before
|
||||
// BeginFrame, so no phase, measurement, diagnostics or recovery can
|
||||
// observe a zero extent, and the outcome says so for the host.
|
||||
var calls = new List<string>();
|
||||
var phases = new RecordingPhases(calls);
|
||||
|
||||
RenderFrameOutcome outcome = Create(phases).Render(
|
||||
Input with { ViewportWidth = width, ViewportHeight = height });
|
||||
|
||||
Assert.True(outcome.SkippedZeroArea);
|
||||
Assert.Empty(calls);
|
||||
Assert.Empty(phases.ObservedInputs);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BeginFailure_DoesNotAttemptAnyPhaseOrClose()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue