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>
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.
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