Skip to content

Commit

Permalink
Fix/stats (#178)
Browse files Browse the repository at this point in the history
* add stats dw and tc panel

* add stats example

* Update StatsSystem.ts

修复开启监控才接入hook的问题
  • Loading branch information
574495412 authored Feb 25, 2022
1 parent 9d30a2d commit f9fb86e
Show file tree
Hide file tree
Showing 6 changed files with 283 additions and 3 deletions.
78 changes: 78 additions & 0 deletions examples/src/stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { RendererSystem } from '@eva/plugin-renderer';
import { Game, GameObject } from '@eva/eva.js';
import { StatsSystem } from '@eva/plugin-stats';
import { Text, TextSystem } from '@eva/plugin-renderer-text';
export const name = 'stats';
export async function init(canvas) {

const game = new Game({
systems: [
//@ts-ignore
new RendererSystem({
canvas,
width: 750,
height: 1000,
}),
//@ts-ignore
new StatsSystem({
show: true,
style: {
x: 0,
y: 0,
width: 20,
height: 12,
},
}),
//@ts-ignore
new TextSystem(),
],
});
// 此处还在考虑如何设置默认场景的宽高
game.scene.transform.size = {
width: 750,
height: 1000,
};

const text = new GameObject('text', {
position: {
x: 0,
y: 0,
},
origin: {
x: 0.5,
y: 0.5,
},
anchor: {
x: 0.5,
y: 0.5,
},
});

text.addComponent(
//@ts-ignore
new Text({
text: '欢迎使用EVA性能监控!',
style: {
fontFamily: 'Arial',
fontSize: 36,
fontStyle: 'italic',
fontWeight: 'bold',
fill: ['#b35d9e', '#84c35f', '#ebe44f'], // gradient
fillGradientType: 1,
fillGradientStops: [0.1, 0.4],
stroke: '#4a1850',
strokeThickness: 5,
dropShadow: true,
dropShadowColor: '#000000',
dropShadowBlur: 4,
dropShadowAngle: Math.PI / 6,
dropShadowDistance: 6,
wordWrap: true,
wordWrapWidth: 400,
breakWords: true,
},
}),
);

game.scene.addChild(text);
}
8 changes: 7 additions & 1 deletion packages/plugin-stats/lib/Stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const Stats = function (style) {

const fpsPanel = addPanel(Stats.Panel('FPS', '#0ff', '#002'));
const msPanel = addPanel(Stats.Panel('MS', '#0f0', '#020'));
const dcPanel = addPanel(Stats.Panel('DrawCall', '#330570', '#A69700'));
const tcPanel = addPanel(Stats.Panel('TC:', '#A62500', '#00B454'));
let memPanel;
// @ts-ignore
if (self.performance && self.performance.memory) {
Expand All @@ -58,12 +60,16 @@ const Stats = function (style) {
beginTime = time || (performance || Date).now();
},

end: function () {
end: function (hook) {
frames++;

const time = (performance || Date).now();

msPanel.update(time - beginTime, 200);
if (hook) {
dcPanel.update(hook.deltaDrawCalls, Math.max(50, hook.maxDeltaDrawCalls));
tcPanel.update(hook.texturesCount, Math.max(20, hook.maxTextureCount));
}

if (time >= prevTime + 1000) {
fpsPanel.update((frames * 1000) / (time - prevTime), 100);
Expand Down
17 changes: 15 additions & 2 deletions packages/plugin-stats/lib/StatsSystem.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { System } from '@eva/eva.js';
import type { RendererSystem } from '@eva/plugin-renderer';
import type { Application } from '@eva/renderer-adapter';
import StatsComponent from './StatsComponent';
import Stats from './Stats';

import { BaseHooks } from './hooks/BaseHooks';
interface StatsParams {
show?: boolean;
style?: {
Expand All @@ -14,13 +16,24 @@ interface StatsParams {

export default class StatsSystem extends System {
static systemName = 'Stats';
public app: Application;
public renderSystem: RendererSystem;
show: boolean = true;
stats;
style;
hook;
component: StatsComponent;
init(param: StatsParams = { show: true }) {
this.show = param.show;
this.style = param.style;
this.renderSystem = this.game.getSystem('Renderer') as RendererSystem;
this.app = this.renderSystem.application;
if (this.app && this.show) {
// @ts-ignore
const gl = this.app.renderer.gl as WebGLRenderingContext;
this.hook = new BaseHooks();
this.hook.attach(gl);
}
}
start() {
if (!this.show) return;
Expand All @@ -32,6 +45,6 @@ export default class StatsSystem extends System {
}
lateUpdate() {
if (!this.show) return;
this.stats && this.stats.end();
this.stats && this.stats.end(this.hook);
}
}
63 changes: 63 additions & 0 deletions packages/plugin-stats/lib/hooks/BaseHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { GLHook } from './GLHook';
import { TextureHook } from './TextureHook';
export class BaseHooks {
protected _drawCalls: number = -1;
protected _maxDeltaDrawCalls: number = -1;
protected glhook?: GLHook;
protected texturehook?: TextureHook;

constructor() {}

public attach(gl: any) {
this.glhook = new GLHook(gl);
this.texturehook = new TextureHook(gl);
}

public get drawCalls(): number {
if (this.glhook && this.glhook.isInit) {
return this.glhook.drawPasses;
}
return -1;
}

public get maxDeltaDrawCalls() {
return this._maxDeltaDrawCalls;
}

public get deltaDrawCalls(): number {
if (this._drawCalls == -1) {
this._drawCalls = this.drawCalls;
return 0;
}

var dc: number = this.drawCalls;
var delta: number = dc - this._drawCalls;
this._drawCalls = dc;

this._maxDeltaDrawCalls = Math.max(this._maxDeltaDrawCalls, delta);
return delta;
}

public get maxTextureCount(): number {
if (this.texturehook && this.texturehook.isInit) return this.texturehook.maxTexturesCount;
return 0;
}

public get texturesCount(): number {
if (this.texturehook && this.texturehook.isInit) return this.texturehook.currentTextureCount;

return 0;
}
public reset(): void {
this._maxDeltaDrawCalls = -1;
this._drawCalls = -1;

if (this.glhook) this.glhook.reset();
if (this.texturehook) this.texturehook.reset();
}

public release(): void {
if (this.glhook) this.glhook.release();
if (this.texturehook) this.texturehook.release();
}
}
52 changes: 52 additions & 0 deletions packages/plugin-stats/lib/hooks/GLHook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@

export class GLHook {

public drawPasses:number = 0;
public isInit:boolean = false;
private realGLDrawElements:Function = function(){};

private gl:any;

constructor(_gl?:any) {

if(_gl){

if(_gl.__proto__.drawElements){
this.gl = _gl;
this.realGLDrawElements = _gl.__proto__.drawElements;

//replace to new function
_gl.__proto__.drawElements = this.fakeGLdrawElements.bind(this);
this.isInit = true;

// console.log("[GLHook] GL was Hooked!");
}

} else {
console.error("[GLHook] GL can't be NULL");
}
}

private fakeGLdrawElements(mode:any, count:any, type:any, offset:any):void {

this.drawPasses ++;
this.realGLDrawElements.call(this.gl, mode, count, type, offset);

}
public reset():void{

this.drawPasses = 0;

}

public release():void{

if(this.isInit){

this.gl.__proto__.drawElements = this.realGLDrawElements;
// console.log("[GLHook] Hook was removed!");
}

this.isInit = false;
}
}
68 changes: 68 additions & 0 deletions packages/plugin-stats/lib/hooks/TextureHook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
export class TextureHook {
public createdTextures: Array<any> = new Array<any>();
public maxTexturesCount: number = 0;

public isInit: boolean = false;
private realGLCreateTexture: Function = function() {};
private realGLDeleteTexture: Function = function() {};

private gl: any;

constructor(_gl?: any) {
if (_gl) {
if (_gl.__proto__.createTexture) {
this.gl = _gl;
this.realGLCreateTexture = _gl.__proto__.createTexture;
this.realGLDeleteTexture = _gl.__proto__.deleteTexture;

//replace to new function
_gl.__proto__.createTexture = this.fakeGLCreateTexture.bind(this);
_gl.__proto__.deleteTexture = this.fakeGLDeleteTexture.bind(this);

this.isInit = true;

// console.log('[TextureHook] GL was Hooked!');
}
} else {
console.error("[TextureHook] GL can't be NULL");
}
}

public get currentTextureCount(): number {
return this.createdTextures.length;
}

public registerTexture(texture: any): void {
this.createdTextures.push(texture); // ++;
this.maxTexturesCount = Math.max(this.createdTextures.length, this.maxTexturesCount);
}

private fakeGLCreateTexture(): any {
var texture = this.realGLCreateTexture.call(this.gl);
this.registerTexture(texture);
return texture;
}

private fakeGLDeleteTexture(texture: any): void {
var index: number = this.createdTextures.indexOf(texture);
if (index > -1) {
this.createdTextures.splice(index, 1);
}

this.realGLDeleteTexture.call(this.gl, texture);
}
public reset(): void {
this.createdTextures = new Array<any>();
this.maxTexturesCount = 0;
}
public release(): void {
if (this.isInit) {
this.gl.__proto__.createTexture = this.realGLCreateTexture;
this.gl.__proto__.deleteTexture = this.realGLDeleteTexture;

console.log('[TextureHook] Hook was removed!');
}

this.isInit = false;
}
}

0 comments on commit f9fb86e

Please sign in to comment.