David Catuhe 7 år sedan
förälder
incheckning
e267c3d499

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 10081 - 10038
dist/preview release/babylon.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 36 - 36
dist/preview release/babylon.js


+ 99 - 9
dist/preview release/babylon.max.js

@@ -11722,6 +11722,8 @@ var BABYLON;
             this.onCanvasBlurObservable.clear();
             this.onCanvasFocusObservable.clear();
             this.onCanvasPointerOutObservable.clear();
+            this.onBeginFrameObservable.clear();
+            this.onEndFrameObservable.clear();
             BABYLON.Effect.ResetCache();
         };
         // Loading screen
@@ -17386,6 +17388,18 @@ var BABYLON;
             */
             this.onMeshRemovedObservable = new BABYLON.Observable();
             /**
+            * An event triggered when render targets are about to be rendered
+            * Can happen multiple times per frame.
+            * @type {BABYLON.Observable}
+            */
+            this.OnBeforeRenderTargetsRenderObservable = new BABYLON.Observable();
+            /**
+            * An event triggered when render targets were rendered.
+            * Can happen multiple times per frame.
+            * @type {BABYLON.Observable}
+            */
+            this.OnAfterRenderTargetsRenderObservable = new BABYLON.Observable();
+            /**
             * An event triggered before calculating deterministic simulation step
             * @type {BABYLON.Observable}
             */
@@ -17534,7 +17548,6 @@ var BABYLON;
             this._activeParticles = new BABYLON.PerfCounter();
             this._interFrameDuration = new BABYLON.PerfCounter();
             this._lastFrameDuration = new BABYLON.PerfCounter();
-            this._renderTargetsDuration = new BABYLON.PerfCounter();
             this._particlesDuration = new BABYLON.PerfCounter();
             this._renderDuration = new BABYLON.PerfCounter();
             this._spritesDuration = new BABYLON.PerfCounter();
