Skip to content

Commit 69c3778

Browse files
authored
WebGPU: Fix wrong instances displayed in custom RTT (#16842)
See https://forum.babylonjs.com/t/webgpu-displays-wrong-instance-in-rtt-when-triggered-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 parent cac31a5 commit 69c3778

File tree

5 files changed

+153
-64
lines changed

5 files changed

+153
-64
lines changed

packages/dev/core/src/Meshes/instancedMesh.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,9 @@ declare module "./mesh" {
684684
vertexBuffers: { [key: string]: Nullable<VertexBuffer> };
685685
strides: { [key: string]: number };
686686
vertexArrayObjects?: { [key: string]: WebGLVertexArrayObject };
687+
renderPasses?: {
688+
[renderPassId: number]: { [kind: string]: Nullable<VertexBuffer> };
689+
};
687690
};
688691
}
689692
}
@@ -827,10 +830,10 @@ Mesh.prototype._invalidateInstanceVertexArrayObject = function () {
827830
};
828831

829832
Mesh.prototype._disposeInstanceSpecificData = function () {
830-
if (this._instanceDataStorage.instancesBuffer) {
831-
this._instanceDataStorage.instancesBuffer.dispose();
832-
this._instanceDataStorage.instancesBuffer = null;
833+
for (const renderPassId in this._instanceDataStorage.renderPasses) {
834+
this._instanceDataStorage.renderPasses[renderPassId].instancesBuffer?.dispose();
833835
}
836+
this._instanceDataStorage.renderPasses = {};
834837

835838
while (this.instances.length) {
836839
this.instances[0].dispose();

0 commit comments

Comments
 (0)