Jelajahi Sumber

Cache texture changes better

Ben Adams 9 tahun lalu
induk
melakukan
8f9a8ccd82
1 mengubah file dengan 62 tambahan dan 52 penghapusan
  1. 62 52
      src/babylon.engine.ts

+ 62 - 52
src/babylon.engine.ts

@@ -58,7 +58,7 @@
         var potWidth = Tools.GetExponentOfTwo(width, engine.getCaps().maxTextureSize);
         var potHeight = Tools.GetExponentOfTwo(height, engine.getCaps().maxTextureSize);
 
-        gl.bindTexture(gl.TEXTURE_2D, texture);
+        engine._bindTextureDirectly(gl.TEXTURE_2D, texture);
         gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
 
         texture._baseWidth = width;
@@ -78,7 +78,7 @@
             gl.generateMipmap(gl.TEXTURE_2D);
         }
 
-        gl.bindTexture(gl.TEXTURE_2D, null);
+        engine._bindTextureDirectly(gl.TEXTURE_2D, null);
 
         engine.resetTextureCache();
         scene._removePendingData(texture);
@@ -337,7 +337,8 @@
         // Cache
         private _loadedTexturesCache = new Array<WebGLTexture>();
         private _maxTextureChannels = 16;
-        private _activeTexturesCache = new Array<BaseTexture>(this._maxTextureChannels);
+        private _activeTexture: number;
+        private _activeTexturesCache = new Array<WebGLTexture>(this._maxTextureChannels);
         private _currentEffect: Effect;
         private _currentProgram: WebGLProgram;
         private _compiledEffects = {};
@@ -862,9 +863,9 @@
             this._currentRenderTarget = null;
             if (texture.generateMipMaps && !disableGenerateMipMaps) {
                 var gl = this._gl;
-                gl.bindTexture(gl.TEXTURE_2D, texture);
+                this._bindTextureDirectly(gl.TEXTURE_2D, texture);
                 gl.generateMipmap(gl.TEXTURE_2D);
-                gl.bindTexture(gl.TEXTURE_2D, null);
+                this._bindTextureDirectly(gl.TEXTURE_2D, null);
             }
 
             this.bindUnboundFramebuffer(null);
@@ -873,9 +874,9 @@
         public generateMipMapsForCubemap(texture: WebGLTexture) {
             if (texture.generateMipMaps) {
                 var gl = this._gl;
-                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
                 gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
-                gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+                this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
             }
         }
 
@@ -1560,7 +1561,7 @@
         public setSamplingMode(texture: WebGLTexture, samplingMode: number): void {
             var gl = this._gl;
 
-            gl.bindTexture(gl.TEXTURE_2D, texture);
+            this._bindTextureDirectly(gl.TEXTURE_2D, texture);
 
             var magFilter = gl.NEAREST;
             var minFilter = gl.NEAREST;
@@ -1576,7 +1577,7 @@
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
             gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
 
-            gl.bindTexture(gl.TEXTURE_2D, null);
+            this._bindTextureDirectly(gl.TEXTURE_2D, null);
 
             texture.samplingMode = samplingMode;
         }
@@ -1719,7 +1720,7 @@
 
         public updateRawTexture(texture: WebGLTexture, data: ArrayBufferView, format: number, invertY: boolean, compression: string = null): void {
             var internalFormat = this._getInternalFormat(format);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
             this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY === undefined ? 1 : (invertY ? 1 : 0));
 
             if (texture._width % 4 !== 0) {
@@ -1735,7 +1736,7 @@
             if (texture.generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_2D);
             }
-            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
             this.resetTextureCache();
             texture.isReady = true;
         }
@@ -1749,14 +1750,14 @@
             texture.references = 1;
 
             this.updateRawTexture(texture, data, format, invertY, compression);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
 
             // Filters
             var filters = getSamplingParameters(samplingMode, generateMipMaps, this._gl);
 
             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
             this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
 
             texture.samplingMode = samplingMode;
 
@@ -1794,22 +1795,22 @@
             var filters = getSamplingParameters(samplingMode, texture.generateMipMaps, this._gl);
 
             if (texture.isCube) {
-                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, texture);
+                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, texture);
 
                 this._gl.texParameteri(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_MAG_FILTER, filters.mag);
                 this._gl.texParameteri(this._gl.TEXTURE_CUBE_MAP, this._gl.TEXTURE_MIN_FILTER, filters.min);
