diff --git a/src/renderer/src/lib/pane-manager/pane-rendering-diagnostics.ts b/src/renderer/src/lib/pane-manager/pane-rendering-diagnostics.ts index be60429ebbb..4c35b80078d 100644 --- a/src/renderer/src/lib/pane-manager/pane-rendering-diagnostics.ts +++ b/src/renderer/src/lib/pane-manager/pane-rendering-diagnostics.ts @@ -1,5 +1,6 @@ import type { ManagedPaneInternal, PaneRenderingDiagnostics } from './pane-manager-types' import { getTerminalWebglAutoDecision } from './terminal-webgl-auto-policy' +import { prunePaneWebglContextLosses } from './pane-webgl-context-loss-policy' export function collectPaneRenderingDiagnostics( panes: Map @@ -10,7 +11,7 @@ export function collectPaneRenderingDiagnostics( gpuRenderingEnabled: pane.gpuRenderingEnabled, webglAttachmentDeferred: pane.webglAttachmentDeferred, webglDisabledAfterContextLoss: pane.webglDisabledAfterContextLoss, - webglContextLossesInWindow: pane.webglContextLossTimestamps?.length ?? 0, + webglContextLossesInWindow: prunePaneWebglContextLosses(pane), webglAttachFailedSinceRecovery: pane.webglAttachFailedSinceRecovery === true, hasComplexScriptOutput: pane.hasComplexScriptOutput, terminalWebglAutoDecision: getTerminalWebglAutoDecision(), diff --git a/src/renderer/src/lib/pane-manager/pane-reveal-repaint.test.ts b/src/renderer/src/lib/pane-manager/pane-reveal-repaint.test.ts index 6c1c4f3191e..50c5784dd30 100644 --- a/src/renderer/src/lib/pane-manager/pane-reveal-repaint.test.ts +++ b/src/renderer/src/lib/pane-manager/pane-reveal-repaint.test.ts @@ -239,6 +239,7 @@ describe('schedulePaneRevealRepaint', () => { it('reattaches a pane that lost WebGL while hidden when its tab is revealed', () => { const pane = createPane() pane.webglDisabledAfterContextLoss = true + pane.webglContextLossTimestamps = [Date.now()] schedulePaneRevealPresent(() => [pane]) flushFrame() @@ -246,6 +247,8 @@ describe('schedulePaneRevealRepaint', () => { expect(pane.webglDisabledAfterContextLoss).toBe(false) expect(pane.webglAddon).not.toBeNull() + expect(pane.terminal.refresh).toHaveBeenCalledTimes(2) + expect(pane.terminal.refresh).toHaveBeenNthCalledWith(2, 0, 23) }) }) }) diff --git a/src/renderer/src/lib/pane-manager/pane-webgl-context-loss-policy.ts b/src/renderer/src/lib/pane-manager/pane-webgl-context-loss-policy.ts index 66963851a8e..97a4660acbc 100644 --- a/src/renderer/src/lib/pane-manager/pane-webgl-context-loss-policy.ts +++ b/src/renderer/src/lib/pane-manager/pane-webgl-context-loss-policy.ts @@ -9,6 +9,12 @@ function recentContextLosses(pane: ManagedPaneInternal, now: number): number[] { return (pane.webglContextLossTimestamps ?? []).filter((timestamp) => timestamp > cutoff) } +export function prunePaneWebglContextLosses(pane: ManagedPaneInternal, now = Date.now()): number { + const losses = recentContextLosses(pane, now) + pane.webglContextLossTimestamps = losses + return losses.length +} + export function recordPaneWebglContextLoss(pane: ManagedPaneInternal, now = Date.now()): number { const losses = recentContextLosses(pane, now) losses.push(now) @@ -20,9 +26,7 @@ export function canRetryPaneWebglAfterContextLoss( pane: ManagedPaneInternal, now = Date.now() ): boolean { - const losses = recentContextLosses(pane, now) - pane.webglContextLossTimestamps = losses - return losses.length < WEBGL_CONTEXT_LOSS_RETRY_LIMIT + return prunePaneWebglContextLosses(pane, now) < WEBGL_CONTEXT_LOSS_RETRY_LIMIT } export function resetPaneWebglContextLosses(pane: ManagedPaneInternal): void { diff --git a/src/renderer/src/lib/pane-manager/pane-webgl-context-recovery.test.ts b/src/renderer/src/lib/pane-manager/pane-webgl-context-recovery.test.ts index 09016e67429..117e5cbc940 100644 --- a/src/renderer/src/lib/pane-manager/pane-webgl-context-recovery.test.ts +++ b/src/renderer/src/lib/pane-manager/pane-webgl-context-recovery.test.ts @@ -2,6 +2,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { setTerminalWebglDiagnosticRecorder } from '../../../../shared/terminal-webgl-diagnostics' import type { ManagedPaneInternal } from './pane-manager-types' import { resumePaneRendering, suspendPaneRendering } from './pane-rendering-control' +import { collectPaneRenderingDiagnostics } from './pane-rendering-diagnostics' import { attachWebgl, resetTerminalWebglSuggestion } from './pane-webgl-renderer' import { rebuildAttachedWebgl } from './pane-webgl-reattach' @@ -216,4 +217,16 @@ describe('terminal WebGL context recovery', () => { } ]) }) + + it('reports only recent context losses in rendering diagnostics', () => { + const now = 1_700_000_000_000 + vi.spyOn(Date, 'now').mockReturnValue(now) + const pane = createPane() + pane.webglContextLossTimestamps = [now - 60_001, now - 1_000] + + const [diagnostics] = collectPaneRenderingDiagnostics(new Map([[pane.id, pane]])) + + expect(diagnostics.webglContextLossesInWindow).toBe(1) + expect(pane.webglContextLossTimestamps).toEqual([now - 1_000]) + }) })