Переглянути джерело

Moving shader compilation to Promises

David Catuhe 7 роки тому
батько
коміт
426014653a
3 змінених файлів з 129 додано та 108 видалено
  1. 10 0
      src/Engine/babylon.engine.ts
  2. 109 108
      src/Materials/babylon.effect.ts
  3. 10 0
      src/babylon.scene.ts

+ 10 - 0
src/Engine/babylon.engine.ts

@@ -5754,6 +5754,16 @@
             return request;
         }
 
+        public _loadFileAsync(url: string, database?: Database, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
+            return new Promise((resolve, reject) => {
+                this._loadFile(url, (data) => {
+                    resolve(data);
+                }, undefined, database, useArrayBuffer, (request, exception) => {
+                    reject(exception);
+                })
+            });
+        }
+
         private _partialLoadFile(url: string, index: number, loadedFiles: (string | ArrayBuffer)[], scene: Nullable<Scene>, onfinish: (files: (string | ArrayBuffer)[]) => void, onErrorCallBack: Nullable<(message?: string, exception?: any) => void> = null): void {
             var onload = (data: string | ArrayBuffer) => {
                 loadedFiles[index] = data;

+ 109 - 108
src/Materials/babylon.effect.ts

@@ -183,28 +183,36 @@
                 fragmentSource = baseName.fragment || baseName;
             }
 
-            this._loadVertexShader(vertexSource, vertexCode => {
-                this._processIncludes(vertexCode, vertexCodeWithIncludes => {
-                    this._processShaderConversion(vertexCodeWithIncludes, false, migratedVertexCode => {
-                        this._loadFragmentShader(fragmentSource, (fragmentCode) => {
-                            this._processIncludes(fragmentCode, fragmentCodeWithIncludes => {
-                                this._processShaderConversion(fragmentCodeWithIncludes, true, migratedFragmentCode => {
-                                    if (baseName) {
-                                        var vertex = baseName.vertexElement || baseName.vertex || baseName;
-                                        var fragment = baseName.fragmentElement || baseName.fragment || baseName;
-
-                                        this._vertexSourceCode = "#define SHADER_NAME vertex:" + vertex + "\n" + migratedVertexCode;
-                                        this._fragmentSourceCode = "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode;
-                                    } else {
-                                        this._vertexSourceCode = migratedVertexCode;
-                                        this._fragmentSourceCode = migratedFragmentCode;
-                                    }
-                                    this._prepareEffect();
-                                });
-                            });
-                        });
-                    });
-                });
+            let finalVertexCode: string;
+            this._loadVertexShaderAsync(vertexSource)
+            .then((vertexCode) => {
+                return this._processIncludesAsync(vertexCode);
+            })
+            .then((vertexCodeWithIncludes) => {
+                return this._processShaderConversion(vertexCodeWithIncludes, false);
+            })
+            .then((migratedVertexCode) => {
+                finalVertexCode = migratedVertexCode;
+                return this._loadFragmentShaderAsync(fragmentSource);
+            })
+            .then((fragmentCode) => {
+                return this._processIncludesAsync(fragmentCode);
+            })
+            .then((fragmentCodeWithIncludes) => {
+                return this._processShaderConversion(fragmentCodeWithIncludes, true);
+            })
+            .then((migratedFragmentCode) => {
+                if (baseName) {
+                    var vertex = baseName.vertexElement || baseName.vertex || baseName;
+                    var fragment = baseName.fragmentElement || baseName.fragment || baseName;
+
+                    this._vertexSourceCode = "#define SHADER_NAME vertex:" + vertex + "\n" + finalVertexCode;
+                    this._fragmentSourceCode = "#define SHADER_NAME fragment:" + fragment + "\n" + migratedFragmentCode;
+                } else {
+                    this._vertexSourceCode = finalVertexCode;
+                    this._fragmentSourceCode = migratedFragmentCode;
+                }
+                this._prepareEffect(); 
             });
         }
 
@@ -271,27 +279,24 @@
             });
         }
 
-        public _loadVertexShader(vertex: any, callback: (data: any) => void): void {
+        public _loadVertexShaderAsync(vertex: any): Promise<any> {
             if (Tools.IsWindowObjectExist()) {
                 // DOM element ?
                 if (vertex instanceof HTMLElement) {
                     var vertexCode = Tools.GetDOMTextContent(vertex);
-                    callback(vertexCode);
-                    return;
+                    return Promise.resolve(vertexCode);
                 }
             }
 
             // Base64 encoded ?
             if (vertex.substr(0, 7) === "base64:") {
                 var vertexBinary = window.atob(vertex.substr(7));
-                callback(vertexBinary);
-                return;
+                return Promise.resolve(vertexBinary);
             }
 
             // Is in local store ?
             if (Effect.ShadersStore[vertex + "VertexShader"]) {
-                callback(Effect.ShadersStore[vertex + "VertexShader"]);
-                return;
+                return Promise.resolve(Effect.ShadersStore[vertex + "VertexShader"]);
             }
 
             var vertexShaderUrl;
@@ -303,35 +308,31 @@
             }
 
             // Vertex shader
-            this._engine._loadFile(vertexShaderUrl + ".vertex.fx", callback);
+            return this._engine._loadFileAsync(vertexShaderUrl + ".vertex.fx");
         }
 