-                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
+                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
             } else {
-                this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
 
                 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MAG_FILTER, filters.mag);
                 this._gl.texParameteri(this._gl.TEXTURE_2D, this._gl.TEXTURE_MIN_FILTER, filters.min);
-                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
             }
         }
 
         public updateDynamicTexture(texture: WebGLTexture, canvas: HTMLCanvasElement, invertY: boolean, premulAlpha: boolean = false): void {
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
             this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 1 : 0);
             if (premulAlpha) {
                 this._gl.pixelStorei(this._gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, 1);
@@ -1818,7 +1819,7 @@
             if (texture.generateMipMaps) {
                 this._gl.generateMipmap(this._gl.TEXTURE_2D);
             }
-            this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
             this.resetTextureCache();
             texture.isReady = true;
         }
@@ -1828,7 +1829,7 @@
                 return;
             }
 
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
             this._gl.pixelStorei(this._gl.UNPACK_FLIP_Y_WEBGL, invertY ? 0 : 1); // Video are upside down by default
 
             try {
@@ -1863,7 +1864,7 @@
                     this._gl.generateMipmap(this._gl.TEXTURE_2D);
                 }
 
-                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
                 this.resetTextureCache();
                 texture.isReady = true;
 
@@ -1897,7 +1898,7 @@
             var gl = this._gl;
 
             var texture = gl.createTexture();
-            gl.bindTexture(gl.TEXTURE_2D, texture);
+            this._bindTextureDirectly(gl.TEXTURE_2D, texture);
 
             var width = size.width || size;
             var height = size.height || size;
@@ -1935,7 +1936,7 @@
             }
 
             // Unbind
