Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: only gather scene updates when needed #50

Merged
merged 1 commit into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions packages/backend/src/assets/gpuTextures/textures.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { TextureDataState } from '@devtool/frontend/pages/assets/assets';
import type { PixiDevtools } from '../../pixi';
import type { TextureSource, GlTexture, CanvasSource, WebGLRenderer, WebGPURenderer } from 'pixi.js';
import type { CanvasSource, GlTexture, TextureSource, WebGLRenderer, WebGPURenderer } from 'pixi.js';
import { PixiHandler } from '../../handler';

const gpuTextureFormatSize: Record<string, number> = {
r8unorm: 1,
Expand Down Expand Up @@ -63,24 +63,22 @@ const glTextureFormatSize: Record<number, number> = {
34041: 2,
};

export class Textures {
private _devtool: typeof PixiDevtools;
export class Textures extends PixiHandler {
private _textures: Map<number, string> = new Map();
private _gpuTextureSize: Map<number, number> = new Map();
private _canvas = document.createElement('canvas');

constructor(devtool: typeof PixiDevtools) {
this._devtool = devtool;
public override init() {
this._textures.clear();
this._gpuTextureSize.clear();
}

public init() {
public override reset() {
this._textures.clear();
this._gpuTextureSize.clear();
}

public update() {}

public complete() {}
public override update() {}

public get() {
const currentTextures = this._devtool.renderer.texture.managedTextures;
Expand Down
17 changes: 17 additions & 0 deletions packages/backend/src/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Container } from 'pixi.js';
import type { PixiDevtools } from './pixi';

export class PixiHandler {
protected _devtool: typeof PixiDevtools;
constructor(devtool: typeof PixiDevtools) {
this._devtool = devtool;
}

public init() {}
public reset() {}
public preupdate() {}
public update() {}
public throttledUpdate() {}
public loop(_container: Container) {}
public postupdate() {}
}
142 changes: 48 additions & 94 deletions packages/backend/src/pixi.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,21 @@
import type { DevtoolState } from '@devtool/frontend/types';
import type { GlobalDevtoolState } from '@devtool/frontend/types';
import { DevtoolMessage } from '@devtool/frontend/types';
import type { Devtools } from '@pixi/devtools';
import type { Application, Container, Renderer, WebGLRenderer } from 'pixi.js';
import { Textures } from './assets/gpuTextures/textures';
import { extensions } from './extensions/Extensions';
import { Overlay } from './scene/overlay/overlay';
import { Rendering } from './rendering/rendering';
import { overlayExtension } from './scene/overlay/overlayExtension';
import { Stats } from './scene/stats/stats';
import { Scene } from './scene/scene';
import { pixiStatsExtension, totalStatsExtension } from './scene/stats/statsExtension';
import { animatedSpritePropertyExtension } from './scene/tree/extensions/animatedSprite/animatedSpritePropertyExtension';
import { containerPropertyExtension } from './scene/tree/extensions/container/containerPropertyExtension';
import { nineSlicePropertyExtension } from './scene/tree/extensions/ninesliceSprite/ninesliceSpritePropertyExtension';
import { textPropertyExtension } from './scene/tree/extensions/text/textPropertyExtension';
import { tilingSpritePropertyExtension } from './scene/tree/extensions/tilingSprite/tilingSpritePropertyExtension';
import { viewPropertyExtension } from './scene/tree/extensions/view/viewPropertyExtension';
import { Properties } from './scene/tree/properties';
import { Tree } from './scene/tree/tree';
import { loop } from './utils/loop';
import { Throttle } from './utils/throttle';
import { Textures } from './assets/gpuTextures/textures';
import type { TextureState } from '@devtool/frontend/pages/assets/assets';
import { Rendering } from './rendering/rendering';
import type { RenderingState } from '@devtool/frontend/pages/rendering/rendering';

/**
* PixiWrapper is a class that wraps around the PixiJS library.
Expand All @@ -31,74 +26,16 @@ class PixiWrapper {
public settings = {
throttle: 100,
};
public state: Omit<
DevtoolState,
| 'active'
| 'setActive'
| 'bridge'
| 'setBridge'
| 'chromeProxy'
| 'setChromeProxy'
| 'reset'
| keyof TextureState
| keyof RenderingState
> = {
public state: Omit<GlobalDevtoolState, 'active' | 'setActive'> = {
version: null,
setVersion: function (version: DevtoolState['version']) {
setVersion: function (version: GlobalDevtoolState['version']) {
this.version = version;
},

sceneGraph: null,
setSceneGraph: function (sceneGraph: DevtoolState['sceneGraph']) {
this.sceneGraph = sceneGraph ?? {
id: 'root',
name: 'root',
children: [],
metadata: {
type: 'Container',
},
};
},

sceneTreeData: {
buttons: [],
},
setSceneTreeData: function (data: DevtoolState['sceneTreeData']) {
this.sceneTreeData = data;
},

stats: null,
setStats: function (stats: DevtoolState['stats']) {
this.stats = stats;
},

selectedNode: null,
setSelectedNode: function (selectedNode: DevtoolState['selectedNode']) {
this.selectedNode = selectedNode;
},

activeProps: [],
setActiveProps: function (activeProps: DevtoolState['activeProps']) {
this.activeProps = activeProps;
},

overlayPickerEnabled: false,
setOverlayPickerEnabled: function (enabled: DevtoolState['overlayPickerEnabled']) {
this.overlayPickerEnabled = enabled;
},

overlayHighlightEnabled: true,
setOverlayHighlightEnabled: function (enabled: DevtoolState['overlayHighlightEnabled']) {
this.overlayHighlightEnabled = enabled;
},
};

public stats = new Stats(this);
public tree = new Tree(this);
public properties = new Properties(this);
public overlay = new Overlay(this);
public textures = new Textures(this);
public rendering = new Rendering(this);
public scene = new Scene(this);
// Private properties
private _devtools: Devtools | undefined;
private _app: Application | undefined;
Expand Down Expand Up @@ -240,6 +177,9 @@ class PixiWrapper {
return this._version;
}

/**
* Gets the major version of PixiJS.
*/
public get majorVersion() {
if (this.version === '') {
if (!this.stage) {
Expand All @@ -264,6 +204,9 @@ class PixiWrapper {
return this.app || (this.stage && this.renderer) ? DevtoolMessage.active : DevtoolMessage.inactive;
}

/**
* Gets the type of renderer being used.
*/
public get rendererType(): 'webgl' | 'webgl2' | 'webgpu' | null {
if (!this.renderer) return null;
return this.renderer.type === 0b10
Expand All @@ -273,6 +216,9 @@ class PixiWrapper {
: 'webgl2';
}

/**
* Inject into the renderers render method.
*/
public inject() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this;
Expand All @@ -295,6 +241,8 @@ class PixiWrapper {
this.renderer && this._originalRenderFn && (this.renderer.render = this._originalRenderFn);
this.renderer && (this.renderer.__devtoolInjected = false);
this.rendering.reset();
this.scene.reset();
this.textures.reset();
this._resetState();
this._devtools = undefined;
this._app = undefined;
Expand All @@ -312,21 +260,17 @@ class PixiWrapper {
this.init();
}

// TODO: tree: 300ms, stats: 300ms, properties: 300ms, overlay: 50ms

this.overlay.update();
this.rendering.update();
this.preupdate();
this._update();
if (this._updateThrottle.shouldExecute(this.settings.throttle)) {
this.preupdate();

this.updatedThrottled();
// check if we are accessing the correct stage
if (this.renderer!.lastObjectRendered === this.stage) {
// loop the scene graph
loop({
container: this.stage!,
loop: (container) => {
this.stats.update(container);
this.tree.update(container);
this.updateLoop(container);
},
test: (container) => {
if (container.__devtoolIgnore) return false;
Expand All @@ -341,36 +285,46 @@ class PixiWrapper {
}

private init() {
this.overlay.init();
this.properties.init();
this.stats.init();
this.tree.init();
this.scene.init();
this.textures.init();
this.rendering.init();
this._initialized = true;
}

private _resetState() {
this.state.setSceneGraph(null);
this.state.setStats({});
this.state.setSelectedNode(null);
this.state.setActiveProps([]);
// TODO: this will cuase us to look through all the iframes each frame if version is not present, we need to add a flag
this.state.setVersion(this.version === '' ? `>${this.majorVersion}.0.0` : this.version);
this.state.setSceneTreeData({ buttons: [] });
}

private preupdate() {
this._resetState();
this.stats.preupdate();
this.tree.preupdate();
this.scene.preupdate();
this.textures.preupdate();
this.rendering.preupdate();
}

private _update() {
this.scene.update();
this.textures.update();
this.rendering.update();
}

private updatedThrottled() {
this.scene.throttledUpdate();
this.textures.throttledUpdate();
this.rendering.throttledUpdate();
}

private updateLoop(container: Container) {
this.scene.loop(container);
this.textures.loop(container);
this.rendering.loop(container);
}

private postupdate() {
this.stats.complete();
this.tree.complete();
this.properties.update();
this.properties.complete();
this.overlay.complete();
this.scene.postupdate();
this.textures.postupdate();
this.rendering.postupdate();

try {
// post the state to the devtools
Expand Down
19 changes: 7 additions & 12 deletions packages/backend/src/rendering/rendering.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
import type { FrameCaptureData, RenderingState } from '@devtool/frontend/pages/rendering/rendering';
import type {
Batch,
BatcherPipe,
CanvasSource,
Container,
GlGeometrySystem,
Expand All @@ -27,10 +28,9 @@ import type {
TextureSource,
TilingSprite,
WebGLRenderer,
BatcherPipe,
WebGPURenderer,
} from 'pixi.js';
import type { PixiDevtools } from '../pixi';
import { PixiHandler } from '../handler';
import { getPixiType } from '../utils/getPixiType';
import { loop } from '../utils/loop';
import {
Expand All @@ -51,8 +51,7 @@ interface PixiMeshObjectInstruction {
mesh: Mesh;
}

export class Rendering {
private _devtool: typeof PixiDevtools;
export class Rendering extends PixiHandler {
private _textureCache: Map<TextureSource, RenderingTextureDataState> = new Map();

private _glDrawFn!: GlGeometrySystem['draw'];
Expand All @@ -72,11 +71,7 @@ export class Rendering {

private stats = new Stats();

constructor(devtool: typeof PixiDevtools) {
this._devtool = devtool;
}

public reset() {
public override reset() {
// restore all overriden functions
const renderer = this._devtool.renderer;

Expand All @@ -95,7 +90,7 @@ export class Rendering {
}
}

public init() {
public override init() {
this._textureCache.clear();
this.stats.reset();

Expand Down Expand Up @@ -187,11 +182,11 @@ export class Rendering {
return res;
};
}
public update() {

public override update() {
this.stats.drawCalls = 0;
this.stats.update();
}
public complete() {}

public captureCanvasData(): RenderingState['canvasData'] {
const renderer = this._devtool.renderer;
Expand Down
Loading
Loading