-        public _loadFragmentShader(fragment: any, callback: (data: any) => void): void {
+        public _loadFragmentShaderAsync(fragment: any): Promise<any>  {
             if (Tools.IsWindowObjectExist()) {
                 // DOM element ?
                 if (fragment instanceof HTMLElement) {
                     var fragmentCode = Tools.GetDOMTextContent(fragment);
-                    callback(fragmentCode);
-                    return;
+                    return Promise.resolve(fragmentCode);
                 }
             }
 
             // Base64 encoded ?
             if (fragment.substr(0, 7) === "base64:") {
                 var fragmentBinary = window.atob(fragment.substr(7));
-                callback(fragmentBinary);
-                return;
+                return Promise.resolve(fragmentBinary);
             }
 
             // Is in local store ?
             if (Effect.ShadersStore[fragment + "PixelShader"]) {
-                callback(Effect.ShadersStore[fragment + "PixelShader"]);
-                return;
+                return Promise.resolve(Effect.ShadersStore[fragment + "PixelShader"]);
             }
 
             if (Effect.ShadersStore[fragment + "FragmentShader"]) {
-                callback(Effect.ShadersStore[fragment + "FragmentShader"]);
-                return;
+                return Promise.resolve(Effect.ShadersStore[fragment + "FragmentShader"]);
             }
 
             var fragmentShaderUrl;
@@ -343,7 +344,7 @@
             }
 
             // Fragment shader
-            this._engine._loadFile(fragmentShaderUrl + ".fragment.fx", callback);
+            return this._engine._loadFileAsync(fragmentShaderUrl + ".fragment.fx");
         }
 
         private _dumpShadersSource(vertexCode: string, fragmentCode: string, defines: string): void {
@@ -375,19 +376,16 @@
             }
         };
 
