diff --git a/lib/webgl/TextureContextWebGL.ts b/lib/webgl/TextureContextWebGL.ts index 2dde5796..8a7f0af4 100644 --- a/lib/webgl/TextureContextWebGL.ts +++ b/lib/webgl/TextureContextWebGL.ts @@ -25,6 +25,7 @@ export class TextureContextWebGL { public static MAX_SAMPLERS = 16; _lastBoundedTexture: TextureWebGL; + _activeTextureUnit: number = -1; _samplerStates: SamplerStateWebGL[] = []; _currentRT: RenderTargetWebGL = null; @@ -109,14 +110,10 @@ export class TextureContextWebGL { public setTextureAt(sampler: number, texture: TextureWebGL): number { const gl = this._context._gl; const samplerState = this._samplerStates[sampler]; - const textureType = GL_MAP.TEXTURE[texture.textureType]; - - if ((texture || samplerState.type)) { - gl.activeTexture(gl.TEXTURE0 + sampler); - } if (!texture) { if (samplerState.type) { + this._activateTextureUnit(sampler); // disable link to sampler in bounded texture if (samplerState.boundedTexture) { @@ -132,15 +129,33 @@ export class TextureContextWebGL { return -1; } + const textureType = GL_MAP.TEXTURE[texture.textureType]; + const alreadyBound = samplerState.boundedTexture === texture && samplerState.type === textureType; + // commit early-outs when wrap/filter already match texture._state + const paramsDirty = !alreadyBound || !samplerState.equals(texture._state); + + // Skip activeTexture when unit is active, texture already bound, params unchanged. + if (!alreadyBound || paramsDirty || this._activeTextureUnit !== sampler) + this._activateTextureUnit(sampler); + texture._state.id = sampler; - this.bindTexture(texture, false, textureType); + // Skip redundant GL bindTexture when this sampler already holds the texture. + this.bindTexture(texture, alreadyBound, textureType); samplerState.commit(textureType, texture); + samplerState.boundedTexture = texture; return sampler; } + private _activateTextureUnit(sampler: number): void { + if (this._activeTextureUnit === sampler) + return; + this._activeTextureUnit = sampler; + this._gl.activeTexture(this._gl.TEXTURE0 + sampler); + } + public setSamplerStateAt( sampler: number, wrap: ContextGLWrapMode,