浏览代码

Merge pull request #1214 from nockawa/PerfMetrics

Tools and rendering improvement with PerfCounter
David Catuhe 9 年之前
父节点
当前提交
55d7aa5313

+ 1 - 0
dist/preview release/what's new.md

@@ -9,6 +9,7 @@
 - MapTexture: add `supersample` mode to double font quality. ([nockawa](https://github.com/nockawa))
 - MapTexture: add `supersample` mode to double font quality. ([nockawa](https://github.com/nockawa))
 - new `invertUV` parameter an all ribbon based shapes : ribbon, tube, lathe, basic and custom extrusion
 - new `invertUV` parameter an all ribbon based shapes : ribbon, tube, lathe, basic and custom extrusion
 - Text2D: new `fontSuperSample` setting to use high quality font.
 - Text2D: new `fontSuperSample` setting to use high quality font.
+- PerfCounter class added to monitor time/counter and expose min/max/average/lastSecondAverage/current metrics. Updated engine/scene current counter to use this class, exposing new properties as well to access the PerfCounter object. ([nockawa](https://github.com/nockawa))
 
 
 ### Exporters
 ### Exporters
     
     

+ 1 - 1
src/Bones/babylon.skeleton.ts

@@ -258,7 +258,7 @@
 
 
             this._isDirty = false;
             this._isDirty = false;
 
 
-            this._scene._activeBones += this.bones.length;
+            this._scene._activeBones.addCount(this.bones.length, false);
         }
         }
 
 
         public getAnimatables(): IAnimatable[] {
         public getAnimatables(): IAnimatable[] {

+ 1 - 1
src/Materials/Textures/babylon.renderTargetTexture.ts

@@ -254,7 +254,7 @@
 
 
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                         for (var subIndex = 0; subIndex < mesh.subMeshes.length; subIndex++) {
                             var subMesh = mesh.subMeshes[subIndex];
                             var subMesh = mesh.subMeshes[subIndex];
-                            scene._activeIndices += subMesh.indexCount;
+                            scene._activeIndices.addCount(subMesh.indexCount, false);
                             this._renderingManager.dispatch(subMesh);
                             this._renderingManager.dispatch(subMesh);
                         }
                         }
                     }
                     }

+ 5 - 5
src/Rendering/babylon.renderingManager.ts

@@ -22,7 +22,7 @@
 
 
             // Particles
             // Particles
             var activeCamera = this._scene.activeCamera;
             var activeCamera = this._scene.activeCamera;
-            var beforeParticlesDate = Tools.Now;
+            this._scene._particlesDuration.beginMonitoring();
             for (var particleIndex = 0; particleIndex < this._scene._activeParticleSystems.length; particleIndex++) {
             for (var particleIndex = 0; particleIndex < this._scene._activeParticleSystems.length; particleIndex++) {
                 var particleSystem = this._scene._activeParticleSystems.data[particleIndex];
                 var particleSystem = this._scene._activeParticleSystems.data[particleIndex];
 
 
@@ -37,10 +37,10 @@
                 this._clearDepthBuffer();
                 this._clearDepthBuffer();
 
 
                 if (!particleSystem.emitter.position || !activeMeshes || activeMeshes.indexOf(particleSystem.emitter) !== -1) {
                 if (!particleSystem.emitter.position || !activeMeshes || activeMeshes.indexOf(particleSystem.emitter) !== -1) {
-                    this._scene._activeParticles += particleSystem.render();
+                    this._scene._activeParticles.addCount(particleSystem.render(), false);
                 }
                 }
             }
             }
-            this._scene._particlesDuration += Tools.Now - beforeParticlesDate;
+            this._scene._particlesDuration.endMonitoring(false);
         }
         }
 
 
         private _renderSprites(index: number): void {
         private _renderSprites(index: number): void {
@@ -50,7 +50,7 @@
 
 
             // Sprites       
             // Sprites       
             var activeCamera = this._scene.activeCamera;
             var activeCamera = this._scene.activeCamera;
-            var beforeSpritessDate = Tools.Now;
+            this._scene._spritesDuration.beginMonitoring();
             for (var id = 0; id < this._scene.spriteManagers.length; id++) {
             for (var id = 0; id < this._scene.spriteManagers.length; id++) {
                 var spriteManager = this._scene.spriteManagers[id];
                 var spriteManager = this._scene.spriteManagers[id];
 
 
@@ -59,7 +59,7 @@
                     spriteManager.render();
                     spriteManager.render();
                 }
                 }
             }
             }
-            this._scene._spritesDuration += Tools.Now - beforeSpritessDate;
+            this._scene._spritesDuration.endMonitoring(false);
         }
         }
 
 
         private _clearDepthBuffer(): void {
         private _clearDepthBuffer(): void {

+ 133 - 0
src/Tools/babylon.tools.ts

@@ -1020,6 +1020,139 @@
     }
     }
 
 
     /**
     /**
+     * This class is used to track a performance counter which is number based.
+     * The user has access to many properties which give statistics of different nature
+     * 
+     * The implementer can track two kinds of Performance Counter: time and count
+     * For time you can optionally call fetchNewFrame() to notify the start of a new frame to monitor, then call beginMonitoring() to start and endMonitoring() to record the lapsed time. endMonitoring takes a newFrame parameter for you to specify if the monitored time should be set for a new frame or accumulated to the current frame being monitored.
+     * For count you first have to call fetchNewFrame() to notify the start of a new frame to monitor, then call addCount() how many time required to increment the count value you monitor.
+     */
+    export class PerfCounter {
+        /**
+         * Returns the smallest value ever
+         */
+        public get min(): number {
+            return this._min;
+        }
+
+        /**
+         * Returns the biggest value ever
+         */
+        public get max(): number {
+            return this._max;
+        }
+
+        /**
+         * Returns the average value since the performance counter is running
+         */
+        public get average(): number {
+            return this._average;
+        }
+
+        /**
+         * Returns the average value of the last second the counter was monitored
+         */
+        public get lastSecAverage(): number {
+            return this._lastSecAverage;
+        }
+
+        /**
+         * Returns the current value
+         */
+        public get current(): number {
+            return this._current;
+        }
+
+        constructor() {
+            this._startMonitoringTime = 0;
+            this._min                 = 0;
+            this._max                 = 0;
+            this._average             = 0;
+            this._lastSecAverage      = 0;
+            this._current             = 0;
+            this._totalValueCount     = 0;
+            this._totalAccumulated    = 0;
+            this._lastSecAccumulated  = 0;
+            this._lastSecTime         = 0;
+            this._lastSecValueCount   = 0;
+        }
+
+        /**
+         * Call this method to start monitoring a new frame.
+         * This scenario is typically used when you accumulate monitoring time many times for a single frame, you call this method at the start of the frame, then beginMonitoring to start recording and endMonitoring(false) to accumulated the recorded time to the PerfCounter or addCount() to accumulate a monitored count.
+         */
+        public fetchNewFrame() {
+            this._totalValueCount++;
+            this._current = 0;
+        }
+
+        /**
+         * Call this method to monitor a count of something (e.g. mesh drawn in viewport count)
+         * @param newCount the count value to add to the monitored count
+         * @param fetchResult true when it's the last time in the frame you add to the counter and you wish to update the statistics properties (min/max/average), false if you only want to update statistics.
+         */
+        public addCount(newCount: number, fetchResult: boolean) {
+            this._current += newCount;
+            if (fetchResult) {
+                this._fetchResult();
+            }
+        }
+
+        /**
+         * Start monitoring this performance counter
+         */
+        public beginMonitoring() {
+            this._startMonitoringTime = Tools.Now;
+        }
+
+        /**
+         * Compute the time lapsed since the previous beginMonitoring() call.
+         * @param newFrame true by default to fetch the result and monitor a new frame, if false the time monitored will be added to the current frame counter
+         */
+        public endMonitoring(newFrame: boolean = true) {
+            if (newFrame) {
+                this.fetchNewFrame();
+            }
+
+            let currentTime = Tools.Now;
+            this._current = currentTime - this._startMonitoringTime;
+
+            if (newFrame) {
+                this._fetchResult();
+            }
+        }
+
+        private _fetchResult() {
+            this._totalAccumulated += this._current;
+
+            // Min/Max update
+            this._min = Math.min(this._min, this._current);
+            this._max = Math.max(this._max, this._current);
+            this._average = this._totalAccumulated / this._totalValueCount;
+
+            // Reset last sec?
+            if ((this._startMonitoringTime - this._lastSecTime) > 1000) {
+                this._lastSecAverage = this._lastSecAccumulated / this._lastSecValueCount;
+                this._lastSecTime = this._startMonitoringTime;
+                this._lastSecAccumulated = 0;
+                this._lastSecValueCount = 0;
+            }
+        }
+
+        private _startMonitoringTime: number;
+        private _min: number;
+        private _max: number;
+        private _average: number;
+        private _current: number;
+        private _totalValueCount: number;
+        private _totalAccumulated: number;
+        private _lastSecAverage: number;
+        private _lastSecAccumulated: number;
+        private _lastSecTime: number;
+        private _lastSecValueCount: number;
+    }
+
+    /**
      * Use this className as a decorator on a given class definition to add it a name.
      * Use this className as a decorator on a given class definition to add it a name.
      * You can then use the Tools.getClassName(obj) on an instance to retrieve its class name.
      * You can then use the Tools.getClassName(obj) on an instance to retrieve its class name.
      * This method is the only way to get it done in all cases, even if the .js file declaring the class is minified
      * This method is the only way to get it done in all cases, even if the .js file declaring the class is minified

+ 7 - 8
src/babylon.engine.ts

@@ -312,7 +312,7 @@
 
 
         private _loadingScreen: ILoadingScreen;
         private _loadingScreen: ILoadingScreen;
 
 
-        private _drawCalls = 0;
+        public  _drawCalls = new PerfCounter();
 
 
         private _glVersion: string;
         private _glVersion: string;
         private _glRenderer: string;
         private _glRenderer: string;
@@ -595,12 +595,11 @@
         }
         }
 
 
         public get drawCalls(): number {
         public get drawCalls(): number {
-            return this._drawCalls;
+            return this._drawCalls.current;
         }
         }
 
 
-        // Methods
-        public resetDrawCalls(): void {
-            this._drawCalls = 0;
+        public get drawCallsPerfCounter(): PerfCounter {
+            return this._drawCalls;
         }
         }
 
 
         public getDepthFunction(): number {
         public getDepthFunction(): number {
@@ -1165,7 +1164,7 @@
             // Apply states
             // Apply states
             this.applyStates();
             this.applyStates();
 
 
-            this._drawCalls++;
+            this._drawCalls.addCount(1, false);
             // Render
             // Render
             var indexFormat = this._uintIndicesCurrentlySet ? this._gl.UNSIGNED_INT : this._gl.UNSIGNED_SHORT;
             var indexFormat = this._uintIndicesCurrentlySet ? this._gl.UNSIGNED_INT : this._gl.UNSIGNED_SHORT;
             var mult = this._uintIndicesCurrentlySet ? 4 : 2;
             var mult = this._uintIndicesCurrentlySet ? 4 : 2;
@@ -1180,7 +1179,7 @@
         public drawPointClouds(verticesStart: number, verticesCount: number, instancesCount?: number): void {
         public drawPointClouds(verticesStart: number, verticesCount: number, instancesCount?: number): void {
             // Apply states
             // Apply states
             this.applyStates();
             this.applyStates();
-            this._drawCalls++;
+            this._drawCalls.addCount(1, false);
 
 
             if (instancesCount) {
             if (instancesCount) {
                 this._caps.instancedArrays.drawArraysInstancedANGLE(this._gl.POINTS, verticesStart, verticesCount, instancesCount);
                 this._caps.instancedArrays.drawArraysInstancedANGLE(this._gl.POINTS, verticesStart, verticesCount, instancesCount);
@@ -1193,7 +1192,7 @@
         public drawUnIndexed(useTriangles: boolean, verticesStart: number, verticesCount: number, instancesCount?: number): void {
         public drawUnIndexed(useTriangles: boolean, verticesStart: number, verticesCount: number, instancesCount?: number): void {
             // Apply states
             // Apply states
             this.applyStates();
             this.applyStates();
-            this._drawCalls++;
+            this._drawCalls.addCount(1, false);
 
 
             if (instancesCount) {
             if (instancesCount) {
                 this._caps.instancedArrays.drawArraysInstancedANGLE(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount, instancesCount);
                 this._caps.instancedArrays.drawArraysInstancedANGLE(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount, instancesCount);

+ 92 - 34
src/babylon.scene.ts

@@ -419,16 +419,24 @@
 
 
         // Private
         // Private
         private _engine: Engine;
         private _engine: Engine;
-        private _totalVertices = 0;
-        public _activeIndices = 0;
-        public _activeParticles = 0;
-        private _lastFrameDuration = 0;
-        private _evaluateActiveMeshesDuration = 0;
-        private _renderTargetsDuration = 0;
-        public _particlesDuration = 0;
-        private _renderDuration = 0;
-        public _spritesDuration = 0;
-        private _animationRatio = 0;
+
+        // Performance counters
+        private _totalMeshesCounter           = new PerfCounter();
+        private _totalLightsCounter           = new PerfCounter();
+        private _totalMaterialsCounter        = new PerfCounter();
+        private _totalTexturesCounter         = new PerfCounter();
+        private _totalVertices                = new PerfCounter();
+        public  _activeIndices                = new PerfCounter();
+        public  _activeParticles              = new PerfCounter();
+        private _lastFrameDuration            = new PerfCounter();
+        private _evaluateActiveMeshesDuration = new PerfCounter();
+        private _renderTargetsDuration        = new PerfCounter();
+        public  _particlesDuration            = new PerfCounter();
+        private _renderDuration               = new PerfCounter();
+        public  _spritesDuration              = new PerfCounter();
+        private _animationRatio               = new PerfCounter();
+        public  _activeBones                  = new PerfCounter();
+
         private _animationStartDate: number;
         private _animationStartDate: number;
         public _cachedMaterial: Material;
         public _cachedMaterial: Material;
 
 
@@ -445,7 +453,6 @@
         public _activeParticleSystems = new SmartArray<ParticleSystem>(256);
         public _activeParticleSystems = new SmartArray<ParticleSystem>(256);
         private _activeSkeletons = new SmartArray<Skeleton>(32);
         private _activeSkeletons = new SmartArray<Skeleton>(32);
         private _softwareSkinnedMeshes = new SmartArray<Mesh>(32);
         private _softwareSkinnedMeshes = new SmartArray<Mesh>(32);
-        public _activeBones = 0;
 
 
         private _renderingManager: RenderingManager;
         private _renderingManager: RenderingManager;
         private _physicsEngine: PhysicsEngine;
         private _physicsEngine: PhysicsEngine;
@@ -584,27 +591,51 @@
         }
         }
 
 
         public getTotalVertices(): number {
         public getTotalVertices(): number {
+            return this._totalVertices.current;
+        }
+
+        public get totalVerticesPerfCounter(): PerfCounter {
             return this._totalVertices;
             return this._totalVertices;
         }
         }
 
 
         public getActiveIndices(): number {
         public getActiveIndices(): number {
+            return this._activeIndices.current;
+        }
+
+        public get totalActiveIndicesPerfCounter(): PerfCounter {
             return this._activeIndices;
             return this._activeIndices;
         }
         }
 
 
         public getActiveParticles(): number {
         public getActiveParticles(): number {
+            return this._activeParticles.current;
+        }
+
+        public get activeParticlesPerfCounter(): PerfCounter {
             return this._activeParticles;
             return this._activeParticles;
         }
         }
 
 
         public getActiveBones(): number {
         public getActiveBones(): number {
+            return this._activeBones.current;
+        }
+
+        public get activeBonesPerfCounter(): PerfCounter {
             return this._activeBones;
             return this._activeBones;
         }
         }
 
 
         // Stats
         // Stats
         public getLastFrameDuration(): number {
         public getLastFrameDuration(): number {
+            return this._lastFrameDuration.current;
+        }
+
+        public get lastFramePerfCounter(): PerfCounter {
             return this._lastFrameDuration;
             return this._lastFrameDuration;
         }
         }
 
 
         public getEvaluateActiveMeshesDuration(): number {
         public getEvaluateActiveMeshesDuration(): number {
+            return this._evaluateActiveMeshesDuration.current;
+        }
+
+        public get evaluateActiveMeshesDurationPerfCounter(): PerfCounter {
             return this._evaluateActiveMeshesDuration;
             return this._evaluateActiveMeshesDuration;
         }
         }
 
 
@@ -613,22 +644,38 @@
         }
         }
 
 
         public getRenderTargetsDuration(): number {
         public getRenderTargetsDuration(): number {
-            return this._renderTargetsDuration;
+            return this._renderTargetsDuration.current;
         }
         }
 
 
         public getRenderDuration(): number {
         public getRenderDuration(): number {
+            return this._renderDuration.current;
+        }
+
+        public get renderDurationPerfCounter(): PerfCounter {
             return this._renderDuration;
             return this._renderDuration;
         }
         }
 
 
         public getParticlesDuration(): number {
         public getParticlesDuration(): number {
+            return this._particlesDuration.current;
+        }
+
+        public get particlesDurationPerfCounter(): PerfCounter {
             return this._particlesDuration;
             return this._particlesDuration;
         }
         }
 
 
         public getSpritesDuration(): number {
         public getSpritesDuration(): number {
+            return this._spritesDuration.current;
+        }
+
+        public get spriteDuractionPerfCounter(): PerfCounter {
             return this._spritesDuration;
             return this._spritesDuration;
         }
         }
 
 
         public getAnimationRatio(): number {
         public getAnimationRatio(): number {
+            return this._animationRatio.current;
+        }
+
+        public animationRatioPerfCounter(): PerfCounter {
             return this._animationRatio;
             return this._animationRatio;
         }
         }
 
 
@@ -1774,7 +1821,7 @@
                     }
                     }
 
 
                     // Dispatch
                     // Dispatch
-                    this._activeIndices += subMesh.indexCount;
+                    this._activeIndices.addCount(subMesh.indexCount, false);
                     this._renderingManager.dispatch(subMesh);
                     this._renderingManager.dispatch(subMesh);
                 }
                 }
             }
             }
@@ -1815,7 +1862,7 @@
                     continue;
                     continue;
                 }
                 }
 
 
-                this._totalVertices += mesh.getTotalVertices();
+                this._totalVertices.addCount(mesh.getTotalVertices(), false);
 
 
                 if (!mesh.isReady() || !mesh.isEnabled()) {
                 if (!mesh.isReady() || !mesh.isEnabled()) {
                     continue;
                     continue;
@@ -1847,6 +1894,7 @@
             }
             }
 
 
             // Particle systems
             // Particle systems
+            this._particlesDuration.beginMonitoring();
             var beforeParticlesDate = Tools.Now;
             var beforeParticlesDate = Tools.Now;
             if (this.particlesEnabled) {
             if (this.particlesEnabled) {
                 Tools.StartPerformanceCounter("Particles", this.particleSystems.length > 0);
                 Tools.StartPerformanceCounter("Particles", this.particleSystems.length > 0);
@@ -1864,7 +1912,7 @@
                 }
                 }
                 Tools.EndPerformanceCounter("Particles", this.particleSystems.length > 0);
                 Tools.EndPerformanceCounter("Particles", this.particleSystems.length > 0);
             }
             }
-            this._particlesDuration += Tools.Now - beforeParticlesDate;
+            this._particlesDuration.endMonitoring(false);
         }
         }
 
 
         private _activeMesh(mesh: AbstractMesh): void {
         private _activeMesh(mesh: AbstractMesh): void {
@@ -1915,6 +1963,7 @@
 
 
         private _renderForCamera(camera: Camera): void {
         private _renderForCamera(camera: Camera): void {
             var engine = this._engine;
             var engine = this._engine;
+            var startTime = Tools.Now;
 
 
             this.activeCamera = camera;
             this.activeCamera = camera;
 
 
@@ -1934,10 +1983,10 @@
             this.onBeforeCameraRenderObservable.notifyObservers(this.activeCamera);
             this.onBeforeCameraRenderObservable.notifyObservers(this.activeCamera);
 
 
             // Meshes
             // Meshes
-            var beforeEvaluateActiveMeshesDate = Tools.Now;
+            this._evaluateActiveMeshesDuration.beginMonitoring();
             Tools.StartPerformanceCounter("Active meshes evaluation");
             Tools.StartPerformanceCounter("Active meshes evaluation");
             this._evaluateActiveMeshes();
             this._evaluateActiveMeshes();
-            this._evaluateActiveMeshesDuration += Tools.Now - beforeEvaluateActiveMeshesDate;
+            this._evaluateActiveMeshesDuration.endMonitoring(false);
             Tools.EndPerformanceCounter("Active meshes evaluation");
             Tools.EndPerformanceCounter("Active meshes evaluation");
 
 
             // Software skinning
             // Software skinning
@@ -1948,6 +1997,7 @@
             }
             }
 
 
             // Render targets
             // Render targets
+            this._renderTargetsDuration.beginMonitoring();
             var beforeRenderTargetDate = Tools.Now;
             var beforeRenderTargetDate = Tools.Now;
             if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
             if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
                 this._intermediateRendering = true;
                 this._intermediateRendering = true;
@@ -1966,12 +2016,12 @@
                 this._renderId++;
                 this._renderId++;
                 engine.restoreDefaultFramebuffer(); // Restore back buffer
                 engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
             }
-            this._renderTargetsDuration += Tools.Now - beforeRenderTargetDate;
+            this._renderTargetsDuration.endMonitoring(false);
 
 
             // Prepare Frame
             // Prepare Frame
             this.postProcessManager._prepareFrame();
             this.postProcessManager._prepareFrame();
 
 
-            var beforeRenderDate = Tools.Now;
+            this._renderDuration.beginMonitoring();
             // Backgrounds
             // Backgrounds
             var layerIndex;
             var layerIndex;
             var layer;
             var layer;
@@ -2024,7 +2074,7 @@
                 engine.setDepthBuffer(true);
                 engine.setDepthBuffer(true);
             }
             }
 
 
-            this._renderDuration += Tools.Now - beforeRenderDate;
+            this._renderDuration.endMonitoring(false);
 
 
             // Finalize frame
             // Finalize frame
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
@@ -2098,17 +2148,17 @@
         }
         }
 
 
         public render(): void {
         public render(): void {
-            var startDate = Tools.Now;
-            this._particlesDuration = 0;
-            this._spritesDuration = 0;
-            this._activeParticles = 0;
-            this._renderDuration = 0;
-            this._renderTargetsDuration = 0;
-            this._evaluateActiveMeshesDuration = 0;
-            this._totalVertices = 0;
-            this._activeIndices = 0;
-            this._activeBones = 0;
-            this.getEngine().resetDrawCalls();
+            this._lastFrameDuration.beginMonitoring();
+            this._particlesDuration.fetchNewFrame();
+            this._spritesDuration.fetchNewFrame();
+            this._activeParticles.fetchNewFrame();
+            this._renderDuration.fetchNewFrame();
+            this._renderTargetsDuration.fetchNewFrame();
+            this._evaluateActiveMeshesDuration.fetchNewFrame();
+            this._totalVertices.fetchNewFrame();
+            this._activeIndices.fetchNewFrame();
+            this._activeBones.fetchNewFrame();
+            this.getEngine()._drawCalls.fetchNewFrame();;
             this._meshesForIntersections.reset();
             this._meshesForIntersections.reset();
             this.resetCachedMaterial();
             this.resetCachedMaterial();
 
 
@@ -2126,7 +2176,7 @@
 
 
             // Animations
             // Animations
             var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime));
             var deltaTime = Math.max(Scene.MinDeltaTime, Math.min(this._engine.getDeltaTime(), Scene.MaxDeltaTime));
-            this._animationRatio = deltaTime * (60.0 / 1000.0);
+            this._animationRatio.addCount(deltaTime * (60.0 / 1000.0), true);
             this._animate();
             this._animate();
 
 
             // Physics
             // Physics
@@ -2140,6 +2190,7 @@
             this.onBeforeRenderObservable.notifyObservers(this);
             this.onBeforeRenderObservable.notifyObservers(this);
 
 
             // Customs render targets
             // Customs render targets
+            this._renderTargetsDuration.beginMonitoring();
             var beforeRenderTargetDate = Tools.Now;
             var beforeRenderTargetDate = Tools.Now;
             var engine = this.getEngine();
             var engine = this.getEngine();
             var currentActiveCamera = this.activeCamera;
             var currentActiveCamera = this.activeCamera;
@@ -2172,7 +2223,7 @@
             if (this.customRenderTargets.length > 0) { // Restore back buffer
             if (this.customRenderTargets.length > 0) { // Restore back buffer
                 engine.restoreDefaultFramebuffer();
                 engine.restoreDefaultFramebuffer();
             }
             }
-            this._renderTargetsDuration += Tools.Now - beforeRenderTargetDate;
+            this._renderTargetsDuration.endMonitoring();
             this.activeCamera = currentActiveCamera;
             this.activeCamera = currentActiveCamera;
 
 
             // Procedural textures
             // Procedural textures
@@ -2257,7 +2308,14 @@
             }
             }
 
 
             Tools.EndPerformanceCounter("Scene rendering");
             Tools.EndPerformanceCounter("Scene rendering");
-            this._lastFrameDuration = Tools.Now - startDate;
+            this._lastFrameDuration.endMonitoring();
+            this._totalMeshesCounter.addCount(this.meshes.length, true);
+            this._totalLightsCounter.addCount(this.lights.length, true);
+            this._totalMaterialsCounter.addCount(this.materials.length, true);
+            this._totalTexturesCounter.addCount(this.textures.length, true);
+            this._activeBones.addCount(0, true);
+            this._activeIndices.addCount(0, true);
+            this._activeParticles.addCount(0, true);
         }
         }
 
 
         private _updateAudioParameters() {
         private _updateAudioParameters() {