-        private _processShaderConversion(sourceCode: string, isFragment: boolean, callback: (data: any) => void): void {
-
+        private _processShaderConversion(sourceCode: string, isFragment: boolean): any {
             var preparedSourceCode = this._processPrecision(sourceCode);
 
             if (this._engine.webGLVersion == 1) {
-                callback(preparedSourceCode);
-                return;
+                return preparedSourceCode;
             }
 
             // Already converted
             if (preparedSourceCode.indexOf("#version 3") !== -1) {
-                callback(preparedSourceCode.replace("#version 300 es", ""));
-                return;
+                return preparedSourceCode.replace("#version 300 es", "");
             }
 
             var hasDrawBuffersExtension = preparedSourceCode.search(/#extension.+GL_EXT_draw_buffers.+require/) !== -1;
@@ -416,92 +414,95 @@
                 result = result.replace(/void\s+?main\s*\(/g, (hasDrawBuffersExtension ? "" : "out vec4 glFragColor;\n") + "void main(");
             }
 
-            callback(result);
+            return result;
         }
 
-        private _processIncludes(sourceCode: string, callback: (data: any) => void): void {
-            var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
-            var match = regex.exec(sourceCode);
+        private _processIncludesAsync(sourceCode: string): Promise<any> {
+            return new Promise((resolve, reject) => {
+                var regex = /#include<(.+)>(\((.*)\))*(\[(.*)\])*/g;
+                var match = regex.exec(sourceCode);
 
-            var returnValue = new String(sourceCode);
+                var returnValue = new String(sourceCode);
 
-            while (match != null) {
-                var includeFile = match[1];
+                while (match != null) {
+                    var includeFile = match[1];
 
-                // Uniform declaration
-                if (includeFile.indexOf("__decl__") !== -1) {
-                    includeFile = includeFile.replace(/__decl__/, "");
-                    if (this._engine.supportsUniformBuffers) {
-                        includeFile = includeFile.replace(/Vertex/, "Ubo");
-                        includeFile = includeFile.replace(/Fragment/, "Ubo");
+                    // Uniform declaration
+                    if (includeFile.indexOf("__decl__") !== -1) {
+                        includeFile = includeFile.replace(/__decl__/, "");
+                        if (this._engine.supportsUniformBuffers) {
+                            includeFile = includeFile.replace(/Vertex/, "Ubo");
+                            includeFile = includeFile.replace(/Fragment/, "Ubo");
+                        }
+                        includeFile = includeFile + "Declaration";
                     }
-                    includeFile = includeFile + "Declaration";
-                }
 
-                if (Effect.IncludesShadersStore[includeFile]) {
-                    // Substitution
-                    var includeContent = Effect.IncludesShadersStore[includeFile];
-                    if (match[2]) {
-                        var splits = match[3].split(",");
+                    if (Effect.IncludesShadersStore[includeFile]) {
+                        // Substitution
+                        var includeContent = Effect.IncludesShadersStore[includeFile];
+                        if (match[2]) {
+                            var splits = match[3].split(",");
 
-                        for (var index = 0; index < splits.length; index += 2) {
-                            var source = new RegExp(splits[index], "g");
-                            var dest = splits[index + 1];
+                            for (var index = 0; index < splits.length; index += 2) {
+                                var source = new RegExp(splits[index], "g");
+                                var dest = splits[index + 1];
 
-                            includeContent = includeContent.replace(source, dest);
+                                includeContent = includeContent.replace(source, dest);
+                            }
                         }
-                    }
 
-                    if (match[4]) {
-                        var indexString = match[5];
+                        if (match[4]) {
+                            var indexString = match[5];
 
-                        if (indexString.indexOf("..") !== -1) {
-                            var indexSplits = indexString.split("..");
-                            var minIndex = parseInt(indexSplits[0]);
-                            var maxIndex = parseInt(indexSplits[1]);
-                            var sourceIncludeContent = includeContent.slice(0);
-                            includeContent = "";
+                            if (indexString.indexOf("..") !== -1) {
+                                var indexSplits = indexString.split("..");
+                                var minIndex = parseInt(indexSplits[0]);
+                                var maxIndex = parseInt(indexSplits[1]);
+                                var sourceIncludeContent = includeContent.slice(0);
+                                includeContent = "";
 
-                            if (isNaN(maxIndex)) {
-                                maxIndex = this._indexParameters[indexSplits[1]];
-                            }
+                                if (isNaN(maxIndex)) {
+                                    maxIndex = this._indexParameters[indexSplits[1]];
+                                }
 
-                            for (var i = minIndex; i < maxIndex; i++) {
+                                for (var i = minIndex; i < maxIndex; i++) {
+                                    if (!this._engine.supportsUniformBuffers) {
+                                        // Ubo replacement
+                                        sourceIncludeContent = sourceIncludeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
+                                            return p1 + "{X}";
+                                        });
+                                    }
+                                    includeContent += sourceIncludeContent.replace(/\{X\}/g, i.toString()) + "\n";
+                                }
+                            } else {
                                 if (!this._engine.supportsUniformBuffers) {
                                     // Ubo replacement
-                                    sourceIncludeContent = sourceIncludeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
+                                    includeContent = includeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
                                         return p1 + "{X}";
                                     });
                                 }
-                                includeContent += sourceIncludeContent.replace(/\{X\}/g, i.toString()) + "\n";
+                                includeContent = includeContent.replace(/\{X\}/g, indexString);
                             }
-                        } else {
-                            if (!this._engine.supportsUniformBuffers) {
-                                // Ubo replacement
-                                includeContent = includeContent.replace(/light\{X\}.(\w*)/g, (str: string, p1: string) => {
-                                    return p1 + "{X}";
-                                });
-                            }
-                            includeContent = includeContent.replace(/\{X\}/g, indexString);
                         }
-                    }
 
-                    // Replace
-                    returnValue = returnValue.replace(match[0], includeContent);
-                } else {
-                    var includeShaderUrl = Engine.ShadersRepository + "ShadersInclude/" + includeFile + ".fx";
+                        // Replace
+                        returnValue = returnValue.replace(match[0], includeContent);
+                    } else {
+                        var includeShaderUrl = Engine.ShadersRepository + "ShadersInclude/" + includeFile + ".fx";
 
-                    this._engine._loadFile(includeShaderUrl, (fileContent) => {
-                        Effect.IncludesShadersStore[includeFile] = fileContent as string;
-                        this._processIncludes(<string>returnValue, callback);
-                    });
-                    return;
-                }
-
-                match = regex.exec(sourceCode);
-            }
+                        return this._engine._loadFileAsync(includeShaderUrl)
+                                .then((fileContent) => {
+                                    Effect.IncludesShadersStore[includeFile] = fileContent as string;
+                                    this._processIncludesAsync(<string>returnValue).then((value) => {
+                                        resolve(value)
+                                    });
+                                });
+                    }
 
-            callback(returnValue);
+                    match = regex.exec(sourceCode);
+                }
+                resolve(returnValue);
+            });            
         }
 
         private _processPrecision(source: string): string {

+ 10 - 0
src/babylon.scene.ts

@@ -4814,5 +4814,15 @@
             });
             return request;
         }
+
+        public _loadFileAsync(url: string, useDatabase?: boolean, useArrayBuffer?: boolean): Promise<string | ArrayBuffer> {
+            return new Promise((resolve, reject) => {
+                this._loadFile(url, (data) => {
+                    resolve(data);
+                }, undefined, useDatabase, useArrayBuffer, (request, exception) => {
+                    reject(exception);
+                })
+            });
+        }
     }
 }