-            gl.bindTexture(gl.TEXTURE_2D, null);
+            this._bindTextureDirectly(gl.TEXTURE_2D, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
             this.bindUnboundFramebuffer(null);
 
@@ -1980,7 +1981,7 @@
 
             var filters = getSamplingParameters(samplingMode, generateMipMaps, gl);
 
-            gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+            this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
 
             for (var face = 0; face < 6; face++) {
                 gl.texImage2D((gl.TEXTURE_CUBE_MAP_POSITIVE_X + face), 0, gl.RGBA, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
@@ -2003,12 +2004,12 @@
 
             // Mipmaps
             if (texture.generateMipMaps) {
-                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
                 gl.generateMipmap(gl.TEXTURE_CUBE_MAP);
             }
 
             // Unbind
-            gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+            this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
             gl.bindRenderbuffer(gl.RENDERBUFFER, null);
             this.bindUnboundFramebuffer(null);
 
@@ -2041,7 +2042,7 @@
 
                     var loadMipmap = (info.isRGB || info.isLuminance || info.mipmapCount > 1) && !noMipmap;
 
-                    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                    this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
                     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
 
                     Internals.DDSTools.UploadDDSLevels(this._gl, this.getCaps().s3tc, data, info, loadMipmap, 6);
@@ -2055,7 +2056,7 @@
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 
-                    gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+                    this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
 
                     this.resetTextureCache();
 
@@ -2077,7 +2078,7 @@
                         gl.TEXTURE_CUBE_MAP_NEGATIVE_X, gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, gl.TEXTURE_CUBE_MAP_NEGATIVE_Z
                     ];
 
-                    gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                    this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
                     gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
 
                     for (var index = 0; index < faces.length; index++) {
@@ -2094,7 +2095,7 @@
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                     gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
 
-                    gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+                    this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
 
                     this.resetTextureCache();
 
@@ -2155,7 +2156,7 @@
                 height = texture._height;
                 isPot = (Tools.IsExponentOfTwo(width) && Tools.IsExponentOfTwo(height));
 
-                gl.bindTexture(gl.TEXTURE_CUBE_MAP, texture);
+                this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, texture);
                 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 0);
 
                 if (!noMipmap && isPot) {
@@ -2244,7 +2245,7 @@
 
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
                 gl.texParameteri(gl.TEXTURE_CUBE_MAP, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
-                gl.bindTexture(gl.TEXTURE_CUBE_MAP, null);
+                this._bindTextureDirectly(gl.TEXTURE_CUBE_MAP, null);
 
                 texture.isReady = true;
 
@@ -2295,16 +2296,28 @@
             this._currentEffect = null;
         }
 
+        private activateTexture(texture: number): void {
+            if (this._activeTexture !== texture) {
+                this._gl.activeTexture(texture);
+                this._activeTexture = texture;
+            }
+        }
+
+        public _bindTextureDirectly(target: number, texture: WebGLTexture): void
+        {
+            if (this._activeTexturesCache[this._activeTexture] !== texture) {
+                this._gl.bindTexture(target, texture);
+                this._activeTexturesCache[this._activeTexture] = texture;
+            }
+        }
 
         public _bindTexture(channel: number, texture: WebGLTexture): void {
             if (channel < 0) {
                 return;
             }
 
-            this._gl.activeTexture(this._gl["TEXTURE" + channel]);
-            this._gl.bindTexture(this._gl.TEXTURE_2D, texture);
-
-            this._activeTexturesCache[channel] = null;
+            this.activateTexture(this._gl["TEXTURE" + channel]);
+            this._bindTextureDirectly(this._gl.TEXTURE_2D, texture);
         }
 
         public setTextureFromPostProcess(channel: number, postProcess: PostProcess): void {
@@ -2313,10 +2326,9 @@
 
         public unbindAllTextures(): void {
             for (var channel = 0; channel < this._caps.maxTexturesImageUnits; channel++) {
-                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
-                this._gl.bindTexture(this._gl.TEXTURE_2D, null);
-                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
-                this._activeTexturesCache[channel] = null;
+                this.activateTexture(this._gl["TEXTURE" + channel]);
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
             }
         }
 
@@ -2327,10 +2339,9 @@
             // Not ready?
             if (!texture || !texture.isReady()) {
                 if (this._activeTexturesCache[channel] != null) {
-                    this._gl.activeTexture(this._gl["TEXTURE" + channel]);
-                    this._gl.bindTexture(this._gl.TEXTURE_2D, null);
-                    this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, null);
-                    this._activeTexturesCache[channel] = null;
+                    this.activateTexture(this._gl["TEXTURE" + channel]);
+                    this._bindTextureDirectly(this._gl.TEXTURE_2D, null);
+                    this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, null);
                 }
                 return;
             }
@@ -2338,7 +2349,7 @@
             // Video
             var alreadyActivated = false;
             if (texture instanceof VideoTexture) {
-                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
+                this.activateTexture(this._gl["TEXTURE" + channel]);
                 alreadyActivated = true;
                 texture.update();
             } else if (texture.delayLoadState === Engine.DELAYLOADSTATE_NOTLOADED) { // Delay loading
@@ -2346,19 +2357,18 @@
                 return;
             }
 
-            if (this._activeTexturesCache[channel] === texture) {
+            var internalTexture = texture.getInternalTexture();
+
+            if (this._activeTexturesCache[channel] === internalTexture) {
                 return;
             }
-            this._activeTexturesCache[channel] = texture;
-
-            var internalTexture = texture.getInternalTexture();
 
             if (!alreadyActivated) {
-                this._gl.activeTexture(this._gl["TEXTURE" + channel]);
+                this.activateTexture(this._gl["TEXTURE" + channel]);
             }
 
             if (internalTexture.isCube) {
-                this._gl.bindTexture(this._gl.TEXTURE_CUBE_MAP, internalTexture);
+                this._bindTextureDirectly(this._gl.TEXTURE_CUBE_MAP, internalTexture);
 
                 if (internalTexture._cachedCoordinatesMode !== texture.coordinatesMode) {
                     internalTexture._cachedCoordinatesMode = texture.coordinatesMode;
@@ -2370,7 +2380,7 @@
 
                 this._setAnisotropicLevel(this._gl.TEXTURE_CUBE_MAP, texture);
             } else {
-                this._gl.bindTexture(this._gl.TEXTURE_2D, internalTexture);
+                this._bindTextureDirectly(this._gl.TEXTURE_2D, internalTexture);
 
                 if (internalTexture._cachedWrapU !== texture.wrapU) {
                     internalTexture._cachedWrapU = texture.wrapU;