# How to keep buffers on the GPU when using compute shaders for instancing or vertex data generation

**URL:** <https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951>\
**Category:** Questions\
**Tags:** instances, thininstances, compute-shader\
**Created:** [November 26, 2023, 7:34pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951 "2023-11-26T19:34:08Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![CrashMaster](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/crashmaster/32/23662_2.png) [@CrashMaster](https://forum.babylonjs.com/u/CrashMaster)\
**Post date:** [November 26, 2023, 7:34pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/1 "2023-11-26T19:34:08Z")

</div>

Hello everyone,  
I have been learning the ways of compute shaders recently, and I am now using them to generate an instance buffer like in this PG:

> **[Babylon.js Playground](https://playground.babylonjs.com/#VMA5LR%2314)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

The compute shader creates an instance buffer on the GPU, then it gets copied to the CPU at the end of the compute dispatch, so that I can pass it to `thinInstanceSetBuffer` which sends it again to the GPU (that what I understand at least).

Copying all this data back and forth is not ideal and there is probably some trick to keep all the data on the GPU which would be a sizeable improvement. Does someone have an idea?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [November 27, 2023, 12:13pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/2 "2023-11-27T12:13:32Z")

</div>

You can’t use your own buffers with thin instances, so what you want to do is currently not possible.

You could try to hack it, by creating your own vertex buffer based on your storage buffer (you can pass `storageBuffer.getBuffer()` as the second parameter of the `VertexBuffer` constructor) and setting it to `mesh.setVerticesBuffer("world", your_vertex_buffer)`. However, for thin instances, the matrices are passed as 4 vertex buffers, world0/world1/world2/world3 (worldX correspond to the row X of the matrix). So, you would need to change your compute shader to fill 4 storage buffers, and you would have to create 4 vertex buffers.

---

<div class="post-metadata">

**Author:** ![CrashMaster](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/crashmaster/32/23662_2.png) [@CrashMaster](https://forum.babylonjs.com/u/CrashMaster)\
**Post date:** [November 27, 2023, 1:26pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/3 "2023-11-27T13:26:43Z")

</div>

I see, is this a technical limitation of webgpu? I will try to implement the hack in the PG and I will post it here later. Thanks for the answer!

In the case of VertexData (positions, normals, indices) generated for a simple mesh by a compute shader, what would the hack look like?

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [November 27, 2023, 1:34pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/4 "2023-11-27T13:34:25Z")

</div>

It’s not a limit of WebGPU but the fact that our current implementation of thin instances pre-date WebGPU, so it does not support storage buffers.

For a simple mesh it is quite easy:

- create a storage buffer
- create a vertex buffer by using this storage buffer: `vb = new VertexBuffer(engine, storageBuffer.getBuffer(), ...)`
- set this vertex buffer to your mesh: `mesh.setVerticesBuffer("position", vb)`

You can see an example in the [boids compute shader example](https://playground.babylonjs.com/#3URR7V#186) from the documentation.

---

<div class="post-metadata">

**Author:** ![CrashMaster](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/crashmaster/32/23662_2.png) [@CrashMaster](https://forum.babylonjs.com/u/CrashMaster)\
**Post date:** [November 27, 2023, 1:48pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/5 "2023-11-27T13:48:40Z")

</div>

That looks fairly easy! I will also create a small PG for that one.

Just to clarify, is using the storage buffer incompatible with a physics engine? I assume that with the physics engine residing on the CPU, while the vertex data resides on the GPU, it may be impossible to account for collisions. I am currently weighing my options here, haha.

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [November 27, 2023, 2:39pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/6 "2023-11-27T14:39:36Z")

</div>

Yes, it’s incompatible with a physics engine because it needs to access the matrices of the thin instances.

---

<div class="post-metadata">

**Author:** ![CrashMaster](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/crashmaster/32/23662_2.png) [@CrashMaster](https://forum.babylonjs.com/u/CrashMaster)\
**Post date:** [November 27, 2023, 2:47pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/7 "2023-11-27T14:47:59Z")

</div>

Vertex data generated by compute shaders:

- without skipping the CPU: [https://playground.babylonjs.com/#25VLT7#5](https://playground.babylonjs.com/#25VLT7#5) (works)
- with skipping the CPU: [https://playground.babylonjs.com/#25VLT7#8](https://playground.babylonjs.com/#25VLT7#8) (does not work)

It almost works! The last problem is with setting the index buffer. I found [Updating Indices of a Mesh: `updateIndices` vs ` setVerticesBuffer`](https://forum.babylonjs.com/t/updating-indices-of-a-mesh-updateindices-vs-setverticesbuffer/27676) where it is advised to use the `updateIndices` method instead of `setVerticesBuffer`.

The issue is that `updateIndices` takes an IndicesArray ([BABYLON | Babylon.js Documentation](https://doc.babylonjs.com/typedoc/modules/BABYLON#IndicesArray)), and does not accept my storage buffer sadly. I also saw the boids compute shader uses a cpu buffer for the indices.

Is there a workaround to set the index buffer using the gpu storage?

---

<div class="post-metadata">

**Author:** ![CrashMaster](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/crashmaster/32/23662_2.png) [@CrashMaster](https://forum.babylonjs.com/u/CrashMaster)\
**Post date:** [November 27, 2023, 3:27pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/8 "2023-11-27T15:27:09Z")

</div>

I am working on the thin instance hack but I am struggling with `setVerticesBuffer`. I can indeed get the world0, world1, world2, world3 properly and I can create the associate buffers but how do I tell my grass blade to create thin instances out of it?

This PG has a boolean to toggle CPU skipping:

> **[Babylon.js Playground](https://playground.babylonjs.com/#VMA5LR%2334)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [November 27, 2023, 4:07pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/9 "2023-11-27T16:07:08Z")

</div>

> [@CrashMaster](#):
>
> Is there a workaround to set the index buffer using the gpu storage?

Here’s a PG that works:

> **[Babylon.js Playground](https://playground.babylonjs.com/?webgpu#25VLT7%2311)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

You must explicitely set the `geometry._indexBuffer` by hand, and create a submesh (it’s done for you when you call `mesh.setIndices`, but you can’t do it in this case).

Also, you must create your storage buffers with the right flags: BUFFER\_CREATIONFLAG\_READWRITE + BUFFER\_CREATIONFLAG\_VERTEX or BUFFER\_CREATIONFLAG\_INDEX, depending on the buffer.

Lastly, you can’t use `material.wireframe = true`, because it triggers an index buffer creation to properly render lines, which expects to be able to read from the existing index buffer.

This PR will simplify things a bit:

> <https://github.com/BabylonJS/Babylon.js/pull/14551>
>
> See https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-comp…ute-shaders-for-instancing-or-vertex-data-generation/45951/6

Once it’s merged, this PG will work:

> **[Babylon.js Playground](https://playground.babylonjs.com/?webgpu#25VLT7%2313)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

---

<div class="post-metadata">

**Author:** ![Evgeni\_Popov](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/evgeni_popov/32/4432_2.png) [@Evgeni\_Popov](https://forum.babylonjs.com/u/Evgeni_Popov)\
**Post date:** [November 27, 2023, 6:01pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/10 "2023-11-27T18:01:42Z")

</div>

> [@CrashMaster](#):
>
> I am working on the thin instance hack but I am struggling with `setVerticesBuffer`. I can indeed get the world0, world1, world2, world3 properly and I can create the associate buffers but how do I tell my grass blade to create thin instances out of it?

This PR will let you force an instance count for thin instances:

> <https://github.com/BabylonJS/Babylon.js/pull/14553>
>
> See https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-comp…ute-shaders-for-instancing-or-vertex-data-generation/45951/7

You also have to indicate that your vertex buffer uses instancing by setting the `instanced: true` option.

Once the PR is merged, this PG will work:

> **[Babylon.js Playground](https://playground.babylonjs.com/?webgpu#VMA5LR%2339)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL 3D scenes

---

<div class="post-metadata">

**Author:** ![CrashMaster](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/crashmaster/32/23662_2.png) [@CrashMaster](https://forum.babylonjs.com/u/CrashMaster)\
**Post date:** [November 27, 2023, 9:38pm UTC](https://forum.babylonjs.com/t/how-to-keep-buffers-on-the-gpu-when-using-compute-shaders-for-instancing-or-vertex-data-generation/45951/11 "2023-11-27T21:38:09Z")

</div>

Wow wow that’s awesome! Thank you I am very excited for the next release haha

I will mark this as solved then, thank you again 🙂
