Selaa lähdekoodia

PerfCounter now support both Time Monitoring and Counter Monitoring. Time Monitoring is now made by the PerfCounter.

New PerfCounter were added for DrawCalls, TotalMesh/Light/Texture/Materials, etc. with new properties exposed while keeping the current APIs behavior.
nockawa 9 vuotta sitten
vanhempi
commit
91246708ef

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

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

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

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

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

@@ -22,7 +22,7 @@
 
             // Particles
             var activeCamera = this._scene.activeCamera;
-            var beforeParticlesDate = Tools.Now;
+            this._scene._particlesDuration.beginMonitoring();
             for (var particleIndex = 0; particleIndex < this._scene._activeParticleSystems.length; particleIndex++) {
                 var particleSystem = this._scene._activeParticleSystems.data[particleIndex];
 
@@ -37,10 +37,10 @@
                 this._clearDepthBuffer();
 
                 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.updateCounter(Tools.Now - beforeParticlesDate, beforeParticlesDate, false);
+            this._scene._particlesDuration.endMonitoring(false);
         }
 
         private _renderSprites(index: number): void {
@@ -50,7 +50,7 @@
 
             // Sprites       
             var activeCamera = this._scene.activeCamera;
-            var beforeSpritessDate = Tools.Now;
+            this._scene._spritesDuration.beginMonitoring();
             for (var id = 0; id < this._scene.spriteManagers.length; id++) {
                 var spriteManager = this._scene.spriteManagers[id];
 
@@ -59,7 +59,7 @@
                     spriteManager.render();
                 }
             }
