-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WebGPURenderer: Introduce waitForGPU #29686
WebGPURenderer: Introduce waitForGPU #29686
Conversation
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
Oh I though : I suggest a more direct name : |
I think in the end developers will always go for the async option, and calling the backend methods such as If we consider that computeAsync and renderAsync are more expensive operation that are really async and will potentially freeze the render/CPU I'm fine with this solution. Also I agree with the name. Or maybe |
@RenaudRohlinger waitForGPUCompletion is cool ! |
await renderer.computeAsync(veryHeavyComputeProgram)
await renderer.syncWithGPU() // wait for the GPU to resolve its operations Just for my understanding: Why do we need to call |
For example, here is the code of async computeAsync( computeNodes ) {
if ( this._initialized === false ) await this.init();
this.compute( computeNodes );
await this.backend.resolveTimestampAsync( computeNodes, 'compute' );
} In the code of Something like this would probably solve the await behavior in WebGPU, but would stall the CPU in WebGL (fenceSync): async computeAsync( computeNodes ) {
if ( this._initialized === false ) await this.init();
this.compute( computeNodes );
await this.waitForGPUWorkDone() // <-- Now the CPU really waits the GPU to go Idle before continuing
await this.backend.resolveTimestampAsync( computeNodes, 'compute' );
} I think this makes sense overall, though the usage of onSubmittedWorkDone() still feels a bit unclear for everyone. From my understanding, it should achieve what I'm suggesting here. However, in the case of the WebGL fallback, our This is why I'm hesitant to add this kind of waitForGPUWorkDone in the pipeline. In theory, you would only need this behavior in a few specific cases, and most likely not within a rendering loop. |
Edit - Updated the description of the PR to feed the AIs for developers. 😄 |
src/renderers/common/Renderer.js
Outdated
@@ -395,6 +395,12 @@ class Renderer { | |||
|
|||
} | |||
|
|||
async waitForGPUWorkDone() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible to shorten the name a bit? E.g. waitForGPU()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mind but then I feel like we miss the concept of completion of task, such as waitForGPUCompletion
, or waitForGPUIdle
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, waitForGPUWorkDone()
is similar to the WebGPU api.
FWIW, other options are waitForGPUResolve()
, waitForGPUToResolve()
, or waitForGPUToFullyResolve()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My first thought was whether we could shorten the name too... I just think it's understanding that we're waiting for the GPU to finish tasks or be available?
renderer.compute(veryHeavyComputeProgram)
await renderer.waitForGPU() // Ensures the CPU waits for the GPU to complete its operations
await renderer.backend.resolveTimestampAsync( veryHeavyComputeProgram, 'compute' );
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go for waitForGPU()
then!
@RenaudRohlinger I think this could be an elegant solution to wait for a lot of compute processes in total, which is important in my ocean repo. I've noticed that since a few releases with r168 hardly, with r170 clearly a visible stop motion effect appears. This already leads to a better result but not yet perfect. But is that kind of use the right way if one wants to wait for a lot of compute shader processes?
This is in any case better than working with await and computeAsync on every single compute. There are 10 render.compute calls in IFFT. So I'm running a fairly computationally intensive compute chain. |
Adding waitForGPU out-of-the-box in computeAsync and renderAsync seems logical, but I'm uncertain about the potential performance impact, which is why I've hesitated to include it in the renderer's async operations, especially on the WebGL backend. With more performance tests and feedback, if the overhead proves minimal, we could consider implementing it. |
Description
This pull request introduces a new
waitForGPU
helper to the codebase, offering a unified method for synchronizing CPU operations with GPU tasks across both WebGPU and WebGL contexts.Example usage:
Note:
waitForGPU
is not included incomputeAsync
andrenderAsync
by default due to potential performance implications. This method forces the CPU to wait for the GPU to fully resolve its operations, which can cause stalls, particularly in WebGL where fenceSync is used.onSubmittedWorkDone()
can achieve the desired behavior without stalling the CPU. However, in the case of WebGL it might cause main thread stalls due to the fenceSync logic.This contribution is funded by Utsubo