rendering stats
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { measuredRenderTime } from "../../utils/layerTimings";
|
||||
|
||||
export const DebugLabelsLayer = observer(function () {
|
||||
export const DebugLabelsLayer = observer(measuredRenderTime("DebugLabels", function () {
|
||||
return null; //TODO
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ObjectGeometriesLayer } from "./ObjectGeometriesLayer";
|
||||
import { Canvas } from "@react-three/fiber";
|
||||
import { SceneEditorCameraLayer } from "./SceneEditorGameraLayer";
|
||||
import { SceneEditorCameraLayer } from "./SceneEditor/SceneEditorGameraLayer";
|
||||
import { LightsLayer } from "./LighsLayer";
|
||||
import { StatsLayer } from './StatsLayer';
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { measuredRenderTime } from "../../utils/layerTimings";
|
||||
|
||||
export const LightsLayer = observer(function () {
|
||||
export const LightsLayer = observer(measuredRenderTime("Lights", function () {
|
||||
return <>
|
||||
<ambientLight intensity={0.5} />
|
||||
<directionalLight position={[5, 5, 5]} intensity={1} />
|
||||
</>;
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -4,9 +4,9 @@ import { ObjectGeometryList } from "../../rendering/ObjectGeometryList";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { state } from "../../state";
|
||||
import { useLayerFrame } from "../../utils/hooks/useLayerFrame";
|
||||
import { measuredRenderTime } from "../../utils/layerTimings";
|
||||
|
||||
export const ObjectGeometriesLayer = observer(function () {
|
||||
|
||||
export const ObjectGeometriesLayer = observer(measuredRenderTime("ObjectGeometries", function () {
|
||||
const geometries = state.view.objectGeometries;
|
||||
|
||||
const threeScene = useThree(s => s.scene);
|
||||
@@ -24,4 +24,4 @@ export const ObjectGeometriesLayer = observer(function () {
|
||||
useLayerFrame("ObjectGeometries", () => list.current?.tick());
|
||||
|
||||
return null;
|
||||
});
|
||||
}));
|
||||
|
||||
+6
-5
@@ -1,12 +1,13 @@
|
||||
import { OrbitControls } from "@react-three/drei";
|
||||
import { state } from "../../state";
|
||||
import { state } from "../../../state";
|
||||
import { useRef } from "react";
|
||||
import { useSyncCamera } from "../../utils/hooks/useSyncCamera";
|
||||
import { useSyncCamera } from "../../../utils/hooks/useSyncCamera";
|
||||
import { MOUSE } from "three";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import type { V3 } from "../../types";
|
||||
import type { V3 } from "../../../types";
|
||||
import { measuredRenderTime } from "../../../utils/layerTimings";
|
||||
|
||||
export const SceneEditorCameraLayer = observer(function () {
|
||||
export const SceneEditorCameraLayer = observer(measuredRenderTime("Camera", function () {
|
||||
const controlsRef = useRef<React.ComponentRef<typeof OrbitControls>>(null);
|
||||
|
||||
useSyncCamera(() => state.view.camera?.camera);
|
||||
@@ -38,4 +39,4 @@ export const SceneEditorCameraLayer = observer(function () {
|
||||
rotateSpeed={0.2}
|
||||
enableDamping={false}
|
||||
/>;
|
||||
});
|
||||
}));
|
||||
@@ -49,12 +49,20 @@ export const StatsLayer = function () {
|
||||
];
|
||||
|
||||
for (const [name, entry] of Object.entries(layerTimings)) {
|
||||
if (entry.frames > 0) {
|
||||
const avg = (entry.acc / entry.frames).toFixed(3);
|
||||
lines.push(`${name} ${avg} ms`);
|
||||
const parts: string[] = [];
|
||||
if (entry.frame.frames > 0) {
|
||||
parts.push(`frame ${(entry.frame.acc / entry.frame.frames).toFixed(3)}`);
|
||||
}
|
||||
entry.acc = 0;
|
||||
entry.frames = 0;
|
||||
if (entry.render.frames > 0) {
|
||||
parts.push(`render ${(entry.render.acc / entry.render.frames).toFixed(3)}`);
|
||||
}
|
||||
if (parts.length > 0) {
|
||||
lines.push(`${name} ${parts.join(" ")} ms`);
|
||||
}
|
||||
entry.frame.acc = 0;
|
||||
entry.frame.frames = 0;
|
||||
entry.render.acc = 0;
|
||||
entry.render.frames = 0;
|
||||
}
|
||||
|
||||
if (divRef.current) {
|
||||
|
||||
@@ -15,15 +15,13 @@ export type RenderInfo = {
|
||||
|
||||
export class RootState {
|
||||
public readonly world = new WorldState();
|
||||
public readonly worldEditor: WorldEditorState;
|
||||
public readonly worldEditor = new WorldEditorState(this.world);
|
||||
public game: GameState | undefined;
|
||||
public renderInfo: RenderInfo | undefined;
|
||||
public readonly menu = new MenuState();
|
||||
public readonly view = new ViewState(this.world);
|
||||
public readonly view = new ViewState(this.world, this.worldEditor);
|
||||
|
||||
constructor() {
|
||||
this.worldEditor = new WorldEditorState(this.world);
|
||||
|
||||
makeAutoObservable(
|
||||
this,
|
||||
{
|
||||
|
||||
@@ -3,13 +3,19 @@ import type { ObjectInstance, ObjectType } from "../types";
|
||||
import { MobxReconcilerMap } from '../utils/reconciler';
|
||||
import { ObjectGeometryViewItem, ObjectTypeGeometryViewItem, ControlledCameraViewItem, ViewItem } from './viewLayers';
|
||||
import type { WorldState } from "./worldState";
|
||||
import { ObjectSelectionViewItem } from "./viewLayers/objectSelection";
|
||||
import type { WorldEditorState } from "./worldEditorState";
|
||||
|
||||
export class ViewState {
|
||||
public objectTypeGeometries: MobxReconcilerMap<ObjectType, ObjectTypeGeometryViewItem>;
|
||||
public objectGeometries: MobxReconcilerMap<ObjectInstance, ObjectGeometryViewItem>;
|
||||
public camera?: ControlledCameraViewItem;
|
||||
|
||||
constructor(world: WorldState) {
|
||||
private readonly editor: WorldEditorState;
|
||||
|
||||
constructor(world: WorldState, editor: WorldEditorState) {
|
||||
this.editor = editor;
|
||||
|
||||
makeAutoObservable(
|
||||
this,
|
||||
);
|
||||
@@ -38,11 +44,24 @@ export class ViewState {
|
||||
this.objectGeometries.dispose();
|
||||
}
|
||||
|
||||
public get selectedObject(): ObjectSelectionViewItem | undefined {
|
||||
const sel = this.editor.selection;
|
||||
if (sel?.type !== 'object')
|
||||
return;
|
||||
|
||||
const geom = this.objectGeometries.get(sel.id);
|
||||
if (!geom)
|
||||
return;
|
||||
|
||||
return new ObjectSelectionViewItem(geom, sel.editMode);
|
||||
}
|
||||
|
||||
public get items(): ViewItem[] {
|
||||
return [
|
||||
...this.objectTypeGeometries,
|
||||
...this.objectGeometries,
|
||||
...[this.camera ? [this.camera] : []],
|
||||
...[this.selectedObject ? [this.selectedObject] : []],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useFrame, type RootState } from "@react-three/fiber";
|
||||
import { layerTimings } from "../layerTimings";
|
||||
import { recordLayerFrameTime } from "../layerTimings";
|
||||
|
||||
export function useLayerFrame(
|
||||
name: string,
|
||||
@@ -9,8 +9,6 @@ export function useLayerFrame(
|
||||
useFrame((state, delta) => {
|
||||
const start = performance.now();
|
||||
callback(state, delta);
|
||||
const entry = layerTimings[name] ??= { acc: 0, frames: 0 };
|
||||
entry.acc += performance.now() - start;
|
||||
entry.frames++;
|
||||
recordLayerFrameTime(name, performance.now() - start);
|
||||
}, priority);
|
||||
}
|
||||
|
||||
@@ -1 +1,43 @@
|
||||
export const layerTimings: Record<string, { acc: number; frames: number }> = {};
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export type LayerTiming = {
|
||||
frame: { acc: number; frames: number };
|
||||
render: { acc: number; frames: number };
|
||||
};
|
||||
|
||||
export const layerTimings: Record<string, LayerTiming> = {};
|
||||
|
||||
function getEntry(name: string): LayerTiming {
|
||||
return layerTimings[name] ??= {
|
||||
frame: { acc: 0, frames: 0 },
|
||||
render: { acc: 0, frames: 0 },
|
||||
};
|
||||
}
|
||||
|
||||
export function recordLayerFrameTime(name: string, ms: number) {
|
||||
const t = getEntry(name).frame;
|
||||
t.acc += ms;
|
||||
t.frames++;
|
||||
}
|
||||
|
||||
export function startLayerRender(name: string): () => void {
|
||||
const start = performance.now();
|
||||
return () => {
|
||||
const t = getEntry(name).render;
|
||||
t.acc += performance.now() - start;
|
||||
t.frames++;
|
||||
};
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export function measuredRenderTime<TArgs extends any[], TResult extends ReactNode>(
|
||||
name: string,
|
||||
callback: (...args: TArgs) => TResult
|
||||
): ((...args: TArgs) => TResult) {
|
||||
return (...args) => {
|
||||
const endRender = startLayerRender(name);
|
||||
const result = callback(...args);
|
||||
endRender();
|
||||
return result;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user