-            this._scene._spritesDuration.updateCounter(Tools.Now - beforeSpritessDate, beforeSpritessDate, false);
+            this._scene._spritesDuration.endMonitoring(false);
         }
 
         private _clearDepthBuffer(): void {

+ 63 - 43
src/Tools/babylon.tools.ts

@@ -1022,7 +1022,10 @@
     /**
      * 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 uses the updateCounter() method to update the many statistics.
+     * 
+     * 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 {
         /**
@@ -1061,65 +1064,82 @@
         }
 
         constructor() {
-            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;
+            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;
         }
 
         /**
-         * This method must be called by the implementer of the counter only!
-         * It's used to update the different statistics
-         * @param newValue the new value recorded
-         * @param currentTime the time at which the value was recorded
-         * @param newFrame true by default to monitor a new frame, if false 'newValue' will be added to the current frame
+         * 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 updateCounter(newValue: number, currentTime: number, newFrame: boolean=true) {
+        public fetchNewFrame() {
+            this._totalValueCount++;
+            this._current = 0;
+        }
 
-            // First time init?
-            if (this._lastSecTime === 0) {
-                this._min = this._max = this._current = this._average = this._lastSecAverage = this._totalAccumulated = this._lastSecAccumulated = newValue;
-                if (newFrame) {
-                    this._lastSecTime = currentTime;
-                }
-                this._totalValueCount = this._lastSecValueCount = 1;
-                return;
+        /**
+         * 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();
             }
+        }
 
-            // Min/Max update
-            this._min = Math.min(this._min, newValue);
-            this._max = Math.max(this._max, newValue);
+        /**
+         * Start monitoring this performance counter
+         */
+        public beginMonitoring() {
+            this._startMonitoringTime = Tools.Now;
+        }
 
-            // Update average
+        /**
+         * 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._totalValueCount++;
+                this.fetchNewFrame();
             }
-            this._totalAccumulated += newValue;
+
+            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 (newFrame && ((currentTime - this._lastSecTime) > 1000)) {
+            if ((this._startMonitoringTime - this._lastSecTime) > 1000) {
                 this._lastSecAverage = this._lastSecAccumulated / this._lastSecValueCount;
-                this._lastSecTime = currentTime;
-                this._lastSecAccumulated = newValue;
-                this._lastSecValueCount = 1;
-            } else {
-                this._lastSecAccumulated += newValue;
-                if (newFrame) {
-                    this._lastSecValueCount++;
-                }
+                this._lastSecTime = this._startMonitoringTime;
+                this._lastSecAccumulated = 0;
+                this._lastSecValueCount = 0;
             }
-
-            // Current update
-            this._current = newValue;
         }
 
+        private _startMonitoringTime: number;
         private _min: number;
         private _max: number;
         private _average: number;

+ 7 - 8
src/babylon.engine.ts

@@ -312,7 +312,7 @@
 
         private _loadingScreen: ILoadingScreen;
 
-        private _drawCalls = 0;
+        public  _drawCalls = new PerfCounter();
 
         private _glVersion: string;
         private _glRenderer: string;
@@ -595,12 +595,11 @@
         }
 
         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 {
@@ -1165,7 +1164,7 @@
             // Apply states
             this.applyStates();
 
-            this._drawCalls++;
+            this._drawCalls.addCount(1, false);
             // Render
             var indexFormat = this._uintIndicesCurrentlySet ? this._gl.UNSIGNED_INT : this._gl.UNSIGNED_SHORT;
             var mult = this._uintIndicesCurrentlySet ? 4 : 2;
@@ -1180,7 +1179,7 @@
         public drawPointClouds(verticesStart: number, verticesCount: number, instancesCount?: number): void {
             // Apply states
             this.applyStates();
-            this._drawCalls++;
+            this._drawCalls.addCount(1, false);
 
             if (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 {
             // Apply states
             this.applyStates();
-            this._drawCalls++;
+            this._drawCalls.addCount(1, false);
 
             if (instancesCount) {
                 this._caps.instancedArrays.drawArraysInstancedANGLE(useTriangles ? this._gl.TRIANGLES : this._gl.LINES, verticesStart, verticesCount, instancesCount);

+ 69 - 32
src/babylon.scene.ts

@@ -419,16 +419,24 @@
 
         // Private
         private _engine: Engine;
-        private _totalVertices = 0;
-        public _activeIndices = 0;
-        public _activeParticles = 0;
-        private _lastFrameDuration = new PerfCounter();
+
+        // 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 = 0;
+        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;
         public _cachedMaterial: Material;
 
@@ -445,7 +453,6 @@
         public _activeParticleSystems = new SmartArray<ParticleSystem>(256);
         private _activeSkeletons = new SmartArray<Skeleton>(32);
         private _softwareSkinnedMeshes = new SmartArray<Mesh>(32);
-        public _activeBones = 0;
 
         private _renderingManager: RenderingManager;
         private _physicsEngine: PhysicsEngine;
@@ -584,18 +591,34 @@
         }
 
         public getTotalVertices(): number {
+            return this._totalVertices.current;
+        }
+
+        public get totalVerticesPerfCounter(): PerfCounter {
             return this._totalVertices;
         }
 
         public getActiveIndices(): number {
+            return this._activeIndices.current;
+        }
+
+        public get totalActiveIndicesPerfCounter(): PerfCounter {
             return this._activeIndices;
         }
 
         public getActiveParticles(): number {
+            return this._activeParticles.current;
+        }
+
+        public get activeParticlesPerfCounter(): PerfCounter {
             return this._activeParticles;
         }
 
         public getActiveBones(): number {
+            return this._activeBones.current;
+        }
+
+        public get activeBonesPerfCounter(): PerfCounter {
             return this._activeBones;
         }
 
@@ -649,6 +672,10 @@
         }
 
         public getAnimationRatio(): number {
+            return this._animationRatio.current;
+        }
+
+        public animationRatioPerfCounter(): PerfCounter {
             return this._animationRatio;
         }
 
@@ -1787,7 +1814,7 @@
                     }
 
                     // Dispatch
-                    this._activeIndices += subMesh.indexCount;
+                    this._activeIndices.addCount(subMesh.indexCount, false);
                     this._renderingManager.dispatch(subMesh);
                 }
             }
@@ -1834,7 +1861,7 @@
                     continue;
                 }
 
-                this._totalVertices += mesh.getTotalVertices();
+                this._totalVertices.addCount(mesh.getTotalVertices(), false);
 
                 if (!mesh.isReady() || !mesh.isEnabled()) {
                     continue;
@@ -1866,6 +1893,7 @@
             }
 
             // Particle systems
+            this._particlesDuration.beginMonitoring();
             var beforeParticlesDate = Tools.Now;
             if (this.particlesEnabled) {
                 Tools.StartPerformanceCounter("Particles", this.particleSystems.length > 0);
@@ -1883,7 +1911,7 @@
                 }
                 Tools.EndPerformanceCounter("Particles", this.particleSystems.length > 0);
             }
-            this._particlesDuration.updateCounter(Tools.Now - beforeParticlesDate, null, false);
+            this._particlesDuration.endMonitoring(false);
         }
 
         private _activeMesh(mesh: AbstractMesh): void {
@@ -1954,10 +1982,10 @@
             this.onBeforeCameraRenderObservable.notifyObservers(this.activeCamera);
 
             // Meshes
-            var beforeEvaluateActiveMeshesDate = Tools.Now;
+            this._evaluateActiveMeshesDuration.beginMonitoring();
             Tools.StartPerformanceCounter("Active meshes evaluation");
             this._evaluateActiveMeshes();
-            this._evaluateActiveMeshesDuration.updateCounter(Tools.Now - beforeEvaluateActiveMeshesDate, startTime, false);
+            this._evaluateActiveMeshesDuration.endMonitoring(false);
             Tools.EndPerformanceCounter("Active meshes evaluation");
 
             // Software skinning
@@ -1968,6 +1996,7 @@
             }
 
             // Render targets
+            this._renderTargetsDuration.beginMonitoring();
             var beforeRenderTargetDate = Tools.Now;
             if (this.renderTargetsEnabled && this._renderTargets.length > 0) {
                 this._intermediateRendering = true;
@@ -1986,12 +2015,12 @@
                 this._renderId++;
                 engine.restoreDefaultFramebuffer(); // Restore back buffer
             }
-            this._renderTargetsDuration.updateCounter(Tools.Now - beforeRenderTargetDate, startTime, false);
+            this._renderTargetsDuration.endMonitoring(false);
 
             // Prepare Frame
             this.postProcessManager._prepareFrame();
 
-            var beforeRenderDate = Tools.Now;
+            this._renderDuration.beginMonitoring();
             // Backgrounds
             var layerIndex;
             var layer;
@@ -2044,7 +2073,7 @@
                 engine.setDepthBuffer(true);
             }
 
-            this._renderDuration.updateCounter(Tools.Now - beforeRenderDate, startTime, false);
+            this._renderDuration.endMonitoring(false);
 
             // Finalize frame
             this.postProcessManager._finalizeFrame(camera.isIntermediate);
@@ -2118,17 +2147,17 @@
         }
 
         public render(): void {
-            var startDate = Tools.Now;
-            this._particlesDuration.updateCounter(0, startDate);
-            this._spritesDuration.updateCounter(0, startDate);
-            this._activeParticles = 0;
-            this._renderDuration.updateCounter(0, startDate);
-            this._renderTargetsDuration.updateCounter(0, startDate);
-            this._evaluateActiveMeshesDuration.updateCounter(0, startDate);
-            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.resetCachedMaterial();
 
@@ -2146,7 +2175,7 @@
 
             // Animations
             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();
 
             // Physics
@@ -2160,6 +2189,7 @@
             this.onBeforeRenderObservable.notifyObservers(this);
 
             // Customs render targets
+            this._renderTargetsDuration.beginMonitoring();
             var beforeRenderTargetDate = Tools.Now;
             var engine = this.getEngine();
             var currentActiveCamera = this.activeCamera;
@@ -2192,7 +2222,7 @@
             if (this.customRenderTargets.length > 0) { // Restore back buffer
                 engine.restoreDefaultFramebuffer();
             }
-            this._renderTargetsDuration.updateCounter(Tools.Now - beforeRenderTargetDate, startDate);
+            this._renderTargetsDuration.endMonitoring();
             this.activeCamera = currentActiveCamera;
 
             // Procedural textures
@@ -2277,7 +2307,14 @@
             }
 
             Tools.EndPerformanceCounter("Scene rendering");
-            this._lastFrameDuration.updateCounter(Tools.Now - startDate, 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() {