repro: https://playground.babylonjs.com/?webgpu#6GFJNR#318
You can toggle between webgl and webgpu to see the diff. Bypassing the pointer triggers with captureRtt.renderList = [i1,i2]
works correctly. Logging within the actions show the correct meshes triggered but the rtt just doesn’t show the correct instances. Only the first instance is rendered regardless of how many instances there are. Did I miss smthg?
Thanks for reporting, that wasn’t an easy fix!
master
← Popov72:fix-webgpu-instances
opened 08:05PM - 02 Jul 25 UTC
See https://forum.babylonjs.com/t/webgpu-displays-wrong-instance-in-rtt-when-tri… ggered-via-actions/59331
The problem is that when instances are rendered in a custom RTT, we need different **world0**...**world3** vertex buffers for the RTT than for normal scene rendering, because vertex buffer updates are performed on the queue timeline. This means that all updates (those we do when managing the RTT and those we do when rendering the normal scene) are done before the graphics commands are submitted. Ultimately, the draw calls for the RTT and normal scene rendering use the same buffers, and those buffers contain what we last wrote...
This works in WebGL because Angle can detect that in the current frame, we are updating a buffer already used by a pending graphics command, and can act accordingly (either allocate a new buffer to copy the updated data, or reserve unused space in an existing buffer and remap it to a new vertex buffer under the hood).
We haven't encountered this issue in WebGPU before, probably because we usually always render the mesh + all its instances in the custom RTT. In this case, the **world0**...**world3** vertex buffers contain the same data for the RTT and normal scene rendering.
As for the implementation, I “simply” moved the instance data one level down: it is now by render pass ID, see `_InstanceDataStorage.renderPasses`. A number of properties that were accessible in `_InstanceDataStorage` are now accessible in `_InstanceDataStorage.renderPasses[renderPassId]`.
To avoid too many changes in WebGL and stay as close as possible to the old way of working (and also because VAO management was tedious with the new changes...), we access everything via `_InstanceDataStorage.renderPasses[0]` (see `Mesh._getInstanceDataStorage`, we force the `renderPassId` to 0 in WebGL before accessing `_InstanceDataStorage.renderPasses`).
1 Like