Hi,
I'm wondering what's the best (fastest) way to update big chunks of dynamic vertex data in WebGL, given the differences to GLES2 and desktop GL (more validation, GL renderer living in different process in the case of Chrome, etc...).
My use case is quite simple: have a single big vertex buffer which holds per-instance data for ANGLE_instanced_arrays rendering, which is updated once per frame (with varying number of instances).
What I'm currently doing is buffer orphaning, basically "unlinking" the previous buffer which might still be in flight, and then writing new data hoping that this will effectively result in buffer renaming, and no expensive allocation.
So basically once per frame in pseudo code:
- update instance positions with CPU in a normal memory chunk
- bindBuffer(ARRAY_BUFFER, vb)
- bufferData(ARRAY_BUFFER, vbSize, STREAM_DRAW); // orphan previous data
- bufferSubData(ARRAY_BUFFER, 0, data); // write into (hopefully renamed) new buffer
In GL this would be:
- glBindBuffer(GL_ARRAY_BUFFER, vb);
- glBufferData(GL_ARRAY_BUFFER, vbSize, NULL, GL_STREAM_DRAW);
- glBufferSubData(GL_ARRAY_BUFFER, 0, numBytes, data);
Here's a demo which uses this pattern (requires ANGLE_instanced_arrays):
Depending on browser and platform, this begins to stutter (in Chrome on OSX with IntelHD4000) at around 40k..50k instances (16 byte per instance in instance vertex buffer, so ~800kByte to 1MB), but on a beefy Windows machine with nVidia 600-something it goes to over 600k instances and while the frame rate drops to 30fps (because of the CPU code updating the vertices) there's no stuttering like on OSX.
So my question is basically: is buffer orphaning supposed to work on WebGL (in the sense that behind the scenes, chunks of buffer storage would be rotated/renamed instead of freed/reallocated), and is this the recommended way to update big chunks of dynamic vertex data once per frame?
Thanks!
-Floh.