-
-
Notifications
You must be signed in to change notification settings - Fork 36.1k
Description
Is your feature request related to a problem? Please describe.
The problem is mainly related to the performance cost of setting up a big texture which is populated incrementally. Allow me to give some context:
I'm using a custom texture subclass which exposes texSubImage2D for that particular texture. The class is inspired by this code, but is adapted to WebGL 2. You can find the custom subclass here.
In my use case the updatable texture (typically sized 8192²) is populated in chunks which is why I'm using texSubImage2D. This means that the initial texture data is empty. However, with the current approach, I need to allocate a data buffer (e.g., with length == 8192²) so that the texture can be initialized with this data. This is suboptimal from a performance perspective since
- I need to allocate the data buffer (depending on dtype this can be well over 200 MB) even though I don't need this buffer for the partial updates and
- threejs uploads the data to the GPU even though it's not really necessary (as it's only zeros). The initial upload roughly takes 1 second for my data load which I'd like to avoid.
For WebGL 1, one could make the texture size 1x1 initially and resize it before the first usage. However, in WebGL 2 this is apparently not possible anymore, since the texture size is immutable.
I found a workaround to the performance problem by passing { width: actualWidth, height: actualHeight, data: new Uint32Array(1) } to the constructor super call of the Texture class. This avoids the unnecessary memory allocation and texture upload. However, it obviously leads to a WebGL error, since the upload call texSubImage2D fails due to the incorrectly sized data array. The rendering works fine afterwards, but the failing WebGL call + error message in the console is not really satisfying to me.
Describe the solution you'd like
I think, it would be ideal if we could tell ThreeJS somehow that it shouldn't do the initial data upload with texSubImage2D or texImage2D in uploadTexture. The rest of the function (i.e., the whole texture setup) should still happen. For example, texture.image.suppressInitialTextureUpload = true could be set on the texture to skip the upload call.
Describe alternatives you've considered
- Handling the texture setup without threejs would also be a viable option to me, but I still want to attach the texture to a ThreeJS material so I'm not sure how this could work.
- Texture SubImage Interface #17162 could also be of interest, but 1) there's little progress on this regard 2) the lazy initialization wasn't yet discussed there.