Problem
Canvas surface readback can silently return zero-filled data when surface.color is read after the browser has presented the rendered texture. At that point GPUCanvasContext.getCurrentTexture() refers to a fresh, unrendered presentation texture rather than the one submitted by the completed frame. This is the behavior reported in #387.
Expected and actual behavior
Expected: readback succeeds only for the current canvas texture that was actually submitted by a completed frame, and stale or not-yet-submitted surface reads fail clearly.
Actual: surface.color.read() wraps whichever texture getCurrentTexture() returns at access time, so deferred reads can silently copy from a new zero-filled texture.
Reproduction / use case
Render to a canvas surface, allow presentation to advance, then call surface.color.read(...). The canvas shows the rendered output while readback can contain zeros. The regression test models the presentation advance by rotating the mocked current-texture identity.
Related work and proposal
Related to #387; this is the same silent-failure family as the separate compute report in #416.
This proposal:
- records the exact canvas texture attached to each frame;
- promotes it to readable state only after successful queue submission;
- rejects reads during an active frame, before submission, after cancellation, or after presentation advances;
- reports
VGPU-SURFACE-READ-UNAVAILABLEwith an offscreen-target workaround; - documents the current-presentation-frame constraint and regenerates reference docs.
The texture-identity check follows the WebGPU canvas current-texture lifecycle described by the W3C specification: https://www.w3.org/TR/webgpu/#canvas-context-getcurrenttexture
Validation
packages/vgpu-api/tests/surface-mock.test.ts: 14 passed- full
vgpu-apisuite excluding the repository's known Windows child-command suites: 736 passed, 79 skipped pnpm run typecheck: passedpnpm run check:skill-drift: passedgit diff --check: passed- GitHub CI: all substantive test, Windows, Docker GPU, docs, and security jobs passed
pnpm test:fast: 1,092 passed, but the Windows checkout still has unrelated path, child-process, and WGSL fixture-resolution failures- docs snippet verification is blocked locally because its direct
spawnSync("pnpm")lookup returnsENOENTon this Windows host
PR type
contribution
Activity
6@matiasngf This draft addresses #387 by guarding stale canvas-surface readback across the frame lifecycle. It remains a draft contribution proposal, and all substantive GitHub CI jobs are green. Could you review it when convenient?
This pull request is a draft
Merging is unavailable until it is marked ready for review.
@Ali-Karaki is attempting to deploy a commit to the Vercel Labs Team on Vercel.
A member of the Team first needs to authorize it.