@@ -18078,7 +18091,8 @@ var BABYLON;
             return this._activeMeshes;
         };
         Scene.prototype.getRenderTargetsDuration = function () {
-            return this._renderTargetsDuration.current;
+            BABYLON.Tools.Log("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
+            return 0;
         };
         Scene.prototype.getRenderDuration = function () {
             return this._renderDuration.current;
@@ -19725,7 +19739,7 @@ var BABYLON;
                 mesh.applySkeleton(mesh.skeleton);
             }
             // Render targets
-            this._renderTargetsDuration.beginMonitoring();
+            this.OnBeforeRenderTargetsRenderObservable.notifyObservers(this);
             var needsRestoreFrameBuffer = false;
             if (camera.customRenderTargets && camera.customRenderTargets.length > 0) {
                 this._renderTargets.concatWithNoDuplicate(camera.customRenderTargets);
@@ -19772,7 +19786,7 @@ var BABYLON;
             if (needsRestoreFrameBuffer) {
                 engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
-            this._renderTargetsDuration.endMonitoring(false);
+            this.OnAfterRenderTargetsRenderObservable.notifyObservers(this);
             // Prepare Frame
             this.postProcessManager._prepareFrame();
             this._renderDuration.beginMonitoring();
@@ -19909,7 +19923,6 @@ var BABYLON;
             this._spritesDuration.fetchNewFrame();
             this._activeParticles.fetchNewFrame();
             this._renderDuration.fetchNewFrame();
-            this._renderTargetsDuration.fetchNewFrame();
             this._totalVertices.fetchNewFrame();
             this._activeIndices.fetchNewFrame();
             this._activeBones.fetchNewFrame();
@@ -19970,7 +19983,7 @@ var BABYLON;
             // Before render
             this.onBeforeRenderObservable.notifyObservers(this);
             // Customs render targets
-            this._renderTargetsDuration.beginMonitoring();
+            this.OnBeforeRenderTargetsRenderObservable.notifyObservers(this);
             var engine = this.getEngine();
             var currentActiveCamera = this.activeCamera;
             if (this.renderTargetsEnabled) {
@@ -19998,7 +20011,7 @@ var BABYLON;
             if (this.customRenderTargets.length > 0) {
                 engine.restoreDefaultFramebuffer();
             }
-            this._renderTargetsDuration.endMonitoring();
+            this.OnAfterRenderTargetsRenderObservable.notifyObservers(this);
             this.activeCamera = currentActiveCamera;
             // Procedural textures
             if (this.proceduralTexturesEnabled) {
@@ -20284,6 +20297,12 @@ var BABYLON;
             this.onDisposeObservable.clear();
             this.onBeforeRenderObservable.clear();
             this.onAfterRenderObservable.clear();
+            this.OnBeforeRenderTargetsRenderObservable.clear();
+            this.OnAfterRenderTargetsRenderObservable.clear();
+            this.onAfterStepObservable.clear();
+            this.onBeforeStepObservable.clear();
+            this.onBeforeActiveMeshesEvaluationObservable.clear();
+            this.onAfterActiveMeshesEvaluationObservable.clear();
             this.detachControl();
             // Release sounds & sounds tracks
             if (BABYLON.AudioEngine) {
@@ -75078,7 +75097,7 @@ var BABYLON;
         });
         Object.defineProperty(EngineInstrumentation.prototype, "captureGPUFrameTime", {
             /**
-             * Gets the current GPU frame time capture status
+             * Gets the GPU frame time capture status
              */
             get: function () {
                 return this._captureGPUFrameTime;
@@ -75131,7 +75150,7 @@ var BABYLON;
         });
         Object.defineProperty(EngineInstrumentation.prototype, "captureShaderCompilationTime", {
             /**
-             * Gets the perf counter associated with shader compilation
+             * Gets the shader compilation time capture status
              */
             get: function () {
                 return this._captureShaderCompilationTime;
@@ -75188,12 +75207,26 @@ var BABYLON;
      */
     var SceneInstrumentation = /** @class */ (function () {
         function SceneInstrumentation(scene) {
+            var _this = this;
             this.scene = scene;
             this._captureActiveMeshesEvaluationTime = false;
             this._activeMeshesEvaluationTime = new BABYLON.PerfCounter();
+            this._captureRenderTargetsRenderTime = false;
+            this._renderTargetsRenderTime = new BABYLON.PerfCounter();
             // Observers
             this._onBeforeActiveMeshesEvaluationObserver = null;
             this._onAfterActiveMeshesEvaluationObserver = null;
+            this._onBeforeRenderTargetsRenderObserver = null;
+            this._onAfterRenderTargetsRenderObserver = null;
+            this._onBeforeRenderObserver = null;
+            this._onBeforeRenderObserver = scene.onBeforeRenderObservable.add(function () {
+                if (_this._captureActiveMeshesEvaluationTime) {
+                    _this._activeMeshesEvaluationTime.fetchNewFrame();
+                }
+                if (_this._captureRenderTargetsRenderTime) {
+                    _this._renderTargetsRenderTime.fetchNewFrame();
+                }
+            });
         }
         Object.defineProperty(SceneInstrumentation.prototype, "activeMeshesEvaluationTime", {
             // Properties
@@ -75208,6 +75241,12 @@ var BABYLON;
         });
         Object.defineProperty(SceneInstrumentation.prototype, "captureActiveMeshesEvaluationTime", {
             /**
+             * Gets the active meshes evaluation time capture status
+             */
+            get: function () {
+                return this._captureActiveMeshesEvaluationTime;
+            },
+            /**
              * Enable or disable the active meshes evaluation time capture
              */
             set: function (value) {
@@ -75235,11 +75274,62 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(SceneInstrumentation.prototype, "renderTargetsRenderTimeCounter", {
+            /**
+             * Gets the perf counter used for render targets render time
+             */
+            get: function () {
+                return this._renderTargetsRenderTime;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneInstrumentation.prototype, "captureRenderTargetsRenderTime", {
+            /**
+             * Gets the render targets render time capture status
+             */
+            get: function () {
+                return this._captureRenderTargetsRenderTime;
+            },
+            /**
+             * Enable or disable the render targets render time capture
+             */
+            set: function (value) {
+                var _this = this;
+                if (value === this._captureRenderTargetsRenderTime) {
+                    return;
+                }
+                if (value) {
+                    this._onBeforeRenderTargetsRenderObserver = this.scene.OnBeforeRenderTargetsRenderObservable.add(function () {
+                        BABYLON.Tools.StartPerformanceCounter("Render targets rendering");
+                        _this._renderTargetsRenderTime.beginMonitoring();
+                    });
+                    this._onAfterRenderTargetsRenderObserver = this.scene.OnAfterRenderTargetsRenderObservable.add(function () {
+                        BABYLON.Tools.EndPerformanceCounter("Render targets rendering");
+                        _this._renderTargetsRenderTime.endMonitoring(false);
+                    });
+                }
+                else {
+                    this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
+                    this._onBeforeRenderTargetsRenderObserver = null;
+                    this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
+                    this._onAfterRenderTargetsRenderObserver = null;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         SceneInstrumentation.prototype.dispose = function () {
+            this.scene.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
+            this._onBeforeRenderObserver = null;
             this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
             this._onBeforeActiveMeshesEvaluationObserver = null;
             this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
             this._onAfterActiveMeshesEvaluationObserver = null;
+            this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
+            this._onBeforeRenderTargetsRenderObserver = null;
+            this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
+            this._onAfterRenderTargetsRenderObserver = null;
             this.scene = null;
         };
         return SceneInstrumentation;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 10081 - 10038
dist/preview release/babylon.module.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 25 - 25
dist/preview release/babylon.worker.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 8793 - 8763
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 43 - 42
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.js


+ 99 - 9
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.max.js

@@ -11722,6 +11722,8 @@ var BABYLON;
             this.onCanvasBlurObservable.clear();
             this.onCanvasFocusObservable.clear();
             this.onCanvasPointerOutObservable.clear();
+            this.onBeginFrameObservable.clear();
+            this.onEndFrameObservable.clear();
             BABYLON.Effect.ResetCache();
         };
         // Loading screen
@@ -17386,6 +17388,18 @@ var BABYLON;
             */
             this.onMeshRemovedObservable = new BABYLON.Observable();
             /**
+            * An event triggered when render targets are about to be rendered
+            * Can happen multiple times per frame.
+            * @type {BABYLON.Observable}
+            */
+            this.OnBeforeRenderTargetsRenderObservable = new BABYLON.Observable();
+            /**
+            * An event triggered when render targets were rendered.
+            * Can happen multiple times per frame.
+            * @type {BABYLON.Observable}
+            */
+            this.OnAfterRenderTargetsRenderObservable = new BABYLON.Observable();
+            /**
             * An event triggered before calculating deterministic simulation step
             * @type {BABYLON.Observable}
             */
@@ -17534,7 +17548,6 @@ var BABYLON;
             this._activeParticles = new BABYLON.PerfCounter();
             this._interFrameDuration = new BABYLON.PerfCounter();
             this._lastFrameDuration = new BABYLON.PerfCounter();
-            this._renderTargetsDuration = new BABYLON.PerfCounter();
             this._particlesDuration = new BABYLON.PerfCounter();
             this._renderDuration = new BABYLON.PerfCounter();
             this._spritesDuration = new BABYLON.PerfCounter();
@@ -18078,7 +18091,8 @@ var BABYLON;
             return this._activeMeshes;
         };
         Scene.prototype.getRenderTargetsDuration = function () {
-            return this._renderTargetsDuration.current;
+            BABYLON.Tools.Log("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
+            return 0;
         };
         Scene.prototype.getRenderDuration = function () {
             return this._renderDuration.current;
@@ -19725,7 +19739,7 @@ var BABYLON;
                 mesh.applySkeleton(mesh.skeleton);
             }
             // Render targets
-            this._renderTargetsDuration.beginMonitoring();
+            this.OnBeforeRenderTargetsRenderObservable.notifyObservers(this);
             var needsRestoreFrameBuffer = false;
             if (camera.customRenderTargets && camera.customRenderTargets.length > 0) {
                 this._renderTargets.concatWithNoDuplicate(camera.customRenderTargets);
@@ -19772,7 +19786,7 @@ var BABYLON;
             if (needsRestoreFrameBuffer) {
                 engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
-            this._renderTargetsDuration.endMonitoring(false);
+            this.OnAfterRenderTargetsRenderObservable.notifyObservers(this);
             // Prepare Frame
             this.postProcessManager._prepareFrame();
             this._renderDuration.beginMonitoring();
@@ -19909,7 +19923,6 @@ var BABYLON;
             this._spritesDuration.fetchNewFrame();
             this._activeParticles.fetchNewFrame();
             this._renderDuration.fetchNewFrame();
-            this._renderTargetsDuration.fetchNewFrame();
             this._totalVertices.fetchNewFrame();
             this._activeIndices.fetchNewFrame();
             this._activeBones.fetchNewFrame();
@@ -19970,7 +19983,7 @@ var BABYLON;
             // Before render
             this.onBeforeRenderObservable.notifyObservers(this);
             // Customs render targets
-            this._renderTargetsDuration.beginMonitoring();
+            this.OnBeforeRenderTargetsRenderObservable.notifyObservers(this);
             var engine = this.getEngine();
             var currentActiveCamera = this.activeCamera;
             if (this.renderTargetsEnabled) {
@@ -19998,7 +20011,7 @@ var BABYLON;
             if (this.customRenderTargets.length > 0) {
                 engine.restoreDefaultFramebuffer();
             }
-            this._renderTargetsDuration.endMonitoring();
+            this.OnAfterRenderTargetsRenderObservable.notifyObservers(this);
             this.activeCamera = currentActiveCamera;
             // Procedural textures
             if (this.proceduralTexturesEnabled) {
@@ -20284,6 +20297,12 @@ var BABYLON;
             this.onDisposeObservable.clear();
             this.onBeforeRenderObservable.clear();
             this.onAfterRenderObservable.clear();
+            this.OnBeforeRenderTargetsRenderObservable.clear();
+            this.OnAfterRenderTargetsRenderObservable.clear();
+            this.onAfterStepObservable.clear();
+            this.onBeforeStepObservable.clear();
+            this.onBeforeActiveMeshesEvaluationObservable.clear();
+            this.onAfterActiveMeshesEvaluationObservable.clear();
             this.detachControl();
             // Release sounds & sounds tracks
             if (BABYLON.AudioEngine) {
@@ -74754,7 +74773,7 @@ var BABYLON;
         });
         Object.defineProperty(EngineInstrumentation.prototype, "captureGPUFrameTime", {
             /**
-             * Gets the current GPU frame time capture status
+             * Gets the GPU frame time capture status
              */
             get: function () {
                 return this._captureGPUFrameTime;
@@ -74807,7 +74826,7 @@ var BABYLON;
         });
         Object.defineProperty(EngineInstrumentation.prototype, "captureShaderCompilationTime", {
             /**
-             * Gets the perf counter associated with shader compilation
+             * Gets the shader compilation time capture status
              */
             get: function () {
                 return this._captureShaderCompilationTime;
@@ -74864,12 +74883,26 @@ var BABYLON;
      */
     var SceneInstrumentation = /** @class */ (function () {
         function SceneInstrumentation(scene) {
+            var _this = this;
             this.scene = scene;
             this._captureActiveMeshesEvaluationTime = false;
             this._activeMeshesEvaluationTime = new BABYLON.PerfCounter();
+            this._captureRenderTargetsRenderTime = false;
+            this._renderTargetsRenderTime = new BABYLON.PerfCounter();
             // Observers
             this._onBeforeActiveMeshesEvaluationObserver = null;
             this._onAfterActiveMeshesEvaluationObserver = null;
+            this._onBeforeRenderTargetsRenderObserver = null;
+            this._onAfterRenderTargetsRenderObserver = null;
+            this._onBeforeRenderObserver = null;
+            this._onBeforeRenderObserver = scene.onBeforeRenderObservable.add(function () {
+                if (_this._captureActiveMeshesEvaluationTime) {
+                    _this._activeMeshesEvaluationTime.fetchNewFrame();
+                }
+                if (_this._captureRenderTargetsRenderTime) {
+                    _this._renderTargetsRenderTime.fetchNewFrame();
+                }
+            });
         }
         Object.defineProperty(SceneInstrumentation.prototype, "activeMeshesEvaluationTime", {
             // Properties
@@ -74884,6 +74917,12 @@ var BABYLON;
         });
         Object.defineProperty(SceneInstrumentation.prototype, "captureActiveMeshesEvaluationTime", {
             /**
+             * Gets the active meshes evaluation time capture status
+             */
+            get: function () {
+                return this._captureActiveMeshesEvaluationTime;
+            },
+            /**
              * Enable or disable the active meshes evaluation time capture
              */
             set: function (value) {
@@ -74911,11 +74950,62 @@ var BABYLON;
             enumerable: true,
             configurable: true
         });
+        Object.defineProperty(SceneInstrumentation.prototype, "renderTargetsRenderTimeCounter", {
+            /**
+             * Gets the perf counter used for render targets render time
+             */
+            get: function () {
+                return this._renderTargetsRenderTime;
+            },
+            enumerable: true,
+            configurable: true
+        });
+        Object.defineProperty(SceneInstrumentation.prototype, "captureRenderTargetsRenderTime", {
+            /**
+             * Gets the render targets render time capture status
+             */
+            get: function () {
+                return this._captureRenderTargetsRenderTime;
+            },
+            /**
+             * Enable or disable the render targets render time capture
+             */
+            set: function (value) {
+                var _this = this;
+                if (value === this._captureRenderTargetsRenderTime) {
+                    return;
+                }
+                if (value) {
+                    this._onBeforeRenderTargetsRenderObserver = this.scene.OnBeforeRenderTargetsRenderObservable.add(function () {
+                        BABYLON.Tools.StartPerformanceCounter("Render targets rendering");
+                        _this._renderTargetsRenderTime.beginMonitoring();
+                    });
+                    this._onAfterRenderTargetsRenderObserver = this.scene.OnAfterRenderTargetsRenderObservable.add(function () {
+                        BABYLON.Tools.EndPerformanceCounter("Render targets rendering");
+                        _this._renderTargetsRenderTime.endMonitoring(false);
+                    });
+                }
+                else {
+                    this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
+                    this._onBeforeRenderTargetsRenderObserver = null;
+                    this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
+                    this._onAfterRenderTargetsRenderObserver = null;
+                }
+            },
+            enumerable: true,
+            configurable: true
+        });
         SceneInstrumentation.prototype.dispose = function () {
+            this.scene.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
+            this._onBeforeRenderObserver = null;
             this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
             this._onBeforeActiveMeshesEvaluationObserver = null;
             this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
             this._onAfterActiveMeshesEvaluationObserver = null;
+            this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
+            this._onBeforeRenderTargetsRenderObserver = null;
+            this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
+            this._onAfterRenderTargetsRenderObserver = null;
             this.scene = null;
         };
         return SceneInstrumentation;

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 8793 - 8763
dist/preview release/customConfigurations/minimalGLTFViewer/babylon.module.d.ts


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/inspector/babylon.inspector.bundle.js


+ 1 - 1
dist/preview release/inspector/babylon.inspector.js

@@ -3762,7 +3762,7 @@ var INSPECTOR;
                 elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);
                 _this._updatableProperties.push({
                     elem: elemValue,
-                    updateFct: function () { return BABYLON.Tools.Format(_this._scene.getRenderTargetsDuration()); }
+                    updateFct: function () { return BABYLON.Tools.Format(_this._sceneInstrumentation.activeMeshesEvaluationTime.current); }
                 });
                 elemLabel = _this._createStatLabel("Particles", _this._panel);
                 elemValue = INSPECTOR.Helpers.CreateDiv('stat-value', _this._panel);

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
dist/preview release/inspector/babylon.inspector.min.js


+ 23 - 5
inspector/src/tabs/StatsTab.ts

@@ -17,6 +17,7 @@ module INSPECTOR {
         private _updateLoopHandler : any;
 
         private _sceneInstrumentation: BABYLON.SceneInstrumentation;
+        private _engineInstrumentation: BABYLON.EngineInstrumentation;
 
         constructor(tabbar:TabBar, insp:Inspector) {
             super(tabbar, 'Stats');        
@@ -29,6 +30,11 @@ module INSPECTOR {
 
             this._sceneInstrumentation = new BABYLON.SceneInstrumentation(this._scene);
             this._sceneInstrumentation.captureActiveMeshesEvaluationTime = true;
+            this._sceneInstrumentation.captureRenderTargetsRenderTime = true;
+            this._sceneInstrumentation.captureFrameTime = true;
+
+            this._engineInstrumentation = new BABYLON.EngineInstrumentation(this._engine);
+            this._engineInstrumentation.captureGPUFrameTime = true;
 
             // Build the stats panel: a div that will contains all stats
             this._panel             = Helpers.CreateDiv('tab-panel') as HTMLDivElement; 
@@ -136,7 +142,7 @@ module INSPECTOR {
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);
                 this._updatableProperties.push({ 
                     elem:elemValue, 
-                    updateFct:() => { return BABYLON.Tools.Format(this._scene.getRenderTargetsDuration())}
+                    updateFct:() => { return BABYLON.Tools.Format(this._sceneInstrumentation.renderTargetsRenderTimeCounter.current)}
                 });
                 elemLabel = this._createStatLabel("Particles", this._panel);
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);
@@ -160,19 +166,31 @@ module INSPECTOR {
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);
                 this._updatableProperties.push({ 
                     elem:elemValue, 
-                    updateFct:() => { return BABYLON.Tools.Format(this._scene.getLastFrameDuration())}
-                });
+                    updateFct:() => { return BABYLON.Tools.Format(this._sceneInstrumentation.frameTimeCounter.current)}
+                });                
                 elemLabel = this._createStatLabel("Inter-frame", this._panel);
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);
                 this._updatableProperties.push({ 
                     elem:elemValue, 
                     updateFct:() => { return BABYLON.Tools.Format(this._scene.getInterFramePerfCounter())}
-                });                
+                });       
+                elemLabel = this._createStatLabel("GPU Frame time", this._panel);
+                elemValue = Helpers.CreateDiv('stat-value', this._panel);
+                this._updatableProperties.push({ 
+                    elem:elemValue, 
+                    updateFct:() => { return BABYLON.Tools.Format(this._engineInstrumentation.gpuFrameTimeCounter.current * 0.000001)}
+                });                  
+                elemLabel = this._createStatLabel("GPU Frame time (average)", this._panel);
+                elemValue = Helpers.CreateDiv('stat-value', this._panel);
+                this._updatableProperties.push({ 
+                    elem:elemValue, 
+                    updateFct:() => { return BABYLON.Tools.Format(this._engineInstrumentation.gpuFrameTimeCounter.average * 0.000001)}
+                });                                 
                 elemLabel = this._createStatLabel("Potential FPS", this._panel);
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);
                 this._updatableProperties.push({ 
                     elem:elemValue, 
-                    updateFct:() => { return BABYLON.Tools.Format(1000.0 / this._scene.getLastFrameDuration(), 0)}
+                    updateFct:() => { return BABYLON.Tools.Format(1000.0 / this._sceneInstrumentation.frameTimeCounter.current, 0)}
                 });
                 elemLabel = this._createStatLabel("Resolution", this._panel);
                 elemValue = Helpers.CreateDiv('stat-value', this._panel);

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

@@ -1129,7 +1129,7 @@
             this._caps.uintIndices = this._webGLVersion > 1 || this._gl.getExtension('OES_element_index_uint') !== null;
             this._caps.fragmentDepthSupported = this._webGLVersion > 1 || this._gl.getExtension('EXT_frag_depth') !== null;
             this._caps.highPrecisionShaderSupported = true;
-            this._caps.timerQuery = this._gl.getExtension("EXT_disjoint_timer_query") || this._gl.getExtension('EXT_disjoint_timer_query_webgl2');
+            this._caps.timerQuery = this._gl.getExtension('EXT_disjoint_timer_query_webgl2') || this._gl.getExtension("EXT_disjoint_timer_query");
             if (this._caps.timerQuery) {
                 if (this._webGLVersion === 1) {
                     this._gl.getQuery = (<any>this._caps.timerQuery).getQueryEXT.bind(this._caps.timerQuery);
@@ -4842,6 +4842,8 @@
             this.onCanvasBlurObservable.clear();
             this.onCanvasFocusObservable.clear();
             this.onCanvasPointerOutObservable.clear();
+            this.onBeginFrameObservable.clear();
+            this.onEndFrameObservable.clear();
 
             BABYLON.Effect.ResetCache();
         }

+ 2 - 2
src/Instrumentation/babylon.engineInstrumentation.ts

@@ -25,7 +25,7 @@ module BABYLON {
         }
 
         /**
-         * Gets the current GPU frame time capture status
+         * Gets the GPU frame time capture status
          */
         public get captureGPUFrameTime(): boolean {
             return this._captureGPUFrameTime;
@@ -74,7 +74,7 @@ module BABYLON {
         }
 
         /**
-         * Gets the perf counter associated with shader compilation
+         * Gets the shader compilation time capture status
          */
         public get captureShaderCompilationTime(): boolean {
             return this._captureShaderCompilationTime;

+ 113 - 0
src/Instrumentation/babylon.sceneInstrumentation.ts

@@ -6,9 +6,20 @@ module BABYLON {
         private _captureActiveMeshesEvaluationTime = false;
         private _activeMeshesEvaluationTime = new PerfCounter();  
 
+        private _captureRenderTargetsRenderTime = false;
+        private _renderTargetsRenderTime = new PerfCounter();    
+        
+        private _captureFrameTime = false;
+        private _frameTime = new PerfCounter();        
+
         // Observers
         private _onBeforeActiveMeshesEvaluationObserver: Nullable<Observer<Scene>> = null;
         private _onAfterActiveMeshesEvaluationObserver: Nullable<Observer<Scene>> = null;
+        private _onBeforeRenderTargetsRenderObserver: Nullable<Observer<Scene>> = null;
+        private _onAfterRenderTargetsRenderObserver: Nullable<Observer<Scene>> = null;
+
+        private _onBeforeRenderObserver: Nullable<Observer<Scene>> = null;
+        private _onAfterRenderObserver: Nullable<Observer<Scene>> = null;
                 
         // Properties
         /**
@@ -19,6 +30,13 @@ module BABYLON {
         }
 
         /**
+         * Gets the active meshes evaluation time capture status
+         */        
+        public get captureActiveMeshesEvaluationTime(): boolean {
+            return this._captureActiveMeshesEvaluationTime;
+        }        
+
+        /**
          * Enable or disable the active meshes evaluation time capture
          */        
         public set captureActiveMeshesEvaluationTime(value: boolean) {
@@ -44,16 +62,111 @@ module BABYLON {
                 this._onAfterActiveMeshesEvaluationObserver = null;
             }
         }
+
+        /**
+         * Gets the perf counter used for render targets render time
+         */
+        public get renderTargetsRenderTimeCounter(): PerfCounter {
+            return this._renderTargetsRenderTime;
+        }
+
+        /**
+         * Gets the render targets render time capture status
+         */
+        public get captureRenderTargetsRenderTime(): boolean {
+            return this._captureRenderTargetsRenderTime;
+        }        
+
+        /**
+         * Enable or disable the render targets render time capture
+         */        
+        public set captureRenderTargetsRenderTime(value: boolean) {
+            if (value === this._captureRenderTargetsRenderTime) {
+                return;
+            }
+
+            if (value) {
+                this._onBeforeRenderTargetsRenderObserver = this.scene.OnBeforeRenderTargetsRenderObservable.add(()=>{
+                    Tools.StartPerformanceCounter("Render targets rendering");
+                    this._renderTargetsRenderTime.beginMonitoring();
+                });
+
+                this._onAfterRenderTargetsRenderObserver = this.scene.OnAfterRenderTargetsRenderObservable.add(()=>{                    
+                    Tools.EndPerformanceCounter("Render targets rendering");
+                    this._renderTargetsRenderTime.endMonitoring(false);
+                });
+            } else {
+                this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
+                this._onBeforeRenderTargetsRenderObserver = null;
+
+                this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
+                this._onAfterRenderTargetsRenderObserver = null;
+            }
+        }        
+
+        /**
+         * Gets the perf counter used for frame time capture
+         */
+        public get frameTimeCounter(): PerfCounter {
+            return this._frameTime;
+        }               
+       
+        /**
+         * Gets the frame time capture status
+         */        
+        public get captureFrameTime(): boolean {
+            return this._captureFrameTime;
+        }        
+
+        /**
+         * Enable or disable the frame time capture
+         */        
+        public set captureFrameTime(value: boolean) {
+            this._captureFrameTime = value;
+        }          
     
         public constructor(public scene: Scene) {
+            this._onBeforeRenderObserver = scene.onBeforeRenderObservable.add(() => {
+                if (this._captureActiveMeshesEvaluationTime) {
+                    this._activeMeshesEvaluationTime.fetchNewFrame();
+                }
+
+                if (this._captureRenderTargetsRenderTime) {
+                    this._renderTargetsRenderTime.fetchNewFrame();
+                }
+
+                if (this._captureFrameTime) {
+                    Tools.StartPerformanceCounter("Scene rendering");
+                    this._frameTime.beginMonitoring();
+                }           
+            });
+
+            this._onAfterRenderObserver = scene.onAfterRenderObservable.add(() => {
+                if (this._captureFrameTime) {
+                    Tools.EndPerformanceCounter("Scene rendering");
+                    this._frameTime.endMonitoring();                    
+                }
+            });
         }
 
         public dispose() {
+            this.scene.onBeforeRenderObservable.remove(this._onBeforeRenderObserver);
+            this._onBeforeRenderObserver = null;
+
+            this.scene.onAfterRenderObservable.remove(this._onAfterRenderObserver);
+            this._onAfterRenderObserver = null;
+
             this.scene.onBeforeActiveMeshesEvaluationObservable.remove(this._onBeforeActiveMeshesEvaluationObserver);
             this._onBeforeActiveMeshesEvaluationObserver = null;
 
             this.scene.onAfterActiveMeshesEvaluationObservable.remove(this._onAfterActiveMeshesEvaluationObserver);
             this._onAfterActiveMeshesEvaluationObserver = null;
+
+            this.scene.OnBeforeRenderTargetsRenderObservable.remove(this._onBeforeRenderTargetsRenderObserver);
+            this._onBeforeRenderTargetsRenderObserver = null;   
+            
+            this.scene.OnAfterRenderTargetsRenderObservable.remove(this._onAfterRenderTargetsRenderObserver);
+            this._onAfterRenderTargetsRenderObserver = null;            
         
             (<any>this.scene) = null;
         }

+ 34 - 16
src/babylon.scene.ts

@@ -345,6 +345,20 @@
         public onMeshRemovedObservable = new Observable<AbstractMesh>();
 
         /**
+        * An event triggered when render targets are about to be rendered
+        * Can happen multiple times per frame.
+        * @type {BABYLON.Observable}
+        */
+        public OnBeforeRenderTargetsRenderObservable = new Observable<Scene>();
+        
+        /**
+        * An event triggered when render targets were rendered.
+        * Can happen multiple times per frame.
+        * @type {BABYLON.Observable}
+        */
+        public OnAfterRenderTargetsRenderObservable = new Observable<Scene>();      
+
+        /**
         * An event triggered before calculating deterministic simulation step
         * @type {BABYLON.Observable}
         */
@@ -739,8 +753,6 @@
         public _activeIndices = new PerfCounter();
         public _activeParticles = new PerfCounter();
         private _interFrameDuration = new PerfCounter();
-        private _lastFrameDuration = new PerfCounter();
-        private _renderTargetsDuration = new PerfCounter();
         public _particlesDuration = new PerfCounter();
         private _renderDuration = new PerfCounter();
         public _spritesDuration = new PerfCounter();
@@ -993,20 +1005,22 @@
         }
 
         public getLastFrameDuration(): number {
-            return this._lastFrameDuration.current;
+            Tools.Warn("getLastFrameDuration is deprecated. Please use SceneInstrumentation class");
+            return 0;
         }
 
-        public get lastFramePerfCounter(): PerfCounter {
-            return this._lastFrameDuration;
+        public get lastFramePerfCounter(): Nullable<PerfCounter> {
+            Tools.Warn("lastFramePerfCounter is deprecated. Please use SceneInstrumentation class");
+            return null;
         }
 
         public getEvaluateActiveMeshesDuration(): number {
-            Tools.Log("getEvaluateActiveMeshesDuration is deprecated. Please use SceneInstrumentation class");
+            Tools.Warn("getEvaluateActiveMeshesDuration is deprecated. Please use SceneInstrumentation class");
             return 0;
         }
 
         public get evaluateActiveMeshesDurationPerfCounter(): Nullable<PerfCounter> {
-            Tools.Log("evaluateActiveMeshesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
+            Tools.Warn("evaluateActiveMeshesDurationPerfCounter is deprecated. Please use SceneInstrumentation class");
             return null;
         }
         public getActiveMeshes(): SmartArray<AbstractMesh> {
@@ -1014,7 +1028,8 @@
         }
 
         public getRenderTargetsDuration(): number {
-            return this._renderTargetsDuration.current;
+            Tools.Warn("getRenderTargetsDuration is deprecated. Please use SceneInstrumentation class");
+            return 0;            
         }
 
         public getRenderDuration(): number {
@@ -2964,7 +2979,7 @@
             }
 
             // Render targets
-            this._renderTargetsDuration.beginMonitoring();
+            this.OnBeforeRenderTargetsRenderObservable.notifyObservers(this);
             var needsRestoreFrameBuffer = false;
 
             if (camera.customRenderTargets && camera.customRenderTargets.length > 0) {
@@ -3022,7 +3037,7 @@
                 engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
 
-            this._renderTargetsDuration.endMonitoring(false);
+            this.OnAfterRenderTargetsRenderObservable.notifyObservers(this);
 
             // Prepare Frame
             this.postProcessManager._prepareFrame();
@@ -3185,12 +3200,10 @@
             }
 
             this._interFrameDuration.endMonitoring();
-            this._lastFrameDuration.beginMonitoring();
             this._particlesDuration.fetchNewFrame();
             this._spritesDuration.fetchNewFrame();
             this._activeParticles.fetchNewFrame();
             this._renderDuration.fetchNewFrame();
-            this._renderTargetsDuration.fetchNewFrame();
             this._totalVertices.fetchNewFrame();
             this._activeIndices.fetchNewFrame();
             this._activeBones.fetchNewFrame();
@@ -3268,7 +3281,7 @@
             this.onBeforeRenderObservable.notifyObservers(this);
 
             // Customs render targets
-            this._renderTargetsDuration.beginMonitoring();
+            this.OnBeforeRenderTargetsRenderObservable.notifyObservers(this);
             var engine = this.getEngine();
             var currentActiveCamera = this.activeCamera;
             if (this.renderTargetsEnabled) {
@@ -3303,7 +3316,7 @@
                 engine.restoreDefaultFramebuffer();
             }
 
-            this._renderTargetsDuration.endMonitoring();
+            this.OnAfterRenderTargetsRenderObservable.notifyObservers(this);
             this.activeCamera = currentActiveCamera;
 
             // Procedural textures
@@ -3401,8 +3414,7 @@
             }
 
             Tools.EndPerformanceCounter("Scene rendering");
-            this._interFrameDuration.beginMonitoring();           
-            this._lastFrameDuration.endMonitoring();
+            this._interFrameDuration.beginMonitoring();  
             this._activeBones.addCount(0, true);
             this._activeIndices.addCount(0, true);
             this._activeParticles.addCount(0, true);
@@ -3633,6 +3645,12 @@
             this.onDisposeObservable.clear();
             this.onBeforeRenderObservable.clear();
             this.onAfterRenderObservable.clear();
+            this.OnBeforeRenderTargetsRenderObservable.clear();
+            this.OnAfterRenderTargetsRenderObservable.clear();
+            this.onAfterStepObservable.clear();
+            this.onBeforeStepObservable.clear();
+            this.onBeforeActiveMeshesEvaluationObservable.clear();
+            this.onAfterActiveMeshesEvaluationObservable.clear();
 
             this.detachControl();