Keep packed acquisition arguments and callbacks alive across native calls - #10
Open
dylanebert wants to merge 3 commits into
Open
dylanebert wants to merge 3 commits into
dylanebert wants to merge 3 commits into
Conversation
* bridge: keep packed acquisition arguments and callbacks alive A CallArena holds every buffer a packed descriptor points into until the request callback runs; device error/loss callbacks live with the adapter; queue and pop-error-scope callback info stay referenced until completion. Version 0.1.7-shallot.1 with platform packages as optional dependencies so a git install finds its native library. * bridge: lock platform packages * bridge: link upstream PR in README
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #9, which closed when its source branch was deleted. Same change, now on a branch that stays.
Problem
On bun-webgpu 0.1.7 (Bun 1.4.x), twenty
requestDevicecalls withBun.gc(true)forced between descriptor packing andwgpuAdapterRequestDeviceproduce descriptor drift: devices come back with features and limits that differ from the request, or acquisition fails outright.Cause
WGPUDeviceDescriptorStruct.pack(and every nested struct, string, enum/struct/primitive array and object-pointer array it packs) allocates ArrayBuffers that are only reachable through raw pointers written into the parent buffer. Nothing in JS holds them, so a collection before or during the native call frees memory Dawn is about to read. The same applies torequestAdapteroptions, the callback-info structs,queue.onSubmittedWorkDoneanddevice.popErrorScopecallback info (the pop-scope userdata buffer included). The device's uncaptured-error and device-lostJSCallbacks were locals too, even though native code calls them for the device's lifetime.Fix
structs_ffi.ts:CallArena, passed as a newarenapack option; every buffer a pack allocates (and every object whose.ptrit writes) joins it.requestAdapter/requestDevice: one arena per request, released after the request callback runs (or on failure).GPUAdapter: keeps the device error/loss callbacks referenced.GPUQueue.onSubmittedWorkDone,GPUDevice.popErrorScope: keep the callback info (and userdata) referenced until completion.Evidence
src/acquisition.test.ts: twenty acquisitions with a forced GC plus allocation churn wedged in front of the native call; each device's features and every limit must equal the request. Passes with the fix (800 expects, RTX 4090 / Vulkan, Bun 1.4.2); the existing suite is unchanged (186 pass, 1 skip).🤖 Generated with Claude Code
https://claude.ai/code/session_01FFh77i2dpmMjbVhbEUd5qX