-
-
Notifications
You must be signed in to change notification settings - Fork 35.4k
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
Feature request: WEBGPU: batch/bundle rendering #26876
Comments
It would be simple* to add the snapshot rendering feature as described in the Babylon.js reference, but as the reference notes, it is only useful with a constant scene graphs, so the use cases for that feature would be limited and should be used with care. It might be worthwhile looking at per object bundle use, but the issues of invalidation need to be worked out for that case and wouldn't provide the same performance improvements as whole scene bundles.
|
My model is mostly static (large bim models). But I use groups [start/end/material index] and change the group/material some time when user does coloring. So I can end up with a lot of drawcalls in some cases. So think snapshot would be a great fit for this. Maybe mesh could have a Old video of app i hope webgpu will help as it gets better. And believe snapshot part is needed for webgpu. This is a very small model... |
How about doing a new scene type... We could make it so This would also deprecate the Lines 100 to 103 in 43a993f
|
I like the term 'static' over 'snapshot' as an API-agnostic way of declaring content's intent for the renderer to optimize. 👍🏻 The feature shouldn't be limited in scope to just multi-material meshes. But declaring the scene static vs. dynamic (all or nothing) feels a bit limiting too. Would it be too complex to allow something like... // (a) mark everything within a THREE.Group as static, allowing the entire
// group to be rendered as a single batch.
group.static = true;
// (b) mark a single THREE.Mesh as static, allowing it to be batched together
// with anything else in the scene also marked as static.
mesh.static = true Or we could go the other way around, let the user declare the scene static by default, and opt-out specific objects as dynamic. But in this case, and in (b) above, we'd still need to do the matrix updates for the entire scene... I might lean toward (a). |
Either way a or b looks practical. Creating renderBundles to freeze some of the scene render, captures the combination of vertex buffer bindings, uniform buffer bindings and shaders, but doesn't prevent you from modifying the contents of the vertices/uniforms themselves, so there is no problem with applying matrix updates etc. You would probably want to turn off frustum culling to ensure all the objects you want are captured when freezing a scene, or with more complexity request thaw/refreeze when the visibility of an object changes.
|
Even if this is the kind of API that's added to the WebGPURenderer I'd still like to see a more flexible, controllable API (like BatchedMesh in #22376) that these more ergonomic use cases can be built on top of. I feel there's a lot of power to having more control which hopefully a demo I'm putting together will demonstrate. Overall my feeling is that static geometry rendering is the least-interesting use case for batching - but I admit that I'm less familiar with what this "GPURenderBundle" call is capable of compared to WEBGL_multidraw_arrays. |
I really hope it will support replacing materials in groups and updating uniforms. Having a lot of fun with merged meshes and geometry groups where I add transformation on selected Would be very nice to be able to port this to webgpu and batch rendering later. Since I will end up with a lot of groups in the end if user goes crazy 😂 Small video of last weeks experiments using transform tool and adding transformations to groups |
That's an interesting point. I'm not sure I understand the full applications of WebGPU render bundles either. It would be interesting to get relative performance numbers for:
If there's really ~zero CPU overhead for drawing 1000 draw calls as a bundle, including distinct materials and un-mergeable objects, and we can continue to update uniform buffers for materials and object transforms without invalidating the bundle ... then that's a hugely flexible feature to have, and limiting it to 'static' objects wouldn't make much sense. Why bother to carefully merge compatible things when you can just toss everything into a bundle? Have one bundle for the static objects and another for the dynamic objects. My guess is that it's not that quite simple and there's more of a tradeoff here. But without knowing what these tradeoffs are, I'm not sure what to propose. |
@donmccurdy Having mesh option |
I have been playing with #26983 and the webgpu_sprites example. You only see significant gains with bundling when you have a large number of draw calls (and associated pipeline and buffer bindings. Rendering 8000 sprites (actually less, because a lot will be culled in the first normal render pass) gives a frame time of 50ms normal and 40ms with bundling enabled. The sprite demo also exposes some of the problems with bundling, the sort order of rendering is frozen as is frustum culling, although the later could be disabled before the 'freeze'. The demonstrations linked are rather misleading, because they don't include the overhead of a full rendering engine. There is still a lot of overhead maintaining the bindingGroups (UBOs in WebGL terms) - selecting what needs updating and then writing etc, which are all still per object. |
A few more use cases we may want to consider eventually:
These uses could be done automatically, without user-facing API. |
Short thread with some helpful comments from Brandon Jones — |
An even more detailed writeup from Brandon! 🎉 |
Bundle Rendering is now possible with the const group = new Group()
group.static = true
// next render the Group and all its children will be automatically bundled and render in a more static way I think we can now close this issue. |
Do you guys think that |
Description
Noticed babylongjs had some tricks to speed up webgpu
https://doc.babylonjs.com/setup/support/webGPU/webGPUOptimization/webGPUSnapshotRendering
Since webgpu is still under development/early in threejs I figured it might be a good time to plan for something like this in threejs also.
From what I understand babylonjs is using GPURenderBundle.
I might be wrong, but I could see they was using it in source code, and threejs did not.
Solution
GPU render bundle is still early, but might be a good time a adapth for it:
https://developer.mozilla.org/en-US/docs/Web/API/GPURenderBundle
Everything with webgpu is early 😄
Samples here showing it in action
https://webgpu.github.io/webgpu-samples/samples/animometer
https://webgpu.github.io/webgpu-samples/samples/renderBundles
Alternatives
Do not really have any alternatives
Additional context
No response
The text was updated successfully, but these errors were encountered: