Repository navigation
Conversation
`buffer_update` wrote into a buffer's store with `glBufferSubData`. A store that draws already queued still read can't be written in place, so the driver copies it first. On a Pixel 6 (Mali-G78), every such write flushed the driver's queue and waited on its backend thread. A macroquad game refills the same stream buffers for each flush of its batches, so a frame that switches render targets a dozen times spent a third of its render thread's time in `glBufferSubData`: about 6 ms a frame. The wait followed the GPU's progress, so a lighter frame, which the GPU clocks down for, waited longer still. `buffer_update` now gives the buffer a new store holding the data (`glBufferData`), which the driver can hand over without copying or waiting. Metal already writes each update into a buffer of its own, so what lay past the data was already gone there. `buffer_update`'s docs now say so. On the Pixel 6, at 60 Hz, a macroquad game with a blurred dim over its frame went from 57.1 to 60.0 fps, its frames' CPU time from 14.2 to 12.5 ms at the median. Each store now only holds the data last written to it, rather than as much as the buffer was made for, so the game's graphics memory went from 212 to 184 MB: macroquad makes its stream buffers big enough for its largest batch. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: multica-agent <github@multica.ai>
|
Confirmed on Adreno as well. We hit the same thing independently in a macroquad 0.4.16 game (Razdor) and wrote the same change (#703, now closed in favour of this one; ours only switched OnePlus 13 (Adreno 830, driver V@0800.77, Android 16), 2.5D map at idle, display confirmed at 120 Hz in
An earlier simpleperf run on the same phone put about 60% of the frame's CPU time in Desktop shows no change, as expected: Mesa llvmpipe 10.56 → 10.53 ms per frame (identical frames, pixel for pixel), and an RTX 4060 (proprietary driver) where One thing we tried first, in case it saves someone time: orphaning with (Measured on the device by me; written up with Claude Code.) |
…ream not-fl3#691, not-fl3#682 (#2) * Integrate upstream PRs not-fl3#691, not-fl3#682: src/graphics/gl.rs * Integrate upstream PRs not-fl3#691, not-fl3#682: src/graphics/gl/cache.rs * Integrate upstream PRs not-fl3#691, not-fl3#682: src/graphics.rs * ci: add targeted Rust WebAssembly and JS build checks * ci: allow generating Cargo.lock for library builds
Why
buffer_updatewrote into a buffer's existing store withglBufferSubData. A store that draws already queued still read can't be written in place, so the driver has to copy it first. On a Pixel 6 (Mali-G78), every such write flushed the driver's queue and waited on its backend thread.macroquad refills the same stream buffers for each flush of its batches, and flushes whenever it switches render targets. In a game (CHOMP) whose screens blur the frame behind a modal, about a dozen switches a frame, the render thread spent a third of its time in
glBufferSubData, about 6 ms a frame, according tosimpleperf --trace-offcpu:The wait followed the GPU's progress, so a lighter frame, which the GPU clocked down for, waited longer still.
Change
buffer_updategives the buffer a new store holding the data (glBufferData, with the buffer's usage hint), which the driver can hand over without copying or waiting. Metal already writes each update into a buffer slot of its own, so what lay past the data was already gone there. The trait's doc forbuffer_updatenow says so: the data can be shorter than the buffer, and what lies past it is undefined afterwards.Each store now only holds the data last written to it, rather than as much as the buffer was made for. macroquad makes its stream buffers big enough for its largest batch, so that's less memory too.
Measurements
CHOMP's frame bench on a Pixel 6 at 60 Hz, with a modal open over a level whose frame is blurred behind it, held for 30 s:
dumpsys meminfo, GL mtrack), after the benchVerification
cargo checkpasses foraarch64-linux-android,wasm32-unknown-unknown,aarch64-apple-darwin,aarch64-apple-iosandaarch64-apple-tvos.🤖 Generated with Claude Code