Forráskód Böngészése

Add Rebuild Program Functions

Sebastien Vandenberghe 7 éve
szülő
commit
fb084c671f
2 módosított fájl, 77 hozzáadás és 6 törlés
  1. 49 1
      src/Materials/babylon.effect.ts
  2. 28 5
      src/babylon.engine.ts

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

@@ -89,6 +89,7 @@
     }
 
     export class Effect {
+        public static rebuildProgramFunctionName = "__SPECTOR_rebuildProgram";
         public name: any;
         public defines: string;
         public onCompiled: (effect: Effect) => void;
@@ -114,6 +115,8 @@
         private _fallbacks: EffectFallbacks;
         private _vertexSourceCode: string;
         private _fragmentSourceCode: string;
+        private _vertexSourceCodeOverride: string;
+        private _fragmentSourceCodeOverride: string;
 
         private _program: WebGLProgram;
         private _valueCache: { [key: string]: any };
@@ -512,15 +515,48 @@
             return source;
         }
 
+        public _rebuildProgram(vertexSourceCode: string, fragmentSourceCode: string, onCompiled: (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[Effect.rebuildProgramFunctionName] = this._rebuildProgram.bind(this);
 
                 if (engine.webGLVersion > 1) {
                     for (var name in this._uniformBuffersNames) {
@@ -555,6 +591,10 @@
                 if (this._fallbacks) {
                     this._fallbacks.unBindMesh();
                 }
+
+                if (previousProgram) {
+                    this.getEngine()._deleteProgram(previousProgram);
+                }
             } catch (e) {
                 this._compilationError = e.message;
 
@@ -568,6 +608,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.");

+ 28 - 5
src/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)) {
@@ -2280,9 +2284,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) {
+            if (program) {
+                program[Effect.rebuildProgramFunctionName] = null;
+                this._gl.deleteProgram(program);
             }
         }
 
@@ -2325,6 +2335,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;
 
@@ -2332,6 +2351,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);
@@ -4372,7 +4395,7 @@
 
         public releaseEffects() {
             for (var name in this._compiledEffects) {
-                this._gl.deleteProgram(this._compiledEffects[name]._program);
+                this._deleteProgram(this._compiledEffects[name]._program)
             }
 
             this._compiledEffects = {};