Explorar o código

Merge pull request #2962 from sebavan/RebuildProgram

Rebuild program
David Catuhe %!s(int64=7) %!d(string=hai) anos
pai
achega
72a735e85b

+ 1 - 1
materialsLibrary/src/custom/babylon.customMaterial.ts

@@ -2039,7 +2039,7 @@ vColor=color;\n\
             
 
             var fn_afterBind = this._afterBind;
-            this._afterBind = function(m,e){ 
+            this._afterBind = (m,e) => { 
                 this.AttachAfterBind(m,e);
                 try{fn_afterBind(m,e);}catch(e){};
             } ;

+ 28 - 5
src/Engine/babylon.engine.ts

@@ -1,8 +1,12 @@
 module BABYLON {
     var compileShader = (gl: WebGLRenderingContext, source: string, type: string, defines: string, shaderVersion: string): WebGLShader => {
+        return compileRawShader(gl, shaderVersion + (defines ? defines + "\n" : "") + source, type);
+    };
+
+    var compileRawShader = (gl: WebGLRenderingContext, source: string, type: string): WebGLShader => {
         var shader = gl.createShader(type === "vertex" ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER);
 
-        gl.shaderSource(shader, shaderVersion + (defines ? defines + "\n" : "") + source);
+        gl.shaderSource(shader, source);
         gl.compileShader(shader);
 
         if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
@@ -2298,9 +2302,15 @@
         public _releaseEffect(effect: Effect): void {
             if (this._compiledEffects[effect._key]) {
                 delete this._compiledEffects[effect._key];
-                if (effect.getProgram()) {
-                    this._gl.deleteProgram(effect.getProgram());
-                }
+
+                this._deleteProgram(effect.getProgram());
+            }
+        }
+
+        public _deleteProgram(program: WebGLProgram): void {
+            if (program) {
+                program.__SPECTOR_rebuildProgram = null;
+                this._gl.deleteProgram(program);
             }
         }
 
@@ -2343,6 +2353,15 @@
                 ["diffuseSampler"].concat(samplers), defines, fallbacks, onCompiled, onError);
         }
 
+        public createRawShaderProgram(vertexCode: string, fragmentCode: string, context?: WebGLRenderingContext): WebGLProgram {
+            context = context || this._gl;
+
+            var vertexShader = compileRawShader(context, vertexCode, "vertex");
+            var fragmentShader = compileRawShader(context, fragmentCode, "fragment");
+
+            return this._createShaderProgram(vertexShader, fragmentShader, context);
+        }
+
         public createShaderProgram(vertexCode: string, fragmentCode: string, defines: string, context?: WebGLRenderingContext): WebGLProgram {
             context = context || this._gl;
 
@@ -2350,6 +2369,10 @@
             var vertexShader = compileShader(context, vertexCode, "vertex", defines, shaderVersion);
             var fragmentShader = compileShader(context, fragmentCode, "fragment", defines, shaderVersion);
 
+            return this._createShaderProgram(vertexShader, fragmentShader, context);
+        }
+
+        private _createShaderProgram(vertexShader: WebGLShader, fragmentShader: WebGLShader, context?: WebGLRenderingContext): WebGLProgram {
             var shaderProgram = context.createProgram();
             context.attachShader(shaderProgram, vertexShader);
             context.attachShader(shaderProgram, fragmentShader);
@@ -4388,7 +4411,7 @@
 
         public releaseEffects() {
             for (var name in this._compiledEffects) {
-                this._gl.deleteProgram(this._compiledEffects[name]._program);
+                this._deleteProgram(this._compiledEffects[name]._program)
             }
 
             this._compiledEffects = {};

+ 3 - 1
src/Engine/babylon.nullEngine.ts

@@ -107,7 +107,9 @@
         }
 
         public createShaderProgram(vertexCode: string, fragmentCode: string, defines: string, context?: WebGLRenderingContext): WebGLProgram {
-            return {};
+            return {
+                __SPECTOR_rebuildProgram: undefined,
+            };
         }
 
         public getUniforms(shaderProgram: WebGLProgram, uniformsNames: string[]): WebGLUniformLocation[] {

+ 48 - 1
src/Materials/babylon.effect.ts

@@ -114,6 +114,8 @@
         private _fallbacks: EffectFallbacks;
         private _vertexSourceCode: string;
         private _fragmentSourceCode: string;
+        private _vertexSourceCodeOverride: string;
+        private _fragmentSourceCodeOverride: string;
 
         public _program: WebGLProgram;
         private _valueCache: { [key: string]: any };
@@ -516,15 +518,48 @@
             return source;
         }
 
+        public _rebuildProgram(vertexSourceCode: string, fragmentSourceCode: string, onCompiled: (program: WebGLProgram) => void, onError: (message: string) => void) {
+            this._isReady = false;
+
+            this._vertexSourceCodeOverride = vertexSourceCode;
+            this._fragmentSourceCodeOverride = fragmentSourceCode;
+            this.onError = (effect, error) => {
+                if (onError) {
+                    onError(error);
+                }
+            };
+            this.onCompiled = () => {
+                var scenes = this.getEngine().scenes;
+                for (var i = 0; i < scenes.length; i++) {
+                    scenes[i].markAllMaterialsAsDirty(Material.TextureDirtyFlag);
+                }
+
+                if (onCompiled) {
+                    onCompiled(this._program);
+                }
+            };
+            this._fallbacks = null;
+            this._prepareEffect();
+        }
+
         public _prepareEffect() {
             let attributesNames = this._attributesNames;
             let defines = this.defines;
             let fallbacks = this._fallbacks;
             this._valueCache = {};
 
+            var previousProgram = this._program;
+
             try {
                 var engine = this._engine;
-                this._program = engine.createShaderProgram(this._vertexSourceCode, this._fragmentSourceCode, defines);
+
+                if (this._vertexSourceCodeOverride && this._fragmentSourceCodeOverride) {
+                    this._program = engine.createRawShaderProgram(this._vertexSourceCodeOverride, this._fragmentSourceCodeOverride);
+                }
+                else {
+                    this._program = engine.createShaderProgram(this._vertexSourceCode, this._fragmentSourceCode, defines);
+                }
+                this._program.__SPECTOR_rebuildProgram = this._rebuildProgram.bind(this);
 
                 if (engine.webGLVersion > 1) {
                     for (var name in this._uniformBuffersNames) {
@@ -559,6 +594,10 @@
                 if (this._fallbacks) {
                     this._fallbacks.unBindMesh();
                 }
+
+                if (previousProgram) {
+                    this.getEngine()._deleteProgram(previousProgram);
+                }
             } catch (e) {
                 this._compilationError = e.message;
 
@@ -572,6 +611,14 @@
                 }));
                 this._dumpShadersSource(this._vertexSourceCode, this._fragmentSourceCode, defines);
                 Tools.Error("Error: " + this._compilationError);
+                if (previousProgram) {
+                    this._program = previousProgram;
+                    this._isReady = true;
+                    if (this.onError) {
+                        this.onError(this, this._compilationError);
+                    }
+                    this.onErrorObservable.notifyObservers(this);
+                }
 
                 if (fallbacks && fallbacks.isMoreFallbacks) {
                     Tools.Error("Trying next fallback.");

+ 4 - 0
src/babylon.mixins.ts

@@ -118,6 +118,10 @@ interface WebGLBuffer {
     is32Bits: boolean;
 }
 
+interface WebGLProgram {
+    __SPECTOR_rebuildProgram(vertexSourceCode: string, fragmentSourceCode: string, onCompiled: (program: WebGLProgram) => void, onError: (message: string) => void): void;
+}
+
 interface MouseEvent {
     mozMovementX: number;
     mozMovementY: number;