Skip to content
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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 21 additions & 0 deletions docs/api/en/textures/CompressedArrayTexture.html
Expand Up @@ -61,11 +61,32 @@ <h3>[property:number wrapR]</h3>
<h3>[property:Object image]</h3>
<p>Overridden with a object containing width, height, and depth.</p>

<h3>[property:Set layerUpdates]</h3>
<p>
A set of all layers which need to be updated in the texture. See
[Page:CompressedTextureArray.addLayerUpdate addLayerUpdate].
</p>

<h3>[property:Boolean isCompressedArrayTexture]</h3>
<p>Read-only flag to check if a given object is of type [name].</p>

<h2>Methods</h2>

<h3>[method:addLayerUpdate addLayerUpdate]( layerIndex )</h3>
<p>
Describes that a specific layer of the texture needs to be updated.
Normally when [page:Texture.needsUpdate needsUpdate] is set to true, the
entire compressed texture array is sent to the GPU. Marking specific
layers will only transmit subsets of all mipmaps associated with a
specific depth in the array which is often much more performant.
</p>

<h3>[method:clearLayerUpdates clearLayerUpdates]()</h3>
<p>
Resets the layer updates registry. See
[Page:CompressedTextureArray.addLayerUpdate addLayerUpdate].
</p>

<p>
See the base [page:CompressedTexture CompressedTexture] class for common
methods.
Expand Down
22 changes: 22 additions & 0 deletions docs/api/en/textures/DataArrayTexture.html
Expand Up @@ -143,8 +143,30 @@ <h3>[property:number wrapR]</h3>
page for details.
</p>

<h3>[property:Set layerUpdates]</h3>
<p>
A set of all layers which need to be updated in the texture. See
[Page:DataArrayTexture.addLayerUpdate addLayerUpdate].
</p>

<h2>Methods</h2>

<h3>[method:addLayerUpdate addLayerUpdate]( layerIndex )</h3>
<p>
Describes that a specific layer of the texture needs to be updated.
Normally when [page:Texture.needsUpdate needsUpdate] is set to true, the
entire compressed texture array is sent to the GPU. Marking specific
layers will only transmit subsets of all mipmaps associated with a
specific depth in the array which is often much more performant.
</p>

<h3>[method:clearLayerUpdates clearLayerUpdates]()</h3>
<p>
Resets the layer updates registry. See
[Page:DataArrayTexture.addLayerUpdate addLayerUpdate].
</p>


<p>See the base [page:Texture Texture] class for common methods.</p>

<h2>Source</h2>
Expand Down
84 changes: 82 additions & 2 deletions src/renderers/webgl/WebGLTextures.js
Expand Up @@ -820,7 +820,22 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,

if ( dataReady ) {

state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 );
if ( texture.layerUpdates.size > 0 ) {

for ( const layerIndex of texture.layerUpdates ) {

const layerSize = mipmap.width * mipmap.height;
state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, layerIndex, mipmap.width, mipmap.height, 1, glFormat, mipmap.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ), 0, 0 );

}

texture.clearLayerUpdates();

} else {

state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 );

}

}

Expand Down Expand Up @@ -926,7 +941,72 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,

if ( dataReady ) {

state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
if ( texture.layerUpdates.size > 0 ) {

// When type is GL_UNSIGNED_BYTE, each of these bytes is
// interpreted as one color component, depending on format. When
// type is one of GL_UNSIGNED_SHORT_5_6_5,
// GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_SHORT_5_5_5_1, each
// unsigned value is interpreted as containing all the components
// for a single pixel, with the color components arranged
// according to format.
//
// See https://registry.khronos.org/OpenGL-Refpages/es1.1/xhtml/glTexImage2D.xml
let texelSize;
switch ( glType ) {

case _gl.UNSIGNED_BYTE:
switch ( glFormat ) {

case _gl.ALPHA:
texelSize = 1;
break;
case _gl.LUMINANCE:
texelSize = 1;
break;
case _gl.LUMINANCE_ALPHA:
texelSize = 2;
break;
case _gl.RGB:
texelSize = 3;
Fixed Show fixed Hide fixed
break;
case _gl.RGBA:
texelSize = 4;
Fixed Show fixed Hide fixed
break;

default:
Fixed Show fixed Hide fixed
throw new Error( `Unknown texel size for format ${glFormat}.` );

Fixed Show fixed Hide fixed
}

Fixed Show fixed Hide fixed
break;

case _gl.UNSIGNED_SHORT_4_4_4_4:
case _gl.UNSIGNED_SHORT_5_5_5_1:
case _gl.UNSIGNED_SHORT_5_6_5:
texelSize = 1;
break;

default:
throw new Error( `Unknown texel size for type ${glType}.` );

}

Fixed Show fixed Hide fixed
const layerSize = image.width * image.height * texelSize;

for ( const layerIndex of texture.layerUpdates ) {

state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, layerIndex, image.width, image.height, 1, glFormat, glType, image.data.slice( layerSize * layerIndex, layerSize * ( layerIndex + 1 ) ) );

}
Fixed Show fixed Hide fixed

texture.clearLayerUpdates();

} else {

state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );

}

}

Expand Down
14 changes: 14 additions & 0 deletions src/textures/CompressedArrayTexture.js
Expand Up @@ -11,6 +11,20 @@ class CompressedArrayTexture extends CompressedTexture {
this.image.depth = depth;
this.wrapR = ClampToEdgeWrapping;

this.layerUpdates = new Set();

}

addLayerUpdates( layerIndex ) {

this.layerUpdates.add( layerIndex );

}

clearLayerUpdates() {

this.layerUpdates.clear();

HunterLarco marked this conversation as resolved.
Show resolved Hide resolved
}

}
Expand Down
14 changes: 14 additions & 0 deletions src/textures/DataArrayTexture.js
Expand Up @@ -20,6 +20,20 @@ class DataArrayTexture extends Texture {
this.flipY = false;
this.unpackAlignment = 1;

this.layerUpdates = new Set();

}

addLayerUpdate( layerIndex ) {

this.layerUpdates.add( layerIndex );

}

clearLayerUpdates() {

this.layerUpdates.clear();

}

}
Expand Down