Skip to content

Conversation

mrxz
Copy link
Collaborator

@mrxz mrxz commented Aug 14, 2025

While investigating the way CPU/GPU work is scheduled in Spark I noticed that the GPU work arising from SparkRenderer.updateInternal was not immediately executed, but instead waited for the next rAF or flush. See the following screenshot:
image

This PR introduces a gl.flush() to encourage eager execution. See WebGL_best_practices#flush_when_expecting_results. The browser can now immediately start the GPU work. Additionally the logic was reworked to:

  • Ensure there's only a single timeout scheduled. Multiple timeouts would be scheduled in case >1 rAF took place before it got a chance to run or during WebXR sessions (once for each eye).
  • Use a single THREE.Matrix4 instance to avoid cloning matrixWorld each time (avoids a memory allocation).

With these changes the timeline looks as follows:
image

Edit: for clarity the "GPU idle" and "GPU work" refer to the GPU thread. The key is that no GPU work is scheduled in the before case, whereas it is with this PR. Whether or not the GPU is actually idle at that point obviously depends on other factors. But in case it is, it can immediately start on it.

@dmarcos dmarcos merged commit 3e9ee5f into sparkjsdev:main Sep 15, 2025
2 checks passed
@dmarcos
Copy link
Contributor

dmarcos commented Sep 15, 2025

Great find! Thanks!

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.

2 participants