Skip to content

fix(core): a graded clip's canvas no longer comes out blank on a real GPU - #6615

Merged
miguel-heygen merged 3 commits into
mainfrom
dscribe/grading-canvas-blank
Oct 28, 2026
Merged

miguel-heygen merged 3 commits into
mainfrom
dscribe/grading-canvas-blank

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

What changed

A graded video could show as a flat background instead of its footage in the preview: the grade drew a blank canvas and hid the source video under it. Two causes, both in the runtime's colour grading:

  1. A clip shown far past the screen asked for a canvas the GPU cannot draw. The canvas was sized from the clip's on-screen box, so a clip zoomed to about three times the frame asked for 6582 x 11520 pixels. The GPU silently clamped the shared WebGL drawing buffer (to 4353 x 7620 here), and every later copy out of it, which reads from the bottom of the buffer, landed outside what had been drawn. The canvas is now capped at 2^24 pixels and 8192 on a side, in the clip's own shape, and a draw whose drawing buffer is smaller than its canvas gives the clip back to its source video (shown again, canvas hidden) and throws instead of copying, including for a clip that had already drawn.
  2. The first draw of a video could sample nothing. loadeddata and seeked arrive before the GPU can upload the frame, so that draw produced a blank canvas, and nothing redrew until the next seek. A video now also redraws once its frame is presented (requestVideoFrameCallback, a single draw when paused).

What I measured

Real GPU: Chromium (Electron) on an Apple-silicon Mac, a 9 s montage with several graded clips, the preview page served by hyperframes preview with the runtime swapped for each build. After the page loads, the playhead goes to 0.4 s, 0, 0.4 s, 0, and each shown clip's grading canvas is read back.

step before after
load blank drawn
0.4 s drawn drawn
back to 0 blank drawn
0.4 s again one clip blank all drawn
back to 0 blank drawn

Three runs after the change gave the same readings. With the change, the frame at 0 matches hyperframes snapshot, which shows ungraded footage there.

What I did NOT exercise

  • CI has no GPU. The tests below run against the mocked WebGL context, so they pin the size cap, the refusal to hide the source over a clamped buffer, and the draw on a presented frame, not the clamp itself.
  • Software GL (SwiftShader) never showed the problem, so a green run there says nothing about it.
  • Only a Mac GPU; other GPUs clamp at other sizes, which the 2^24 cap sits under but I did not measure.

fails without the fix: caps a clip shown far larger than the screen to what a GPU can draw, keeping its shape, leaves the source showing when the drawing buffer cannot hold the canvas, gives a drawn clip back to its source when a later draw outgrows the drawing buffer, and draws a paused video again once its frame is presented, after the first draw sampled nothing in packages/core/src/runtime/colorGrading.test.ts; all four fail on main and pass here (113 of 113 in the file, three runs in a row).

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES · 1 blocker · 0 important · 0 nits · reviewed 217ce51b, plus the comment-only a6e04242 that fixes Comments

The drawing-buffer guard keeps the source showing only when nothing has drawn yet. Once a clip has drawn, it hits the same blank canvas the PR fixes. ↓ inline

Scope and checks
  • I ran colorGrading.test.ts locally at the head: 112/112 pass. With main's colorGrading.ts swapped in, the 3 tests the PR names on its fails without the fix: line fail, as claimed.
  • The cap math and the requestVideoFrameCallback scheduling look right. scheduleVideoDraw skips the call if a draw is already pending, and a paused video draws once and stops.
  • CI at 217ce51b was cancelled when a6e04242 was pushed. Comments was red there (+5 comment lines), and the new head removes those lines.

@github-actions

Copy link
Copy Markdown
Contributor

Edit accuracy: accurate 271 (base branch 271), smooth 166 of those

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

Quarantined, measured but not gated (0)

@heygengenesis heygengenesis Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE · 1 resolved, 0 open, 0 new · a6e0424 → 6573730

@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 28, 2026
Merged via the queue into main with commit 9eaf9ef Oct 28, 2026
84 of 85 checks passed
@miguel-heygen
miguel-heygen deleted the dscribe/grading-canvas-blank branch October 28, 2026 04:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant