@aura3d/debug 4.0.8 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/safety/blackFrame.d.ts +119 -0
- package/dist/safety/blackFrame.d.ts.map +1 -0
- package/dist/safety/blackFrame.js +326 -0
- package/dist/safety/blackFrame.js.map +1 -0
- package/dist/safety/diagnosticsPanel.d.ts +70 -0
- package/dist/safety/diagnosticsPanel.d.ts.map +1 -0
- package/dist/safety/diagnosticsPanel.js +123 -0
- package/dist/safety/diagnosticsPanel.js.map +1 -0
- package/dist/safety/guard.d.ts +51 -0
- package/dist/safety/guard.d.ts.map +1 -0
- package/dist/safety/guard.js +64 -0
- package/dist/safety/guard.js.map +1 -0
- package/dist/safety/index.d.ts +50 -0
- package/dist/safety/index.d.ts.map +1 -0
- package/dist/safety/index.js +71 -0
- package/dist/safety/index.js.map +1 -0
- package/dist/safety/switches.d.ts +27 -0
- package/dist/safety/switches.d.ts.map +1 -0
- package/dist/safety/switches.js +23 -0
- package/dist/safety/switches.js.map +1 -0
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -28,4 +28,6 @@ export { buildAxesHelper, buildBoundsHelper, buildCameraFrustumHelper, buildDire
|
|
|
28
28
|
export type { AxesHelperOptions, BoundsHelperOptions, CameraFrustumHelperOptions, DebugColor, DebugVec3, DirectionalLightHelperOptions, GridHelperOptions, SkeletonHelperJoint } from "./SceneHelpers.js";
|
|
29
29
|
export { ReportExporter } from "./ReportExporter.js";
|
|
30
30
|
export type { DebugReport } from "./ReportExporter.js";
|
|
31
|
+
export { DEFAULT_HEAL_LADDER, DEFAULT_HEAL_STORAGE_KEY, QR_HEAL_LADDER, createBlackFrameWatch, formatEngineSection, formatGpuProbe, healParams, healRungName, healStage, installBlackFrameGuard, installDiagnosticsPanel, installSafetyNet, isBlackFrame, probeGpu, qrHealRungName, qrHealStage, qrHealUrl, resolveQualitySwitches } from "./safety/index.js";
|
|
32
|
+
export type { BlackFrameGuardOptions, BlackFrameWatch, BlackFrameWatchOptions, DiagnosticsAppLike, DiagnosticsPanelHandle, DiagnosticsPanelOptions, GpuProbe, HealGlobal, HealRung, QualitySwitches, ResolveQualitySwitchesOptions, SafetyNet, SafetyNetOptions, SafetyReport, SafetySettings } from "./safety/index.js";
|
|
31
33
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACvF,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACxG,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAClF,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACxF,YAAY,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AACtH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AACxG,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,YAAY,EAAE,8BAA8B,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AACjI,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,0BAA0B,EAC1B,UAAU,EACV,SAAS,EACT,6BAA6B,EAC7B,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -13,4 +13,5 @@ export { DebugOverlay } from "./DebugOverlay.js";
|
|
|
13
13
|
export { DebugLineCanvasRenderer } from "./DebugLineCanvasRenderer.js";
|
|
14
14
|
export { buildAxesHelper, buildBoundsHelper, buildCameraFrustumHelper, buildDirectionalLightHelper, buildGridHelper, buildSkeletonHelper } from "./SceneHelpers.js";
|
|
15
15
|
export { ReportExporter } from "./ReportExporter.js";
|
|
16
|
+
export { DEFAULT_HEAL_LADDER, DEFAULT_HEAL_STORAGE_KEY, QR_HEAL_LADDER, createBlackFrameWatch, formatEngineSection, formatGpuProbe, healParams, healRungName, healStage, installBlackFrameGuard, installDiagnosticsPanel, installSafetyNet, isBlackFrame, probeGpu, qrHealRungName, qrHealStage, qrHealUrl, resolveQualitySwitches } from "./safety/index.js";
|
|
16
17
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../packages/debug/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEvF,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAElF,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAExF,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAE/D,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,2BAA2B,EAC3B,eAAe,EACf,mBAAmB,EACpB,MAAM,mBAAmB,CAAC;AAW3B,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EACL,mBAAmB,EACnB,wBAAwB,EACxB,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,YAAY,EACZ,SAAS,EACT,sBAAsB,EACtB,uBAAuB,EACvB,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,WAAW,EACX,SAAS,EACT,sBAAsB,EACvB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Black-frame self-heal. Some GPU/driver combinations present a frame that is entirely black while the engine reports
|
|
3
|
+
* draw calls. When that persists the page reloads itself one rung down a compatibility ladder (each rung switches off
|
|
4
|
+
* one more optional stage) and records the rung and why, so a player still gets a picture and the diagnostics panel
|
|
5
|
+
* shows which rung fixed it. Opt-in only: nothing here runs unless `installSafetyNet`, `installBlackFrameGuard` or
|
|
6
|
+
* `createBlackFrameWatch` is called.
|
|
7
|
+
*
|
|
8
|
+
* The watch is deliberately conservative. A frame counts as broken only when (almost) every sampled texel of the world
|
|
9
|
+
* canvas is the clear colour, the app is ready (document loaded, no loading overlay, no asset fetches in flight, the
|
|
10
|
+
* engine drew something), it has rendered a minimum number of frames since becoming ready, and the canvas stayed that
|
|
11
|
+
* way for several consecutive samples over a time budget that grows with the measured frame time. A dark but valid
|
|
12
|
+
* scene, a slow first frame on a CPU renderer or a page that is still loading never trips it.
|
|
13
|
+
*/
|
|
14
|
+
export interface HealRung {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly params: Readonly<Record<string, string>>;
|
|
17
|
+
}
|
|
18
|
+
export declare const DEFAULT_HEAL_LADDER: readonly HealRung[];
|
|
19
|
+
export declare const DEFAULT_HEAL_STORAGE_KEY = "aura3d-safety-heal-stage";
|
|
20
|
+
type StorageLike = Pick<Storage, "getItem" | "setItem">;
|
|
21
|
+
/** Current rung (0 = full quality) from session storage, so a reload continues down the ladder. */
|
|
22
|
+
export declare function healStage(storage?: Pick<Storage, "getItem"> | undefined, ladder?: readonly HealRung[], storageKey?: string): number;
|
|
23
|
+
/** Query parameters implied by rung `stage` (cumulative); callers merge them under the author's explicit parameters. */
|
|
24
|
+
export declare function healParams(stage: number, ladder?: readonly HealRung[]): Record<string, string>;
|
|
25
|
+
export declare function healRungName(stage: number, ladder?: readonly HealRung[]): string;
|
|
26
|
+
export interface FrameStats {
|
|
27
|
+
readonly samples: number;
|
|
28
|
+
/** Samples with any colour channel above the black threshold. */
|
|
29
|
+
readonly lit: number;
|
|
30
|
+
readonly litFraction: number;
|
|
31
|
+
/** Largest colour channel seen (0..255). */
|
|
32
|
+
readonly max: number;
|
|
33
|
+
/** Mean of the RGB channels (0..255). */
|
|
34
|
+
readonly mean: number;
|
|
35
|
+
}
|
|
36
|
+
/** Statistics of a downscaled RGBA probe of the canvas. */
|
|
37
|
+
export declare function analyseFrame(rgba: ArrayLike<number>, maxChannel?: number): FrameStats;
|
|
38
|
+
/**
|
|
39
|
+
* True when the sampled frame is black: every texel by default; pass a small `maxLitFraction` to tolerate a few stray lit
|
|
40
|
+
* texels (for example a HUD drawn into the same canvas). Empty input is never black.
|
|
41
|
+
*/
|
|
42
|
+
export declare function isBlackFrame(rgba: ArrayLike<number>, maxLitFraction?: number): boolean;
|
|
43
|
+
/** True while a visible loading overlay is on the page (`#boot`, `#loading`, `.loading`, `[aria-busy=true]` ...). */
|
|
44
|
+
export declare function hasVisibleLoadingOverlay(root?: Pick<Document, "querySelectorAll"> | undefined): boolean;
|
|
45
|
+
/** Default readiness: document fully loaded, no asset fetches in flight, no visible loading overlay. */
|
|
46
|
+
export declare function defaultIsReady(): boolean;
|
|
47
|
+
/** Largest canvas big enough to be the world view, ignoring minimap/HUD/overlay canvases. */
|
|
48
|
+
export declare function findWorldCanvas(root?: Pick<Document, "querySelectorAll"> | undefined): HTMLCanvasElement | null;
|
|
49
|
+
export interface WatchObservation {
|
|
50
|
+
/** `sample()` calls so far (frames the app drew while the watch was installed). */
|
|
51
|
+
readonly calls: number;
|
|
52
|
+
/** Call index at which the app first counted as ready, or null while it is not. */
|
|
53
|
+
readonly readyAtCall: number | null;
|
|
54
|
+
readonly framesSinceReady: number;
|
|
55
|
+
readonly samples: number;
|
|
56
|
+
readonly blackSamples: number;
|
|
57
|
+
readonly consecutiveBlack: number;
|
|
58
|
+
/** True once lit frames were seen for long enough that the watch relaxed to occasional sampling. */
|
|
59
|
+
readonly healthy: boolean;
|
|
60
|
+
readonly lastStats: FrameStats | undefined;
|
|
61
|
+
readonly medianFrameMs: number;
|
|
62
|
+
/** How long the canvas has stayed black (ms), 0 when it is not. */
|
|
63
|
+
readonly blackMs: number;
|
|
64
|
+
readonly skipped: {
|
|
65
|
+
readonly notReady: number;
|
|
66
|
+
readonly noDrawCalls: number;
|
|
67
|
+
readonly hidden: number;
|
|
68
|
+
};
|
|
69
|
+
readonly escalated: boolean;
|
|
70
|
+
/** Why the watch reloaded this page (set on escalation) or why the previous page did (from session storage). */
|
|
71
|
+
readonly reason: string | undefined;
|
|
72
|
+
}
|
|
73
|
+
export interface BlackFrameWatchOptions {
|
|
74
|
+
readonly enabled: boolean;
|
|
75
|
+
readonly ladder?: readonly HealRung[];
|
|
76
|
+
readonly storageKey?: string;
|
|
77
|
+
/** Shortens every window (tests only): minimum frames after ready, no minimum black time, samples needed = half of it. */
|
|
78
|
+
readonly fastFrames?: number;
|
|
79
|
+
/** Reads a downscaled RGBA probe of the canvas. Defaults to a nearest-neighbour 2D canvas copy. */
|
|
80
|
+
readonly readProbe?: (canvas: HTMLCanvasElement) => ArrayLike<number> | undefined;
|
|
81
|
+
readonly storage?: StorageLike;
|
|
82
|
+
readonly currentUrl?: () => string;
|
|
83
|
+
/** Navigates to the next rung. Defaults to `location.replace`. */
|
|
84
|
+
readonly navigate?: (url: string) => void;
|
|
85
|
+
readonly log?: (code: string, message: string) => void;
|
|
86
|
+
/** Extra readiness signal (for example the app's own `ready` flag). The default checks overlays, load state and fetches. */
|
|
87
|
+
readonly isReady?: () => boolean;
|
|
88
|
+
/** Engine draw calls for the current frame; when given and not > 0 the frame is not judged (nothing was drawn). */
|
|
89
|
+
readonly getDrawCalls?: () => number | undefined;
|
|
90
|
+
/** Builds the reload URL for rung `stage`, or null to stop. Default merges the rung parameters under the existing query. */
|
|
91
|
+
readonly buildUrl?: (stage: number, currentUrl: string) => string | null;
|
|
92
|
+
/** Clock in ms (tests). Defaults to `performance.now()`. */
|
|
93
|
+
readonly now?: () => number;
|
|
94
|
+
/** Treat the page as hidden (tests). Defaults to `document.hidden`. */
|
|
95
|
+
readonly isHidden?: () => boolean;
|
|
96
|
+
/** Minimum black duration in ms; the effective window is `max(minBlackMs, medianFrameMs * blackFramesBudget)`. Default 4000. */
|
|
97
|
+
readonly minBlackMs?: number;
|
|
98
|
+
/** Frames' worth of measured frame time black must persist for. Default 40. */
|
|
99
|
+
readonly blackFramesBudget?: number;
|
|
100
|
+
/** Rendered frames required after becoming ready before judging. Default 30. */
|
|
101
|
+
readonly minFramesAfterReady?: number;
|
|
102
|
+
/** Judge every Nth frame. Default 4. */
|
|
103
|
+
readonly sampleEvery?: number;
|
|
104
|
+
/** Consecutive black samples required. Default 12. */
|
|
105
|
+
readonly samplesNeeded?: number;
|
|
106
|
+
}
|
|
107
|
+
export interface BlackFrameWatch {
|
|
108
|
+
/** Call right after a frame was drawn, in the same task (before the browser composites it). The argument is unused and kept for compatibility. */
|
|
109
|
+
sample(framesDrawn?: number): void;
|
|
110
|
+
readonly stage: number;
|
|
111
|
+
readonly rung: string;
|
|
112
|
+
/** True once the watch decided to reload one rung down. */
|
|
113
|
+
readonly escalated: boolean;
|
|
114
|
+
/** What the watch has seen so far (also why the previous page reloaded, if it did). */
|
|
115
|
+
observation(): WatchObservation;
|
|
116
|
+
}
|
|
117
|
+
export declare function createBlackFrameWatch(canvas: HTMLCanvasElement | (() => HTMLCanvasElement | null | undefined), options: BlackFrameWatchOptions): BlackFrameWatch;
|
|
118
|
+
export {};
|
|
119
|
+
//# sourceMappingURL=blackFrame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blackFrame.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/blackFrame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
export const DEFAULT_HEAL_LADDER = [
|
|
2
|
+
{ name: "no-aa", params: { aa: "0" } },
|
|
3
|
+
{ name: "no-post", params: { post: "0" } },
|
|
4
|
+
{ name: "aces-tone", params: { tm: "aces" } },
|
|
5
|
+
{ name: "no-env", params: { env: "0" } },
|
|
6
|
+
{ name: "no-shadow", params: { shadow: "0" } },
|
|
7
|
+
{ name: "low-quality", params: { quality: "low", sky: "1" } }
|
|
8
|
+
];
|
|
9
|
+
export const DEFAULT_HEAL_STORAGE_KEY = "aura3d-safety-heal-stage";
|
|
10
|
+
const BLACK_MAX_CHANNEL = 4;
|
|
11
|
+
/** Nearest-neighbour probe grid: one texel per block, so thin bright features are not averaged away. */
|
|
12
|
+
const PROBE_WIDTH = 48;
|
|
13
|
+
const PROBE_HEIGHT = 32;
|
|
14
|
+
/** "Nearly all" black: at most this fraction of grid samples may be lit (a few stray texels of a HUD drawn into the canvas). */
|
|
15
|
+
const MAX_LIT_FRACTION = 0.002;
|
|
16
|
+
const LOADING_SELECTOR = '#boot, .boot, #loading, #loader, #loading-screen, .loading, .loader, [data-loading="true"], [aria-busy="true"], [id*="loading" i], [class*="loading" i]';
|
|
17
|
+
const HIDDEN_CLASSES = ["hidden", "done", "is-hidden", "loaded", "ready", "fade-out"];
|
|
18
|
+
function safeStorage() {
|
|
19
|
+
try {
|
|
20
|
+
return globalThis.sessionStorage;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Current rung (0 = full quality) from session storage, so a reload continues down the ladder. */
|
|
27
|
+
export function healStage(storage = safeStorage(), ladder = DEFAULT_HEAL_LADDER, storageKey = DEFAULT_HEAL_STORAGE_KEY) {
|
|
28
|
+
const raw = Number(storage?.getItem(storageKey) ?? "0");
|
|
29
|
+
return Number.isInteger(raw) && raw >= 0 && raw <= ladder.length ? raw : 0;
|
|
30
|
+
}
|
|
31
|
+
/** Query parameters implied by rung `stage` (cumulative); callers merge them under the author's explicit parameters. */
|
|
32
|
+
export function healParams(stage, ladder = DEFAULT_HEAL_LADDER) {
|
|
33
|
+
const merged = {};
|
|
34
|
+
for (const rung of ladder.slice(0, Math.max(0, stage)))
|
|
35
|
+
Object.assign(merged, rung.params);
|
|
36
|
+
return merged;
|
|
37
|
+
}
|
|
38
|
+
export function healRungName(stage, ladder = DEFAULT_HEAL_LADDER) {
|
|
39
|
+
return stage <= 0 ? "full" : ladder[Math.min(stage, ladder.length) - 1].name;
|
|
40
|
+
}
|
|
41
|
+
/** Statistics of a downscaled RGBA probe of the canvas. */
|
|
42
|
+
export function analyseFrame(rgba, maxChannel = BLACK_MAX_CHANNEL) {
|
|
43
|
+
let samples = 0;
|
|
44
|
+
let lit = 0;
|
|
45
|
+
let max = 0;
|
|
46
|
+
let sum = 0;
|
|
47
|
+
for (let i = 0; i + 2 < rgba.length; i += 4) {
|
|
48
|
+
const r = rgba[i];
|
|
49
|
+
const g = rgba[i + 1];
|
|
50
|
+
const b = rgba[i + 2];
|
|
51
|
+
samples += 1;
|
|
52
|
+
sum += r + g + b;
|
|
53
|
+
const peak = Math.max(r, g, b);
|
|
54
|
+
if (peak > max)
|
|
55
|
+
max = peak;
|
|
56
|
+
if (peak > maxChannel)
|
|
57
|
+
lit += 1;
|
|
58
|
+
}
|
|
59
|
+
return { samples, lit, litFraction: samples === 0 ? 1 : lit / samples, max, mean: samples === 0 ? 0 : sum / (samples * 3) };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* True when the sampled frame is black: every texel by default; pass a small `maxLitFraction` to tolerate a few stray lit
|
|
63
|
+
* texels (for example a HUD drawn into the same canvas). Empty input is never black.
|
|
64
|
+
*/
|
|
65
|
+
export function isBlackFrame(rgba, maxLitFraction = 0) {
|
|
66
|
+
if (rgba.length < 4)
|
|
67
|
+
return false;
|
|
68
|
+
return analyseFrame(rgba).litFraction <= maxLitFraction;
|
|
69
|
+
}
|
|
70
|
+
function elementVisible(element) {
|
|
71
|
+
const node = element;
|
|
72
|
+
if (node.hidden === true)
|
|
73
|
+
return false;
|
|
74
|
+
const classes = node.classList;
|
|
75
|
+
if (classes && HIDDEN_CLASSES.some((name) => classes.contains(name)))
|
|
76
|
+
return false;
|
|
77
|
+
if (typeof getComputedStyle === "function") {
|
|
78
|
+
try {
|
|
79
|
+
const style = getComputedStyle(node);
|
|
80
|
+
if (style.display === "none" || style.visibility === "hidden" || Number(style.opacity) < 0.02)
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
/* detached or stubbed element: treat as visible */
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (typeof node.getBoundingClientRect === "function") {
|
|
88
|
+
const box = node.getBoundingClientRect();
|
|
89
|
+
if (box.width <= 0 || box.height <= 0)
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
/** True while a visible loading overlay is on the page (`#boot`, `#loading`, `.loading`, `[aria-busy=true]` ...). */
|
|
95
|
+
export function hasVisibleLoadingOverlay(root = typeof document === "undefined" ? undefined : document) {
|
|
96
|
+
if (!root || typeof root.querySelectorAll !== "function")
|
|
97
|
+
return false;
|
|
98
|
+
try {
|
|
99
|
+
return Array.from(root.querySelectorAll(LOADING_SELECTOR)).some(elementVisible);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Default readiness: document fully loaded, no asset fetches in flight, no visible loading overlay. */
|
|
106
|
+
export function defaultIsReady() {
|
|
107
|
+
if (typeof document !== "undefined" && document.readyState && document.readyState !== "complete")
|
|
108
|
+
return false;
|
|
109
|
+
const inflight = globalThis.__aura3dInFlightByteFetches;
|
|
110
|
+
if (typeof inflight === "number" && inflight > 0)
|
|
111
|
+
return false;
|
|
112
|
+
return !hasVisibleLoadingOverlay();
|
|
113
|
+
}
|
|
114
|
+
/** Largest canvas big enough to be the world view, ignoring minimap/HUD/overlay canvases. */
|
|
115
|
+
export function findWorldCanvas(root = typeof document === "undefined" ? undefined : document) {
|
|
116
|
+
if (!root || typeof root.querySelectorAll !== "function")
|
|
117
|
+
return null;
|
|
118
|
+
let best = null;
|
|
119
|
+
let area = 0;
|
|
120
|
+
for (const canvas of Array.from(root.querySelectorAll("canvas"))) {
|
|
121
|
+
const label = `${canvas.id ?? ""} ${canvas.className ?? ""}`;
|
|
122
|
+
if (/minimap|mini-map|hud|overlay|compass|radar|(^|[\s_-])ui([\s_-]|$)/i.test(label))
|
|
123
|
+
continue;
|
|
124
|
+
const a = canvas.width * canvas.height;
|
|
125
|
+
if (canvas.width >= 128 && canvas.height >= 96 && a > area) {
|
|
126
|
+
best = canvas;
|
|
127
|
+
area = a;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return best;
|
|
131
|
+
}
|
|
132
|
+
function defaultProbe() {
|
|
133
|
+
let ctx;
|
|
134
|
+
return (canvas) => {
|
|
135
|
+
if (ctx === undefined) {
|
|
136
|
+
const probe = document.createElement("canvas");
|
|
137
|
+
probe.width = PROBE_WIDTH;
|
|
138
|
+
probe.height = PROBE_HEIGHT;
|
|
139
|
+
ctx = probe.getContext("2d", { willReadFrequently: true });
|
|
140
|
+
if (ctx)
|
|
141
|
+
ctx.imageSmoothingEnabled = false;
|
|
142
|
+
}
|
|
143
|
+
if (!ctx)
|
|
144
|
+
return undefined;
|
|
145
|
+
ctx.drawImage(canvas, 0, 0, PROBE_WIDTH, PROBE_HEIGHT);
|
|
146
|
+
return ctx.getImageData(0, 0, PROBE_WIDTH, PROBE_HEIGHT).data;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function median(values) {
|
|
150
|
+
if (values.length === 0)
|
|
151
|
+
return 0;
|
|
152
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
153
|
+
return sorted[Math.floor(sorted.length / 2)];
|
|
154
|
+
}
|
|
155
|
+
export function createBlackFrameWatch(canvas, options) {
|
|
156
|
+
const ladder = options.ladder ?? DEFAULT_HEAL_LADDER;
|
|
157
|
+
const storageKey = options.storageKey ?? DEFAULT_HEAL_STORAGE_KEY;
|
|
158
|
+
const reasonKey = `${storageKey}:reason`;
|
|
159
|
+
const storage = options.storage ?? safeStorage();
|
|
160
|
+
const fast = options.fastFrames !== undefined;
|
|
161
|
+
const minFramesAfterReady = options.minFramesAfterReady ?? options.fastFrames ?? 30;
|
|
162
|
+
const sampleEvery = Math.max(1, options.sampleEvery ?? (fast ? 2 : 4));
|
|
163
|
+
const samplesNeeded = Math.max(2, options.samplesNeeded ?? (fast ? Math.ceil(options.fastFrames / 2) : 12));
|
|
164
|
+
const minBlackMs = options.minBlackMs ?? (fast ? 0 : 4000);
|
|
165
|
+
const blackFramesBudget = options.blackFramesBudget ?? (fast ? 0 : 40);
|
|
166
|
+
const stage = healStage(storage, ladder, storageKey);
|
|
167
|
+
const readProbe = options.readProbe ?? defaultProbe();
|
|
168
|
+
const log = options.log ?? ((code, message) => console.warn(`${code}: ${message}`));
|
|
169
|
+
const currentUrl = options.currentUrl ?? (() => location.href);
|
|
170
|
+
const navigate = options.navigate ?? ((url) => location.replace(url));
|
|
171
|
+
const now = options.now ?? (() => performance.now());
|
|
172
|
+
const isHidden = options.isHidden ?? (() => typeof document !== "undefined" && (document.hidden === true || document.visibilityState === "hidden"));
|
|
173
|
+
const appReady = options.isReady;
|
|
174
|
+
const previousReason = (() => {
|
|
175
|
+
try {
|
|
176
|
+
return storage?.getItem(reasonKey) ?? undefined;
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
})();
|
|
182
|
+
let calls = 0;
|
|
183
|
+
let readyAtCall = null;
|
|
184
|
+
let samples = 0;
|
|
185
|
+
let blackSamples = 0;
|
|
186
|
+
let consecutive = 0;
|
|
187
|
+
let litStreak = 0;
|
|
188
|
+
let healthy = false;
|
|
189
|
+
let blackSince = 0;
|
|
190
|
+
let escalated = false;
|
|
191
|
+
let lastStats;
|
|
192
|
+
let lastTime;
|
|
193
|
+
let reason = previousReason;
|
|
194
|
+
const deltas = [];
|
|
195
|
+
const skipped = { notReady: 0, noDrawCalls: 0, hidden: 0 };
|
|
196
|
+
if (stage > 0)
|
|
197
|
+
log("SAFETY_COMPAT_MODE", `rung ${stage} (${healRungName(stage, ladder)}) after a black frame was detected${previousReason ? `: ${previousReason}` : ""}`);
|
|
198
|
+
const resetStreak = () => {
|
|
199
|
+
consecutive = 0;
|
|
200
|
+
blackSince = 0;
|
|
201
|
+
};
|
|
202
|
+
return {
|
|
203
|
+
stage,
|
|
204
|
+
rung: healRungName(stage, ladder),
|
|
205
|
+
get escalated() {
|
|
206
|
+
return escalated;
|
|
207
|
+
},
|
|
208
|
+
observation() {
|
|
209
|
+
const t = lastTime ?? 0;
|
|
210
|
+
return {
|
|
211
|
+
calls,
|
|
212
|
+
readyAtCall,
|
|
213
|
+
framesSinceReady: readyAtCall === null ? 0 : calls - readyAtCall + 1,
|
|
214
|
+
samples,
|
|
215
|
+
blackSamples,
|
|
216
|
+
consecutiveBlack: consecutive,
|
|
217
|
+
healthy,
|
|
218
|
+
lastStats,
|
|
219
|
+
medianFrameMs: median(deltas),
|
|
220
|
+
blackMs: blackSince ? Math.max(0, t - blackSince) : 0,
|
|
221
|
+
skipped: { ...skipped },
|
|
222
|
+
escalated,
|
|
223
|
+
reason
|
|
224
|
+
};
|
|
225
|
+
},
|
|
226
|
+
sample() {
|
|
227
|
+
const t = now();
|
|
228
|
+
if (lastTime !== undefined && t >= lastTime) {
|
|
229
|
+
deltas.push(t - lastTime);
|
|
230
|
+
if (deltas.length > 31)
|
|
231
|
+
deltas.shift();
|
|
232
|
+
}
|
|
233
|
+
lastTime = t;
|
|
234
|
+
calls += 1;
|
|
235
|
+
if (!options.enabled || escalated)
|
|
236
|
+
return;
|
|
237
|
+
if (isHidden()) {
|
|
238
|
+
skipped.hidden += 1;
|
|
239
|
+
resetStreak();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
let ready = (appReady ? appReady() : true) && defaultIsReady();
|
|
243
|
+
if (!ready) {
|
|
244
|
+
skipped.notReady += 1;
|
|
245
|
+
readyAtCall = null;
|
|
246
|
+
healthy = false;
|
|
247
|
+
litStreak = 0;
|
|
248
|
+
resetStreak();
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (readyAtCall === null)
|
|
252
|
+
readyAtCall = calls;
|
|
253
|
+
ready = true;
|
|
254
|
+
const since = calls - readyAtCall + 1;
|
|
255
|
+
const every = healthy ? sampleEvery * 8 : sampleEvery;
|
|
256
|
+
if (since < minFramesAfterReady || since % every !== 0)
|
|
257
|
+
return;
|
|
258
|
+
const drawCalls = options.getDrawCalls?.();
|
|
259
|
+
if (drawCalls !== undefined && !(drawCalls > 0)) {
|
|
260
|
+
skipped.noDrawCalls += 1;
|
|
261
|
+
resetStreak();
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
const target = typeof canvas === "function" ? canvas() : canvas;
|
|
265
|
+
if (!target)
|
|
266
|
+
return;
|
|
267
|
+
let stats;
|
|
268
|
+
try {
|
|
269
|
+
const data = readProbe(target);
|
|
270
|
+
if (!data)
|
|
271
|
+
return;
|
|
272
|
+
stats = analyseFrame(data);
|
|
273
|
+
}
|
|
274
|
+
catch {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
lastStats = stats;
|
|
278
|
+
samples += 1;
|
|
279
|
+
const black = stats.samples > 0 && stats.litFraction <= MAX_LIT_FRACTION;
|
|
280
|
+
if (!black) {
|
|
281
|
+
litStreak += 1;
|
|
282
|
+
resetStreak();
|
|
283
|
+
if (litStreak >= 3)
|
|
284
|
+
healthy = true;
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
litStreak = 0;
|
|
288
|
+
blackSamples += 1;
|
|
289
|
+
consecutive += 1;
|
|
290
|
+
if (blackSince === 0)
|
|
291
|
+
blackSince = t;
|
|
292
|
+
const medianFrameMs = median(deltas);
|
|
293
|
+
const windowMs = Math.max(minBlackMs, medianFrameMs * blackFramesBudget);
|
|
294
|
+
if (consecutive < samplesNeeded || t - blackSince < windowMs || stage >= ladder.length)
|
|
295
|
+
return;
|
|
296
|
+
escalated = true;
|
|
297
|
+
reason = `black for ${consecutive} samples / ${Math.round(t - blackSince)} ms after ${since} ready frames (lit ${stats.lit}/${stats.samples}, max channel ${stats.max}, median frame ${Math.round(medianFrameMs)} ms, drawCalls ${drawCalls ?? "n/a"})`;
|
|
298
|
+
const href = currentUrl();
|
|
299
|
+
let next;
|
|
300
|
+
if (options.buildUrl) {
|
|
301
|
+
next = options.buildUrl(stage + 1, href);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
const url = new URL(href);
|
|
305
|
+
for (const [key, value] of Object.entries(healParams(stage + 1, ladder)))
|
|
306
|
+
if (!url.searchParams.has(key))
|
|
307
|
+
url.searchParams.set(key, value);
|
|
308
|
+
next = url.toString();
|
|
309
|
+
}
|
|
310
|
+
if (!next) {
|
|
311
|
+
escalated = false;
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
try {
|
|
315
|
+
storage?.setItem(storageKey, String(stage + 1));
|
|
316
|
+
storage?.setItem(reasonKey, reason);
|
|
317
|
+
}
|
|
318
|
+
catch {
|
|
319
|
+
/* storage unavailable: the reload still happens, the rung just cannot continue */
|
|
320
|
+
}
|
|
321
|
+
log("SAFETY_BLACK_FRAME", `reloading at rung ${stage + 1} (${healRungName(stage + 1, ladder)}): ${reason}`);
|
|
322
|
+
navigate(next);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
//# sourceMappingURL=blackFrame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blackFrame.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/blackFrame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* On-screen GPU diagnostics panel: renderer string, WebGL limits and extensions, canvas size, WebGPU presence, engine
|
|
3
|
+
* draw calls, shader compile/link failures, WebGL context loss and the last console errors. Intended for real-device
|
|
4
|
+
* bug reports ("open the page with ?diag=1 and send a screenshot"). Nothing is installed until the function is called,
|
|
5
|
+
* and `dispose()` restores every patched browser prototype and console method.
|
|
6
|
+
*/
|
|
7
|
+
/** Subset of the engine's `diagnostics().shaderFailures` records the panel prints. */
|
|
8
|
+
export interface ShaderFailureLike {
|
|
9
|
+
readonly code?: string;
|
|
10
|
+
readonly material?: string;
|
|
11
|
+
readonly stage?: string;
|
|
12
|
+
readonly message?: string;
|
|
13
|
+
readonly locations?: readonly {
|
|
14
|
+
readonly line?: number;
|
|
15
|
+
readonly authoredLine?: number;
|
|
16
|
+
readonly message?: string;
|
|
17
|
+
readonly window?: readonly {
|
|
18
|
+
readonly text?: string;
|
|
19
|
+
readonly error?: boolean;
|
|
20
|
+
}[];
|
|
21
|
+
}[];
|
|
22
|
+
}
|
|
23
|
+
export interface DiagnosticsAppLike {
|
|
24
|
+
/** `AuraApp.diagnostics()` shape; only these members are read. */
|
|
25
|
+
diagnostics?(): {
|
|
26
|
+
readonly backend?: unknown;
|
|
27
|
+
readonly drawCalls?: unknown;
|
|
28
|
+
readonly fps?: unknown;
|
|
29
|
+
readonly warnings?: readonly string[];
|
|
30
|
+
readonly errors?: readonly string[];
|
|
31
|
+
readonly shaderFailures?: readonly ShaderFailureLike[];
|
|
32
|
+
} | undefined;
|
|
33
|
+
}
|
|
34
|
+
export interface DiagnosticsPanelOptions {
|
|
35
|
+
readonly app?: DiagnosticsAppLike;
|
|
36
|
+
readonly title?: string;
|
|
37
|
+
readonly maxLines?: number;
|
|
38
|
+
/** Extra lines appended to the engine section (the safety net adds its rung and switches here). */
|
|
39
|
+
readonly extraLines?: () => readonly string[];
|
|
40
|
+
/** Update period in ms. */
|
|
41
|
+
readonly refreshMs?: number;
|
|
42
|
+
}
|
|
43
|
+
export interface DiagnosticsPanelHandle {
|
|
44
|
+
readonly lines: readonly string[];
|
|
45
|
+
refresh(): void;
|
|
46
|
+
dispose(): void;
|
|
47
|
+
}
|
|
48
|
+
export interface GpuProbe {
|
|
49
|
+
readonly renderer: string;
|
|
50
|
+
readonly limits: string;
|
|
51
|
+
readonly extensions: string;
|
|
52
|
+
readonly webgpu: boolean;
|
|
53
|
+
readonly dpr: number;
|
|
54
|
+
}
|
|
55
|
+
export declare function probeGpu(): GpuProbe | {
|
|
56
|
+
readonly error: string;
|
|
57
|
+
};
|
|
58
|
+
export declare function formatGpuProbe(probe: GpuProbe | {
|
|
59
|
+
readonly error: string;
|
|
60
|
+
}): string;
|
|
61
|
+
/** Pure formatter for the engine section so it can be unit tested without a browser. */
|
|
62
|
+
export declare function formatEngineSection(app: DiagnosticsAppLike | undefined, canvases: ReadonlyArray<{
|
|
63
|
+
id?: string;
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
clientWidth: number;
|
|
67
|
+
clientHeight: number;
|
|
68
|
+
}>): string;
|
|
69
|
+
export declare function installDiagnosticsPanel(options?: DiagnosticsPanelOptions): DiagnosticsPanelHandle;
|
|
70
|
+
//# sourceMappingURL=diagnosticsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnosticsPanel.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/diagnosticsPanel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,sFAAsF;AACtF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS;YAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,CAAC;CAC1M;AAED,MAAM,WAAW,kBAAkB;IACjC,kEAAkE;IAClE,WAAW,CAAC,IAAI;QAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;KAAE,GAAG,SAAS,CAAC;CACtP;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,mGAAmG;IACnG,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC9C,2BAA2B;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,OAAO,IAAI,IAAI,CAAC;IAChB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAID,wBAAgB,QAAQ,IAAI,QAAQ,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAehE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,QAAQ,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGnF;AAED,wFAAwF;AACxF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,kBAAkB,GAAG,SAAS,EAAE,QAAQ,EAAE,aAAa,CAAC;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,MAAM,CAsBnM;AAED,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,uBAA4B,GAAG,sBAAsB,CAsErG"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
const EXTENSIONS = ["EXT_color_buffer_float", "OES_texture_float_linear", "WEBGL_multi_draw", "EXT_disjoint_timer_query_webgl2"];
|
|
2
|
+
export function probeGpu() {
|
|
3
|
+
try {
|
|
4
|
+
const gl = document.createElement("canvas").getContext("webgl2");
|
|
5
|
+
if (!gl)
|
|
6
|
+
return { error: "webgl2: unavailable" };
|
|
7
|
+
const info = gl.getExtension("WEBGL_debug_renderer_info");
|
|
8
|
+
return {
|
|
9
|
+
renderer: String(info ? gl.getParameter(info.UNMASKED_RENDERER_WEBGL) : gl.getParameter(gl.RENDERER)),
|
|
10
|
+
limits: `maxTex ${gl.getParameter(gl.MAX_TEXTURE_SIZE)} units ${gl.getParameter(gl.MAX_TEXTURE_IMAGE_UNITS)} samples ${gl.getParameter(gl.MAX_SAMPLES)} fragUniforms ${gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS)} varyings ${gl.getParameter(gl.MAX_VARYING_VECTORS)}`,
|
|
11
|
+
extensions: EXTENSIONS.map((name) => `${name.replace(/^(EXT|OES|WEBGL)_/, "")}:${gl.getExtension(name) ? "y" : "n"}`).join(" "),
|
|
12
|
+
webgpu: "gpu" in navigator,
|
|
13
|
+
dpr: globalThis.devicePixelRatio ?? 1
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
return { error: `webgl2 probe failed: ${String(error.message)}` };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function formatGpuProbe(probe) {
|
|
21
|
+
if ("error" in probe)
|
|
22
|
+
return probe.error;
|
|
23
|
+
return `gpu: ${probe.renderer}\n${probe.limits}\n${probe.extensions} navigator.gpu:${probe.webgpu ? "y" : "n"} dpr ${probe.dpr}`;
|
|
24
|
+
}
|
|
25
|
+
/** Pure formatter for the engine section so it can be unit tested without a browser. */
|
|
26
|
+
export function formatEngineSection(app, canvases) {
|
|
27
|
+
const parts = [];
|
|
28
|
+
try {
|
|
29
|
+
const report = app?.diagnostics?.();
|
|
30
|
+
if (report) {
|
|
31
|
+
if (report.backend !== undefined)
|
|
32
|
+
parts.push(`backend=${String(report.backend)}`);
|
|
33
|
+
if (report.drawCalls !== undefined)
|
|
34
|
+
parts.push(`drawCalls=${String(report.drawCalls)}`);
|
|
35
|
+
if (report.fps !== undefined)
|
|
36
|
+
parts.push(`fps=${Number(report.fps).toFixed(0)}`);
|
|
37
|
+
for (const warning of (report.warnings ?? []).slice(0, 3))
|
|
38
|
+
parts.push(`warn:${String(warning).slice(0, 80)}`);
|
|
39
|
+
for (const error of (report.errors ?? []).slice(0, 3))
|
|
40
|
+
parts.push(`error:${String(error).slice(0, 80)}`);
|
|
41
|
+
for (const failure of (report.shaderFailures ?? []).slice(0, 2)) {
|
|
42
|
+
const first = failure.locations?.[0];
|
|
43
|
+
const offending = first?.window?.find((row) => row.error)?.text?.trim();
|
|
44
|
+
const where = first ? ` ${failure.stage ?? ""} line ${first.line}${first.authoredLine !== undefined ? ` (source line ${first.authoredLine})` : ""}` : ` ${failure.stage ?? ""}`;
|
|
45
|
+
parts.push(`\nSHADER ${failure.code ?? "FAILED"} "${failure.material ?? "?"}"${where}: ${String(first?.message ?? failure.message ?? "").slice(0, 100)}${offending ? ` >> ${offending.slice(0, 100)}` : ""}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
parts.push("diagnostics() threw");
|
|
51
|
+
}
|
|
52
|
+
const sizes = canvases.map((c) => `${c.id || "canvas"} ${c.width}x${c.height} (css ${c.clientWidth}x${c.clientHeight})`).join("; ");
|
|
53
|
+
return `engine: ${parts.join(" ") || "no diagnostics exposed"}\ncanvas: ${sizes}`;
|
|
54
|
+
}
|
|
55
|
+
export function installDiagnosticsPanel(options = {}) {
|
|
56
|
+
const lines = [];
|
|
57
|
+
const maxLines = options.maxLines ?? 14;
|
|
58
|
+
const restore = [];
|
|
59
|
+
const push = (line) => {
|
|
60
|
+
lines.push(line.slice(0, 220));
|
|
61
|
+
while (lines.length > maxLines)
|
|
62
|
+
lines.shift();
|
|
63
|
+
};
|
|
64
|
+
const originalError = console.error;
|
|
65
|
+
const originalWarn = console.warn;
|
|
66
|
+
console.error = (...args) => { push(`error: ${args.map(String).join(" ")}`); originalError.apply(console, args); };
|
|
67
|
+
console.warn = (...args) => { push(`warn: ${args.map(String).join(" ")}`); originalWarn.apply(console, args); };
|
|
68
|
+
restore.push(() => { console.error = originalError; console.warn = originalWarn; });
|
|
69
|
+
const onError = (event) => push(`uncaught: ${event.message}`);
|
|
70
|
+
const onRejection = (event) => push(`rejection: ${String(event.reason?.message ?? event.reason)}`);
|
|
71
|
+
window.addEventListener("error", onError);
|
|
72
|
+
window.addEventListener("unhandledrejection", onRejection);
|
|
73
|
+
restore.push(() => { window.removeEventListener("error", onError); window.removeEventListener("unhandledrejection", onRejection); });
|
|
74
|
+
const proto = globalThis.WebGL2RenderingContext?.prototype;
|
|
75
|
+
if (proto) {
|
|
76
|
+
const compile = proto.compileShader;
|
|
77
|
+
const link = proto.linkProgram;
|
|
78
|
+
proto.compileShader = function (shader) {
|
|
79
|
+
compile.call(this, shader);
|
|
80
|
+
if (!this.getShaderParameter(shader, this.COMPILE_STATUS))
|
|
81
|
+
push(`SHADER COMPILE FAILED: ${(this.getShaderInfoLog(shader) ?? "").replace(/\s+/g, " ")}`);
|
|
82
|
+
};
|
|
83
|
+
proto.linkProgram = function (program) {
|
|
84
|
+
link.call(this, program);
|
|
85
|
+
if (!this.getProgramParameter(program, this.LINK_STATUS))
|
|
86
|
+
push(`PROGRAM LINK FAILED: ${(this.getProgramInfoLog(program) ?? "").replace(/\s+/g, " ")}`);
|
|
87
|
+
};
|
|
88
|
+
restore.push(() => { proto.compileShader = compile; proto.linkProgram = link; });
|
|
89
|
+
}
|
|
90
|
+
const getContext = HTMLCanvasElement.prototype.getContext;
|
|
91
|
+
HTMLCanvasElement.prototype.getContext = function (...args) {
|
|
92
|
+
const context = getContext.apply(this, args);
|
|
93
|
+
if (context && !this.__auraSafetyWatched) {
|
|
94
|
+
this.__auraSafetyWatched = true;
|
|
95
|
+
this.addEventListener("webglcontextlost", () => push("WEBGL CONTEXT LOST"));
|
|
96
|
+
}
|
|
97
|
+
return context;
|
|
98
|
+
};
|
|
99
|
+
restore.push(() => { HTMLCanvasElement.prototype.getContext = getContext; });
|
|
100
|
+
const panel = document.createElement("pre");
|
|
101
|
+
panel.setAttribute("data-aura3d-safety-panel", "");
|
|
102
|
+
panel.style.cssText = "position:fixed;left:8px;top:8px;z-index:2147483001;max-width:min(720px,calc(100vw - 16px));margin:0;padding:6px 9px;border-radius:6px;background:rgba(0,0,0,.78);color:#9dffb0;font:400 11px/1.35 ui-monospace,Menlo,monospace;white-space:pre-wrap;pointer-events:none";
|
|
103
|
+
document.body.appendChild(panel);
|
|
104
|
+
restore.push(() => panel.remove());
|
|
105
|
+
const staticInfo = formatGpuProbe(probeGpu());
|
|
106
|
+
const refresh = () => {
|
|
107
|
+
const canvases = Array.from(document.querySelectorAll("canvas"));
|
|
108
|
+
const extra = options.extraLines?.() ?? [];
|
|
109
|
+
panel.textContent = `${options.title ?? "Aura3D diagnostics"}\n${staticInfo}\n${formatEngineSection(options.app, canvases)}${extra.length ? `\n${extra.join("\n")}` : ""}\n${lines.length ? lines.join("\n") : "no errors captured"}`;
|
|
110
|
+
};
|
|
111
|
+
refresh();
|
|
112
|
+
const timer = setInterval(refresh, options.refreshMs ?? 1000);
|
|
113
|
+
restore.push(() => clearInterval(timer));
|
|
114
|
+
return {
|
|
115
|
+
lines,
|
|
116
|
+
refresh,
|
|
117
|
+
dispose() {
|
|
118
|
+
for (const undo of restore.reverse())
|
|
119
|
+
undo();
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=diagnosticsPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnosticsPanel.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/diagnosticsPanel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { createBlackFrameWatch, type BlackFrameWatch, type WatchObservation } from "./blackFrame.js";
|
|
2
|
+
/**
|
|
3
|
+
* Black-frame guard for pages that run on the engine's `a3d-qr` URL flag list (the showcase games). It installs once,
|
|
4
|
+
* before the app starts drawing, wraps `requestAnimationFrame` so the world canvas is sampled right after each frame
|
|
5
|
+
* callback (same task, before the browser composites), and reloads one rung down when the canvas stays black. It is a
|
|
6
|
+
* thin shell around `createBlackFrameWatch`: readiness gating, black-versus-dark detection, once-per-load stepping and
|
|
7
|
+
* the recorded reason all live there.
|
|
8
|
+
*
|
|
9
|
+
* `?heal=0` disables it; an `a3d-qr` supplied in the URL by the author or player is never rewritten.
|
|
10
|
+
*/
|
|
11
|
+
export declare const QR_HEAL_LADDER: ReadonlyArray<{
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly qr: string;
|
|
14
|
+
}>;
|
|
15
|
+
/** Rung currently applied (0 = full quality) from the stored value. */
|
|
16
|
+
export declare function qrHealStage(raw: string | null | undefined): number;
|
|
17
|
+
export declare const qrHealRungName: (stage: number) => string;
|
|
18
|
+
/**
|
|
19
|
+
* URL for rung `stage`, or `null` when the ladder is exhausted or an author/player supplied their own `a3d-qr`.
|
|
20
|
+
* `ownsQr` is true when the `a3d-qr` already in the URL was written by an earlier rung of this guard.
|
|
21
|
+
*/
|
|
22
|
+
export declare function qrHealUrl(href: string, stage: number, ownsQr?: boolean): string | null;
|
|
23
|
+
export interface HealGlobal {
|
|
24
|
+
rung: number;
|
|
25
|
+
name: string;
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
/** Live view of what the watch has seen (frames, samples, last probe stats, skips) and why a reload happened. */
|
|
28
|
+
observation?: () => WatchObservation;
|
|
29
|
+
}
|
|
30
|
+
declare global {
|
|
31
|
+
interface Window {
|
|
32
|
+
__AURA3D_HEAL__?: HealGlobal;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export interface BlackFrameGuardOptions {
|
|
36
|
+
/** Defaults to true unless the URL has `heal=0`. */
|
|
37
|
+
readonly enabled?: boolean;
|
|
38
|
+
/** Tests only: shorter detection window. */
|
|
39
|
+
readonly fast?: boolean;
|
|
40
|
+
/** Extra readiness signal, for example the app's own `ready` flag. Combined with the built-in overlay/load/fetch checks. */
|
|
41
|
+
readonly isReady?: () => boolean;
|
|
42
|
+
/** Engine draw calls for the current frame; when given and not > 0 the frame is not judged. */
|
|
43
|
+
readonly getDrawCalls?: () => number | undefined;
|
|
44
|
+
/** Which canvas to judge. Defaults to the largest non-HUD canvas on the page. */
|
|
45
|
+
readonly canvas?: () => HTMLCanvasElement | null | undefined;
|
|
46
|
+
/** Test hooks forwarded to the watch (clock, probe, storage, navigation, logging). */
|
|
47
|
+
readonly watch?: Partial<Pick<Parameters<typeof createBlackFrameWatch>[1], "now" | "readProbe" | "storage" | "navigate" | "log" | "isHidden" | "currentUrl" | "minBlackMs" | "blackFramesBudget" | "minFramesAfterReady" | "sampleEvery" | "samplesNeeded">>;
|
|
48
|
+
}
|
|
49
|
+
/** Returns the watch (or undefined when disabled/unavailable) so callers and tests can read its observation. */
|
|
50
|
+
export declare function installBlackFrameGuard(options?: BlackFrameGuardOptions): BlackFrameWatch | undefined;
|
|
51
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/guard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAiC,KAAK,eAAe,EAAiB,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnJ;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAIxF,CAAC;AAIF,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAGlE;AAED,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MAAuC,CAAC;AAEvF;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,UAAQ,GAAG,MAAM,GAAG,IAAI,CAMpF;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,iHAAiH;IACjH,WAAW,CAAC,EAAE,MAAM,gBAAgB,CAAC;CACtC;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd,eAAe,CAAC,EAAE,UAAU,CAAC;KAC9B;CACF;AAED,MAAM,WAAW,sBAAsB;IACrC,oDAAoD;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,4HAA4H;IAC5H,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;IACjC,+FAA+F;IAC/F,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IACjD,iFAAiF;IACjF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,iBAAiB,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7D,sFAAsF;IACtF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,GAAG,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,aAAa,GAAG,eAAe,CAAC,CAAC,CAAC;CAC9P;AAED,gHAAgH;AAChH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,sBAA2B,GAAG,eAAe,GAAG,SAAS,CAyBxG"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createBlackFrameWatch, findWorldCanvas, healRungName } from "./blackFrame.js";
|
|
2
|
+
/**
|
|
3
|
+
* Black-frame guard for pages that run on the engine's `a3d-qr` URL flag list (the showcase games). It installs once,
|
|
4
|
+
* before the app starts drawing, wraps `requestAnimationFrame` so the world canvas is sampled right after each frame
|
|
5
|
+
* callback (same task, before the browser composites), and reloads one rung down when the canvas stays black. It is a
|
|
6
|
+
* thin shell around `createBlackFrameWatch`: readiness gating, black-versus-dark detection, once-per-load stepping and
|
|
7
|
+
* the recorded reason all live there.
|
|
8
|
+
*
|
|
9
|
+
* `?heal=0` disables it; an `a3d-qr` supplied in the URL by the author or player is never rewritten.
|
|
10
|
+
*/
|
|
11
|
+
export const QR_HEAL_LADDER = [
|
|
12
|
+
{ name: "no-vfx-fog", qr: "-vfxFog" },
|
|
13
|
+
{ name: "no-post", qr: "-vfxFog,-post" },
|
|
14
|
+
{ name: "legacy-compile", qr: "-vfxFog,-post,-compiler" }
|
|
15
|
+
];
|
|
16
|
+
const QR_RUNGS = QR_HEAL_LADDER.map((rung) => ({ name: rung.name, params: { "a3d-qr": `game,${rung.qr}` } }));
|
|
17
|
+
/** Rung currently applied (0 = full quality) from the stored value. */
|
|
18
|
+
export function qrHealStage(raw) {
|
|
19
|
+
const n = Number(raw ?? "0");
|
|
20
|
+
return Number.isInteger(n) && n >= 0 && n <= QR_HEAL_LADDER.length ? n : 0;
|
|
21
|
+
}
|
|
22
|
+
export const qrHealRungName = (stage) => healRungName(stage, QR_RUNGS);
|
|
23
|
+
/**
|
|
24
|
+
* URL for rung `stage`, or `null` when the ladder is exhausted or an author/player supplied their own `a3d-qr`.
|
|
25
|
+
* `ownsQr` is true when the `a3d-qr` already in the URL was written by an earlier rung of this guard.
|
|
26
|
+
*/
|
|
27
|
+
export function qrHealUrl(href, stage, ownsQr = false) {
|
|
28
|
+
if (stage < 1 || stage > QR_HEAL_LADDER.length)
|
|
29
|
+
return null;
|
|
30
|
+
const url = new URL(href);
|
|
31
|
+
if (url.searchParams.has("a3d-qr") && !ownsQr)
|
|
32
|
+
return null;
|
|
33
|
+
url.searchParams.set("a3d-qr", `game,${QR_HEAL_LADDER[stage - 1].qr}`);
|
|
34
|
+
return url.toString();
|
|
35
|
+
}
|
|
36
|
+
/** Returns the watch (or undefined when disabled/unavailable) so callers and tests can read its observation. */
|
|
37
|
+
export function installBlackFrameGuard(options = {}) {
|
|
38
|
+
if (typeof window === "undefined" || window.__AURA3D_HEAL_INSTALLED__)
|
|
39
|
+
return undefined;
|
|
40
|
+
window.__AURA3D_HEAL_INSTALLED__ = true;
|
|
41
|
+
const params = new URLSearchParams(location.search);
|
|
42
|
+
const enabled = options.enabled ?? params.get("heal") !== "0";
|
|
43
|
+
const key = `aura3d-heal:${location.pathname}`;
|
|
44
|
+
const watch = createBlackFrameWatch(options.canvas ?? (() => findWorldCanvas()), {
|
|
45
|
+
enabled,
|
|
46
|
+
ladder: QR_RUNGS,
|
|
47
|
+
storageKey: key,
|
|
48
|
+
...(options.fast ? { fastFrames: 6 } : {}),
|
|
49
|
+
...(options.isReady ? { isReady: options.isReady } : {}),
|
|
50
|
+
...(options.getDrawCalls ? { getDrawCalls: options.getDrawCalls } : {}),
|
|
51
|
+
buildUrl: (next, href) => qrHealUrl(href, next, next > 1),
|
|
52
|
+
...(options.watch ?? {})
|
|
53
|
+
});
|
|
54
|
+
window.__AURA3D_HEAL__ = { rung: watch.stage, name: qrHealRungName(watch.stage), enabled, observation: () => watch.observation() };
|
|
55
|
+
if (!enabled)
|
|
56
|
+
return watch;
|
|
57
|
+
const originalRaf = window.requestAnimationFrame.bind(window);
|
|
58
|
+
window.requestAnimationFrame = (callback) => originalRaf((time) => {
|
|
59
|
+
callback(time);
|
|
60
|
+
watch.sample();
|
|
61
|
+
});
|
|
62
|
+
return watch;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type BlackFrameWatchOptions, type HealRung, type WatchObservation } from "./blackFrame.js";
|
|
2
|
+
import { type DiagnosticsAppLike } from "./diagnosticsPanel.js";
|
|
3
|
+
import { type QualitySwitches } from "./switches.js";
|
|
4
|
+
export * from "./blackFrame.js";
|
|
5
|
+
export * from "./guard.js";
|
|
6
|
+
export * from "./diagnosticsPanel.js";
|
|
7
|
+
export * from "./switches.js";
|
|
8
|
+
export interface SafetyNetOptions {
|
|
9
|
+
/** Must be true (or an options object) for anything to run: the safety net is never on by default. */
|
|
10
|
+
readonly safety: boolean | SafetySettings;
|
|
11
|
+
readonly canvas?: HTMLCanvasElement;
|
|
12
|
+
readonly app?: DiagnosticsAppLike;
|
|
13
|
+
/** Query string to read switches from; defaults to `location.search`. */
|
|
14
|
+
readonly search?: string | URLSearchParams;
|
|
15
|
+
}
|
|
16
|
+
export interface SafetySettings {
|
|
17
|
+
/** Reload one rung down when the canvas stays black. Default true; `?heal=0` still wins. */
|
|
18
|
+
readonly selfHeal?: boolean;
|
|
19
|
+
/** Show the diagnostics panel. Default: only when the URL has `?diag=1`. */
|
|
20
|
+
readonly panel?: boolean | "query";
|
|
21
|
+
readonly ladder?: readonly HealRung[];
|
|
22
|
+
readonly watch?: Pick<BlackFrameWatchOptions, "fastFrames" | "readProbe" | "storage" | "currentUrl" | "navigate" | "storageKey" | "log" | "isReady" | "getDrawCalls" | "now" | "isHidden" | "minBlackMs" | "blackFramesBudget" | "minFramesAfterReady" | "sampleEvery" | "samplesNeeded">;
|
|
23
|
+
}
|
|
24
|
+
export interface SafetyReport {
|
|
25
|
+
readonly enabled: boolean;
|
|
26
|
+
readonly stage: number;
|
|
27
|
+
readonly rung: string;
|
|
28
|
+
readonly escalated: boolean;
|
|
29
|
+
readonly switches: QualitySwitches;
|
|
30
|
+
readonly panel: boolean;
|
|
31
|
+
/** What the black-frame watch has seen (frames, probe stats, skips) and why a reload happened; undefined without a watch. */
|
|
32
|
+
readonly observed?: WatchObservation;
|
|
33
|
+
}
|
|
34
|
+
export interface SafetyNet {
|
|
35
|
+
/** Switches in force (explicit URL parameters, then the black-frame rung's parameters). */
|
|
36
|
+
readonly switches: QualitySwitches;
|
|
37
|
+
/** Call after every presented frame with the running frame count. */
|
|
38
|
+
sample(framesDrawn: number): void;
|
|
39
|
+
/** What the safety net did; also exposed as `globalThis.__AURA_SAFETY__` while installed. */
|
|
40
|
+
report(): SafetyReport;
|
|
41
|
+
dispose(): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Opt-in runtime safety net for real-device failures: quality URL switches, black-frame self-heal and the diagnostics panel.
|
|
45
|
+
* Returns an inert handle (switches still parsed) unless `safety` is truthy. Reports through stable console codes
|
|
46
|
+
* (`SAFETY_COMPAT_MODE`, `SAFETY_BLACK_FRAME`), `report()` and the panel; `AuraApp.diagnostics()` is a read-only snapshot,
|
|
47
|
+
* so the safety net does not write into it.
|
|
48
|
+
*/
|
|
49
|
+
export declare function installSafetyNet(options: SafetyNetOptions): SafetyNet;
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6F,KAAK,sBAAsB,EAAE,KAAK,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC/L,OAAO,EAA2B,KAAK,kBAAkB,EAA+B,MAAM,uBAAuB,CAAC;AACtH,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAE7E,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC;AAC3B,cAAc,uBAAuB,CAAC;AACtC,cAAc,eAAe,CAAC;AAE9B,MAAM,WAAW,gBAAgB;IAC/B,sGAAsG;IACtG,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,cAAc,CAAC;IAC1C,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,EAAE,kBAAkB,CAAC;IAClC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;CAC5C;AAED,MAAM,WAAW,cAAc;IAC7B,4FAA4F;IAC5F,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,sBAAsB,EAAE,YAAY,GAAG,WAAW,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,YAAY,GAAG,KAAK,GAAG,SAAS,GAAG,cAAc,GAAG,KAAK,GAAG,UAAU,GAAG,YAAY,GAAG,mBAAmB,GAAG,qBAAqB,GAAG,aAAa,GAAG,eAAe,CAAC,CAAC;CAC3R;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,6HAA6H;IAC7H,QAAQ,CAAC,QAAQ,CAAC,EAAE,gBAAgB,CAAC;CACtC;AAED,MAAM,WAAW,SAAS;IACxB,2FAA2F;IAC3F,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;IACnC,qEAAqE;IACrE,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,6FAA6F;IAC7F,MAAM,IAAI,YAAY,CAAC;IACvB,OAAO,IAAI,IAAI,CAAC;CACjB;AAID;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,SAAS,CAsDrE"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createBlackFrameWatch, DEFAULT_HEAL_LADDER, healRungName, healStage } from "./blackFrame.js";
|
|
2
|
+
import { installDiagnosticsPanel } from "./diagnosticsPanel.js";
|
|
3
|
+
import { resolveQualitySwitches } from "./switches.js";
|
|
4
|
+
export * from "./blackFrame.js";
|
|
5
|
+
export * from "./guard.js";
|
|
6
|
+
export * from "./diagnosticsPanel.js";
|
|
7
|
+
export * from "./switches.js";
|
|
8
|
+
const NOOP_REPORT = (switches) => ({ enabled: false, stage: 0, rung: "full", escalated: false, switches, panel: false });
|
|
9
|
+
/**
|
|
10
|
+
* Opt-in runtime safety net for real-device failures: quality URL switches, black-frame self-heal and the diagnostics panel.
|
|
11
|
+
* Returns an inert handle (switches still parsed) unless `safety` is truthy. Reports through stable console codes
|
|
12
|
+
* (`SAFETY_COMPAT_MODE`, `SAFETY_BLACK_FRAME`), `report()` and the panel; `AuraApp.diagnostics()` is a read-only snapshot,
|
|
13
|
+
* so the safety net does not write into it.
|
|
14
|
+
*/
|
|
15
|
+
export function installSafetyNet(options) {
|
|
16
|
+
const settings = typeof options.safety === "object" ? options.safety : {};
|
|
17
|
+
const enabled = options.safety !== false && options.safety !== undefined;
|
|
18
|
+
const ladder = settings.ladder ?? DEFAULT_HEAL_LADDER;
|
|
19
|
+
const stage = enabled ? healStage(settings.watch?.storage, ladder, settings.watch?.storageKey) : 0;
|
|
20
|
+
const switches = resolveQualitySwitches({ search: options.search, healStage: stage, ladder });
|
|
21
|
+
if (!enabled) {
|
|
22
|
+
return { switches, sample() { }, report: () => NOOP_REPORT(switches), dispose() { } };
|
|
23
|
+
}
|
|
24
|
+
let watch;
|
|
25
|
+
if (options.canvas && settings.selfHeal !== false) {
|
|
26
|
+
watch = createBlackFrameWatch(options.canvas, { enabled: switches.heal, ladder, ...settings.watch });
|
|
27
|
+
}
|
|
28
|
+
const showPanel = settings.panel === true || ((settings.panel === undefined || settings.panel === "query") && switches.diag);
|
|
29
|
+
const report = () => ({
|
|
30
|
+
enabled: true,
|
|
31
|
+
stage: watch?.stage ?? stage,
|
|
32
|
+
rung: watch?.rung ?? healRungName(stage, ladder),
|
|
33
|
+
escalated: watch?.escalated ?? false,
|
|
34
|
+
switches,
|
|
35
|
+
panel: showPanel,
|
|
36
|
+
...(watch ? { observed: watch.observation() } : {})
|
|
37
|
+
});
|
|
38
|
+
let panel;
|
|
39
|
+
if (showPanel && typeof document !== "undefined") {
|
|
40
|
+
panel = installDiagnosticsPanel({
|
|
41
|
+
...(options.app ? { app: options.app } : {}),
|
|
42
|
+
title: "Aura3D safety net (?diag=1)",
|
|
43
|
+
extraLines: () => {
|
|
44
|
+
const r = report();
|
|
45
|
+
const off = ["post", "shadow", "env", "sky", "aa"].filter((key) => !switches[key]);
|
|
46
|
+
const lines = [`safety: rung ${r.stage} (${r.rung})${r.escalated ? " reloading" : ""} off:[${off.join(",")}] quality:${switches.quality} tm:${switches.toneMapping} heal:${switches.heal ? "on" : "off"}`];
|
|
47
|
+
const seen = r.observed ?? globalThis.__AURA3D_HEAL__?.observation?.();
|
|
48
|
+
if (seen) {
|
|
49
|
+
const s = seen.lastStats;
|
|
50
|
+
lines.push(`heal watch: frames ${seen.calls} ready@${seen.readyAtCall ?? "no"} samples ${seen.samples} black ${seen.blackSamples} lit ${s ? `${s.lit}/${s.samples} max ${s.max}` : "n/a"} frame ${Math.round(seen.medianFrameMs)}ms skipped notReady ${seen.skipped.notReady} noDraw ${seen.skipped.noDrawCalls}${seen.healthy ? " healthy" : ""}`);
|
|
51
|
+
if (seen.reason)
|
|
52
|
+
lines.push(`heal reason: ${seen.reason}`);
|
|
53
|
+
}
|
|
54
|
+
return lines;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const g = globalThis;
|
|
59
|
+
g.__AURA_SAFETY__ = report;
|
|
60
|
+
return {
|
|
61
|
+
switches,
|
|
62
|
+
sample: (framesDrawn) => watch?.sample(framesDrawn),
|
|
63
|
+
report,
|
|
64
|
+
dispose() {
|
|
65
|
+
panel?.dispose();
|
|
66
|
+
if (g.__AURA_SAFETY__ === report)
|
|
67
|
+
delete g.__AURA_SAFETY__;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type HealRung } from "./blackFrame.js";
|
|
2
|
+
/**
|
|
3
|
+
* Quality URL switches shared by every game: `?post=0 ?shadow=0 ?env=0 ?sky=0 ?aa=0 ?quality=low ?tm=aces ?heal=0 ?diag=1`.
|
|
4
|
+
* Parsing is pure; a game decides what each switch changes in its own options. Rung parameters from the black-frame
|
|
5
|
+
* ladder are merged UNDER explicit parameters, so an author's URL always wins.
|
|
6
|
+
*/
|
|
7
|
+
export interface QualitySwitches {
|
|
8
|
+
readonly post: boolean;
|
|
9
|
+
readonly shadow: boolean;
|
|
10
|
+
readonly env: boolean;
|
|
11
|
+
readonly sky: boolean;
|
|
12
|
+
readonly aa: boolean;
|
|
13
|
+
readonly heal: boolean;
|
|
14
|
+
readonly diag: boolean;
|
|
15
|
+
readonly quality: "default" | "low";
|
|
16
|
+
readonly toneMapping: "default" | "aces";
|
|
17
|
+
/** The merged query parameters actually used (explicit + ladder). */
|
|
18
|
+
readonly params: Readonly<Record<string, string>>;
|
|
19
|
+
}
|
|
20
|
+
export interface ResolveQualitySwitchesOptions {
|
|
21
|
+
readonly search?: string | URLSearchParams;
|
|
22
|
+
/** Black-frame ladder rung currently in force (0 = none). */
|
|
23
|
+
readonly healStage?: number;
|
|
24
|
+
readonly ladder?: readonly HealRung[];
|
|
25
|
+
}
|
|
26
|
+
export declare function resolveQualitySwitches(options?: ResolveQualitySwitchesOptions): QualitySwitches;
|
|
27
|
+
//# sourceMappingURL=switches.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switches.d.ts","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/switches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmC,KAAK,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEjF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,KAAK,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,SAAS,GAAG,MAAM,CAAC;IACzC,qEAAqE;IACrE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;IAC3C,6DAA6D;IAC7D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,QAAQ,EAAE,CAAC;CACvC;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,6BAAkC,GAAG,eAAe,CAmBnG"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { DEFAULT_HEAL_LADDER, healParams } from "./blackFrame.js";
|
|
2
|
+
export function resolveQualitySwitches(options = {}) {
|
|
3
|
+
const raw = options.search ?? (typeof location === "undefined" ? "" : location.search);
|
|
4
|
+
const query = raw instanceof URLSearchParams ? new URLSearchParams(raw) : new URLSearchParams(raw);
|
|
5
|
+
for (const [key, value] of Object.entries(healParams(options.healStage ?? 0, options.ladder ?? DEFAULT_HEAL_LADDER))) {
|
|
6
|
+
if (!query.has(key))
|
|
7
|
+
query.set(key, value);
|
|
8
|
+
}
|
|
9
|
+
const off = (key) => query.get(key) !== "0";
|
|
10
|
+
return {
|
|
11
|
+
post: off("post"),
|
|
12
|
+
shadow: off("shadow"),
|
|
13
|
+
env: off("env"),
|
|
14
|
+
sky: off("sky"),
|
|
15
|
+
aa: off("aa"),
|
|
16
|
+
heal: off("heal"),
|
|
17
|
+
diag: query.get("diag") === "1",
|
|
18
|
+
quality: query.get("quality") === "low" ? "low" : "default",
|
|
19
|
+
toneMapping: query.get("tm") === "aces" ? "aces" : "default",
|
|
20
|
+
params: Object.fromEntries(query.entries())
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=switches.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switches.js","sourceRoot":"","sources":["../../../../../packages/debug/src/safety/switches.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAiB,MAAM,iBAAiB,CAAC;AA4BjF,MAAM,UAAU,sBAAsB,CAAC,UAAyC,EAAE;IAChF,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACvF,MAAM,KAAK,GAAG,GAAG,YAAY,eAAe,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;IACnG,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,EAAE,OAAO,CAAC,MAAM,IAAI,mBAAmB,CAAC,CAAC,EAAE,CAAC;QACrH,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC7C,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC;IAC7D,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;QACjB,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC;QACrB,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QACf,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QACf,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC;QACjB,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG;QAC/B,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;QAC3D,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC5D,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;KAC5C,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aura3d/debug",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@aura3d/animation": "4.
|
|
7
|
-
"@aura3d/rendering": "4.
|
|
8
|
-
"@aura3d/physics": "4.
|
|
6
|
+
"@aura3d/animation": "4.1.1",
|
|
7
|
+
"@aura3d/rendering": "4.1.1",
|
|
8
|
+
"@aura3d/physics": "4.1.1"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|