-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support updating only dirty CompressedArrayTexture
layers
#27972
support updating only dirty CompressedArrayTexture
layers
#27972
Conversation
📦 Bundle sizeFull ESM build, minified and gzipped.
🌳 Bundle size after tree-shakingMinimal build including a renderer, camera, empty scene, and dependencies.
|
Awesome work! @HunterLarco This enhancement appears to also be beneficial for non-compressed array textures ( Also what about using a private prefix and a for (const layerIndex of texture.__layersNeedsUpdate) {
const layerSize = mipmap.width * mipmap.height;
state.compressedTexSubImage3D(_gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, mipmap.data.slice(layerSize * layerIndex, layerSize * (layerIndex + 1)), 0, 0);
}
texture.__layersNeedsUpdate.clear();
// Apply the same approach for state.texSubImage3D |
By the way threejs somehow already supports modifying individual texture array layers through |
Thanks! I'm more than happy to use a private prefix and use a
My team was wondering about this option and had a question. If I create (but do not use in a material) a texture, does it get allocated in GPU memory? One of the benefits of the texture array is that we've already allocated the GPU memory and can subsequently write to it. Whereas copying from a different texture requires that we allocate new/additional memory. This may be good in some scenarios to mitigate texture locking, but not all. |
Ah you're right, it's usually using single Simply creating a texture shouldn't allocate in GPU memory. It would need to be used in a uniform somewhere in order to call |
There is no other instance of the word "dirty" in the library. |
|
Updated to reflect the previously established naming convention of "needsUpdate" instead of "dirty". |
Apologies for the delay, a few things took my time at work but I now have time to land this. |
Bump~ is there anything remaining on my end to help land this? |
Sorry, for the delay! The PR looks good now and can be merged. |
Hmm, any chance we could add an example for this? Or implement the feature in any of the existing examples? |
Related issue: n/a
Description
ThreeJS's
CompressedArrayTexture
is useful to pack multiple compressed textures into a single sampler (making more efficient use of GPU resources). However, it's critical for performance that when making changes to the texture array, that the CPU only update subsets of the bound GPU texture. It turns out that ThreeJS does not currently support modifying individual texture array layers, instead it always flushes the entire texture array to the GPU on every change. This PR changes ThreeJS by adding new functionality to update specific layers individually resulting in much less data transmission during render and therefore better performance.Case Study
My company SOOT, uses
CompressedArrayTexture
regularly with large numbers of 256x256 layers. We observed that if we needed to updateN
layers in a frame this would result in a command buffer issued to the GPU withN * byteSize(textureArray)
when we expectedN * byteSize(layer)
. This resulted in 16777216 bytes transmitted from CPU to GPU multiple times per frame instead of 65536. By authoring this change we observed a 99.6% reduction in command buffer size between the CPU and GPU and a 423% increase in framerate.Implementation Strategy
I designed this change to be minimally invasive and not impact existing ThreeJS projects. The feature is gated by the new field
layerUpdates
which was not previously used by the codebase. As a result, if ThreeJS users don't calltexture.addLayerUpdate(...)
then this change has no impact.This contribution is funded by SOOT