@vib3code/sdk 2.0.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.
Files changed (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,381 @@
1
+ /**
2
+ * BenchmarkRunner - Run performance benchmarks on VIB3+ engine
3
+ *
4
+ * Executes standardized benchmark scenes and collects metrics
5
+ * for performance analysis and regression detection.
6
+ */
7
+
8
+ import { MetricsCollector } from './MetricsCollector.js';
9
+ import { BENCHMARK_SCENES } from './scenes.js';
10
+
11
+ /**
12
+ * Default benchmark options
13
+ */
14
+ const DEFAULT_OPTIONS = {
15
+ duration: 10000, // 10 seconds per scene
16
+ warmupDuration: 2000, // 2 second warmup
17
+ platform: 'desktop',
18
+ verbose: false
19
+ };
20
+
21
+ /**
22
+ * Platform-specific thresholds
23
+ */
24
+ const PLATFORM_THRESHOLDS = {
25
+ desktop: {
26
+ maxFrameTime: 11, // 90 FPS
27
+ minFPS: 90,
28
+ maxMemory: 200
29
+ },
30
+ mobile: {
31
+ maxFrameTime: 14, // 72 FPS
32
+ minFPS: 72,
33
+ maxMemory: 100
34
+ },
35
+ web: {
36
+ maxFrameTime: 16.67, // 60 FPS
37
+ minFPS: 60,
38
+ maxMemory: 150
39
+ }
40
+ };
41
+
42
+ /**
43
+ * Benchmark runner for VIB3+ engine
44
+ */
45
+ export class BenchmarkRunner {
46
+ /**
47
+ * Create a benchmark runner
48
+ * @param {object} engine - VIB3+ engine instance
49
+ * @param {object} options - Runner options
50
+ */
51
+ constructor(engine, options = {}) {
52
+ /** @type {object} Engine instance */
53
+ this.engine = engine;
54
+
55
+ /** @type {object} Runner options */
56
+ this.options = { ...DEFAULT_OPTIONS, ...options };
57
+
58
+ /** @type {MetricsCollector} Metrics collector */
59
+ this.collector = new MetricsCollector({
60
+ renderer: engine?.renderer || null
61
+ });
62
+
63
+ /** @type {Array<object>} Benchmark results */
64
+ this.results = [];
65
+
66
+ /** @type {boolean} Running state */
67
+ this.running = false;
68
+
69
+ /** @type {Function|null} Frame callback */
70
+ this._frameCallback = null;
71
+ }
72
+
73
+ /**
74
+ * Run a single benchmark scene
75
+ * @param {string} sceneName - Name of scene from BENCHMARK_SCENES
76
+ * @param {number} duration - Duration in milliseconds
77
+ * @returns {Promise<object>} Benchmark result
78
+ */
79
+ async runBenchmark(sceneName, duration = this.options.duration) {
80
+ const scene = BENCHMARK_SCENES[sceneName];
81
+ if (!scene) {
82
+ throw new Error(`Unknown benchmark scene: ${sceneName}`);
83
+ }
84
+
85
+ if (this.options.verbose) {
86
+ console.log(`Running benchmark: ${scene.name}`);
87
+ }
88
+
89
+ // Configure scene
90
+ if (this.engine?.setParameters) {
91
+ this.engine.setParameters(scene.params);
92
+ }
93
+
94
+ this.collector.reset();
95
+ this.running = true;
96
+
97
+ // Warmup phase
98
+ if (this.options.verbose) {
99
+ console.log(` Warmup: ${this.options.warmupDuration}ms`);
100
+ }
101
+ await this._runFrames(this.options.warmupDuration);
102
+ this.collector.reset();
103
+
104
+ // Measurement phase
105
+ if (this.options.verbose) {
106
+ console.log(` Measuring: ${duration}ms`);
107
+ }
108
+ await this._runFrames(duration);
109
+
110
+ this.running = false;
111
+
112
+ // Collect results
113
+ const stats = this.collector.getStats();
114
+ const thresholds = PLATFORM_THRESHOLDS[this.options.platform] || PLATFORM_THRESHOLDS.desktop;
115
+ const passed = this._evaluateThresholds(stats, thresholds);
116
+
117
+ const result = {
118
+ scene: sceneName,
119
+ sceneName: scene.name,
120
+ description: scene.description,
121
+ params: scene.params,
122
+ duration,
123
+ ...stats,
124
+ timestamp: new Date().toISOString(),
125
+ platform: this.options.platform,
126
+ thresholds,
127
+ passed
128
+ };
129
+
130
+ this.results.push(result);
131
+
132
+ if (this.options.verbose) {
133
+ const status = passed.overall ? '✓ PASS' : '✗ FAIL';
134
+ console.log(` Result: ${status} (${stats.fps.avg.toFixed(1)} FPS, ${stats.frameTime.p95.toFixed(2)}ms p95)`);
135
+ }
136
+
137
+ return result;
138
+ }
139
+
140
+ /**
141
+ * Run frames for specified duration
142
+ * @private
143
+ */
144
+ async _runFrames(duration) {
145
+ return new Promise((resolve) => {
146
+ const startTime = performance.now();
147
+
148
+ const frame = () => {
149
+ if (!this.running || performance.now() - startTime >= duration) {
150
+ resolve();
151
+ return;
152
+ }
153
+
154
+ this.collector.beginFrame();
155
+
156
+ // Render frame if engine available
157
+ if (this.engine?.renderFrame) {
158
+ this.engine.renderFrame();
159
+ } else if (this.engine?.render) {
160
+ this.engine.render();
161
+ }
162
+
163
+ this.collector.endFrame();
164
+
165
+ // Use requestAnimationFrame for realistic timing
166
+ if (typeof requestAnimationFrame !== 'undefined') {
167
+ requestAnimationFrame(frame);
168
+ } else {
169
+ setImmediate(frame);
170
+ }
171
+ };
172
+
173
+ frame();
174
+ });
175
+ }
176
+
177
+ /**
178
+ * Evaluate results against thresholds
179
+ * @private
180
+ */
181
+ _evaluateThresholds(stats, thresholds) {
182
+ if (!stats) {
183
+ return { overall: false, frameTime: false, fps: false, memory: false };
184
+ }
185
+
186
+ const results = {
187
+ frameTime: stats.frameTime.p95 <= thresholds.maxFrameTime,
188
+ fps: stats.fps.avg >= thresholds.minFPS,
189
+ memory: !stats.memory || stats.memory.used <= thresholds.maxMemory
190
+ };
191
+
192
+ results.overall = results.frameTime && results.fps && results.memory;
193
+
194
+ return results;
195
+ }
196
+
197
+ /**
198
+ * Run all benchmark scenes
199
+ * @param {number} duration - Duration per scene
200
+ * @returns {Promise<object>} All results
201
+ */
202
+ async runAllBenchmarks(duration = this.options.duration) {
203
+ const results = {};
204
+ const sceneNames = Object.keys(BENCHMARK_SCENES);
205
+
206
+ if (this.options.verbose) {
207
+ console.log(`Running ${sceneNames.length} benchmark scenes...`);
208
+ }
209
+
210
+ for (const sceneName of sceneNames) {
211
+ try {
212
+ results[sceneName] = await this.runBenchmark(sceneName, duration);
213
+ } catch (error) {
214
+ results[sceneName] = {
215
+ scene: sceneName,
216
+ error: error.message,
217
+ passed: { overall: false }
218
+ };
219
+ }
220
+ }
221
+
222
+ return results;
223
+ }
224
+
225
+ /**
226
+ * Run benchmarks matching a pattern
227
+ * @param {string|RegExp} pattern - Scene name pattern
228
+ * @param {number} duration - Duration per scene
229
+ * @returns {Promise<object>}
230
+ */
231
+ async runMatchingBenchmarks(pattern, duration = this.options.duration) {
232
+ const regex = pattern instanceof RegExp ? pattern : new RegExp(pattern);
233
+ const matchingScenes = Object.keys(BENCHMARK_SCENES).filter(name => regex.test(name));
234
+
235
+ const results = {};
236
+ for (const sceneName of matchingScenes) {
237
+ results[sceneName] = await this.runBenchmark(sceneName, duration);
238
+ }
239
+ return results;
240
+ }
241
+
242
+ /**
243
+ * Compare current results against a baseline
244
+ * @param {object} baseline - Baseline results
245
+ * @param {number} threshold - Regression threshold (e.g., 0.15 = 15%)
246
+ * @returns {object} Comparison results
247
+ */
248
+ compareToBaseline(baseline, threshold = 0.15) {
249
+ const comparisons = {};
250
+
251
+ for (const result of this.results) {
252
+ const baselineResult = baseline.results?.[result.scene];
253
+ if (!baselineResult) {
254
+ comparisons[result.scene] = {
255
+ status: 'new',
256
+ message: 'No baseline for comparison'
257
+ };
258
+ continue;
259
+ }
260
+
261
+ const frameTimeRatio = result.frameTime.avg / baselineResult.frameTime.avg;
262
+ const fpsRatio = baselineResult.fps.avg / result.fps.avg;
263
+
264
+ const regression = frameTimeRatio > (1 + threshold) || fpsRatio > (1 + threshold);
265
+
266
+ comparisons[result.scene] = {
267
+ status: regression ? 'regression' : 'pass',
268
+ frameTimeRatio: frameTimeRatio.toFixed(3),
269
+ fpsRatio: fpsRatio.toFixed(3),
270
+ threshold,
271
+ current: {
272
+ frameTime: result.frameTime.avg,
273
+ fps: result.fps.avg
274
+ },
275
+ baseline: {
276
+ frameTime: baselineResult.frameTime.avg,
277
+ fps: baselineResult.fps.avg
278
+ }
279
+ };
280
+ }
281
+
282
+ const hasRegression = Object.values(comparisons).some(c => c.status === 'regression');
283
+
284
+ return {
285
+ overall: hasRegression ? 'regression' : 'pass',
286
+ threshold,
287
+ comparisons
288
+ };
289
+ }
290
+
291
+ /**
292
+ * Export results as report
293
+ * @returns {object}
294
+ */
295
+ exportReport() {
296
+ const passedCount = this.results.filter(r => r.passed?.overall).length;
297
+ const failedCount = this.results.length - passedCount;
298
+
299
+ return {
300
+ generated: new Date().toISOString(),
301
+ platform: this.detectPlatform(),
302
+ summary: {
303
+ total: this.results.length,
304
+ passed: passedCount,
305
+ failed: failedCount
306
+ },
307
+ results: this.results.reduce((acc, r) => {
308
+ acc[r.scene] = r;
309
+ return acc;
310
+ }, {})
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Export results as markdown
316
+ * @returns {string}
317
+ */
318
+ exportMarkdown() {
319
+ let md = '# VIB3+ Benchmark Results\n\n';
320
+ md += `**Generated:** ${new Date().toISOString()}\n`;
321
+ md += `**Platform:** ${this.options.platform}\n\n`;
322
+
323
+ md += '## Summary\n\n';
324
+ const passed = this.results.filter(r => r.passed?.overall).length;
325
+ md += `- **Passed:** ${passed}/${this.results.length}\n`;
326
+ md += `- **Failed:** ${this.results.length - passed}/${this.results.length}\n\n`;
327
+
328
+ md += '## Results\n\n';
329
+ md += '| Scene | FPS | Frame Time (p95) | Status |\n';
330
+ md += '|-------|-----|------------------|--------|\n';
331
+
332
+ for (const result of this.results) {
333
+ const status = result.passed?.overall ? '✓ Pass' : '✗ Fail';
334
+ const fps = result.fps?.avg?.toFixed(1) || 'N/A';
335
+ const frameTime = result.frameTime?.p95?.toFixed(2) || 'N/A';
336
+ md += `| ${result.sceneName} | ${fps} | ${frameTime}ms | ${status} |\n`;
337
+ }
338
+
339
+ return md;
340
+ }
341
+
342
+ /**
343
+ * Detect current platform
344
+ * @returns {object}
345
+ */
346
+ detectPlatform() {
347
+ const info = {
348
+ type: this.options.platform,
349
+ timestamp: new Date().toISOString()
350
+ };
351
+
352
+ if (typeof navigator !== 'undefined') {
353
+ info.userAgent = navigator.userAgent;
354
+ info.cores = navigator.hardwareConcurrency || 'unknown';
355
+ info.memory = navigator.deviceMemory || 'unknown';
356
+ }
357
+
358
+ if (this.engine?.getGPUInfo) {
359
+ info.gpu = this.engine.getGPUInfo();
360
+ }
361
+
362
+ return info;
363
+ }
364
+
365
+ /**
366
+ * Clear all results
367
+ */
368
+ clearResults() {
369
+ this.results = [];
370
+ this.collector.reset();
371
+ }
372
+
373
+ /**
374
+ * Stop current benchmark
375
+ */
376
+ stop() {
377
+ this.running = false;
378
+ }
379
+ }
380
+
381
+ export default BenchmarkRunner;
@@ -0,0 +1,299 @@
1
+ /**
2
+ * MetricsCollector - Collect performance metrics for VIB3+ engine
3
+ *
4
+ * Captures frame time, FPS, memory usage, draw calls, and triangle counts
5
+ * for performance analysis and regression detection.
6
+ */
7
+
8
+ /**
9
+ * Performance metrics collector
10
+ */
11
+ export class MetricsCollector {
12
+ constructor(options = {}) {
13
+ /** @type {Array<object>} Sample history */
14
+ this.samples = [];
15
+
16
+ /** @type {number} Total frames counted */
17
+ this.frameCount = 0;
18
+
19
+ /** @type {number} Last frame timestamp */
20
+ this.lastFrameTime = 0;
21
+
22
+ /** @type {number|null} Current frame start time */
23
+ this.frameStart = null;
24
+
25
+ /** @type {object|null} Renderer reference for stats */
26
+ this.renderer = options.renderer || null;
27
+
28
+ /** @type {number} Maximum samples to keep */
29
+ this.maxSamples = options.maxSamples || 1000;
30
+
31
+ /** @type {boolean} Whether to track memory */
32
+ this.trackMemory = options.trackMemory !== false;
33
+
34
+ /** @type {number} Session start time */
35
+ this.sessionStart = performance.now();
36
+ }
37
+
38
+ /**
39
+ * Set renderer reference for draw call/triangle stats
40
+ * @param {object} renderer
41
+ */
42
+ setRenderer(renderer) {
43
+ this.renderer = renderer;
44
+ }
45
+
46
+ /**
47
+ * Mark the beginning of a frame
48
+ */
49
+ beginFrame() {
50
+ this.frameStart = performance.now();
51
+ }
52
+
53
+ /**
54
+ * Mark the end of a frame and record metrics
55
+ */
56
+ endFrame() {
57
+ if (this.frameStart === null) {
58
+ console.warn('MetricsCollector: endFrame called without beginFrame');
59
+ return;
60
+ }
61
+
62
+ const now = performance.now();
63
+ const frameTime = now - this.frameStart;
64
+ this.frameCount++;
65
+
66
+ const sample = {
67
+ timestamp: Date.now(),
68
+ frameNumber: this.frameCount,
69
+ frameTime,
70
+ fps: frameTime > 0 ? 1000 / frameTime : 0,
71
+ memory: this.trackMemory ? this.getMemoryUsage() : null,
72
+ drawCalls: this.getDrawCallCount(),
73
+ triangles: this.getTriangleCount()
74
+ };
75
+
76
+ this.samples.push(sample);
77
+
78
+ // Keep sample buffer bounded
79
+ if (this.samples.length > this.maxSamples) {
80
+ this.samples.shift();
81
+ }
82
+
83
+ this.lastFrameTime = frameTime;
84
+ this.frameStart = null;
85
+
86
+ return sample;
87
+ }
88
+
89
+ /**
90
+ * Get current memory usage (if available)
91
+ * @returns {object|null}
92
+ */
93
+ getMemoryUsage() {
94
+ // Only available in Chrome with --enable-precise-memory-info flag
95
+ if (typeof performance !== 'undefined' && performance.memory) {
96
+ return {
97
+ used: performance.memory.usedJSHeapSize / 1024 / 1024,
98
+ total: performance.memory.totalJSHeapSize / 1024 / 1024,
99
+ limit: performance.memory.jsHeapSizeLimit / 1024 / 1024
100
+ };
101
+ }
102
+ return null;
103
+ }
104
+
105
+ /**
106
+ * Get draw call count from renderer
107
+ * @returns {number}
108
+ */
109
+ getDrawCallCount() {
110
+ if (this.renderer?.stats?.drawCalls !== undefined) {
111
+ return this.renderer.stats.drawCalls;
112
+ }
113
+ if (this.renderer?.getStats) {
114
+ const stats = this.renderer.getStats();
115
+ return stats?.drawCalls ?? 0;
116
+ }
117
+ return 0;
118
+ }
119
+
120
+ /**
121
+ * Get triangle count from renderer
122
+ * @returns {number}
123
+ */
124
+ getTriangleCount() {
125
+ if (this.renderer?.stats?.triangles !== undefined) {
126
+ return this.renderer.stats.triangles;
127
+ }
128
+ if (this.renderer?.getStats) {
129
+ const stats = this.renderer.getStats();
130
+ return stats?.triangles ?? 0;
131
+ }
132
+ return 0;
133
+ }
134
+
135
+ /**
136
+ * Calculate statistics from collected samples
137
+ * @returns {object|null}
138
+ */
139
+ getStats() {
140
+ if (this.samples.length === 0) {
141
+ return null;
142
+ }
143
+
144
+ const frameTimes = this.samples.map(s => s.frameTime);
145
+ const fpsValues = this.samples.map(s => s.fps);
146
+
147
+ return {
148
+ frameTime: {
149
+ min: Math.min(...frameTimes),
150
+ max: Math.max(...frameTimes),
151
+ avg: this.average(frameTimes),
152
+ median: this.median(frameTimes),
153
+ stdDev: this.standardDeviation(frameTimes),
154
+ p50: this.percentile(frameTimes, 50),
155
+ p90: this.percentile(frameTimes, 90),
156
+ p95: this.percentile(frameTimes, 95),
157
+ p99: this.percentile(frameTimes, 99)
158
+ },
159
+ fps: {
160
+ min: Math.min(...fpsValues),
161
+ max: Math.max(...fpsValues),
162
+ avg: this.average(fpsValues),
163
+ median: this.median(fpsValues)
164
+ },
165
+ memory: this.samples[this.samples.length - 1].memory,
166
+ drawCalls: this.samples[this.samples.length - 1].drawCalls,
167
+ triangles: this.samples[this.samples.length - 1].triangles,
168
+ sampleCount: this.samples.length,
169
+ totalFrames: this.frameCount,
170
+ sessionDuration: (performance.now() - this.sessionStart) / 1000
171
+ };
172
+ }
173
+
174
+ /**
175
+ * Calculate percentile of array
176
+ * @param {number[]} arr
177
+ * @param {number} p - Percentile (0-100)
178
+ * @returns {number}
179
+ */
180
+ percentile(arr, p) {
181
+ if (arr.length === 0) return 0;
182
+ const sorted = [...arr].sort((a, b) => a - b);
183
+ const index = Math.ceil((p / 100) * sorted.length) - 1;
184
+ return sorted[Math.max(0, index)];
185
+ }
186
+
187
+ /**
188
+ * Calculate median of array
189
+ * @param {number[]} arr
190
+ * @returns {number}
191
+ */
192
+ median(arr) {
193
+ return this.percentile(arr, 50);
194
+ }
195
+
196
+ /**
197
+ * Calculate average of array
198
+ * @param {number[]} arr
199
+ * @returns {number}
200
+ */
201
+ average(arr) {
202
+ if (arr.length === 0) return 0;
203
+ return arr.reduce((a, b) => a + b, 0) / arr.length;
204
+ }
205
+
206
+ /**
207
+ * Calculate standard deviation of array
208
+ * @param {number[]} arr
209
+ * @returns {number}
210
+ */
211
+ standardDeviation(arr) {
212
+ if (arr.length === 0) return 0;
213
+ const avg = this.average(arr);
214
+ const squareDiffs = arr.map(value => Math.pow(value - avg, 2));
215
+ return Math.sqrt(this.average(squareDiffs));
216
+ }
217
+
218
+ /**
219
+ * Reset all collected data
220
+ */
221
+ reset() {
222
+ this.samples = [];
223
+ this.frameCount = 0;
224
+ this.lastFrameTime = 0;
225
+ this.frameStart = null;
226
+ this.sessionStart = performance.now();
227
+ }
228
+
229
+ /**
230
+ * Export samples as CSV
231
+ * @returns {string}
232
+ */
233
+ exportCSV() {
234
+ const headers = ['timestamp', 'frameNumber', 'frameTime', 'fps', 'memoryUsed', 'drawCalls', 'triangles'];
235
+ const rows = this.samples.map(s => [
236
+ s.timestamp,
237
+ s.frameNumber,
238
+ s.frameTime.toFixed(3),
239
+ s.fps.toFixed(1),
240
+ s.memory?.used?.toFixed(2) ?? '',
241
+ s.drawCalls,
242
+ s.triangles
243
+ ]);
244
+ return [headers.join(','), ...rows.map(r => r.join(','))].join('\n');
245
+ }
246
+
247
+ /**
248
+ * Export samples as JSON
249
+ * @returns {object}
250
+ */
251
+ exportJSON() {
252
+ return {
253
+ stats: this.getStats(),
254
+ samples: this.samples,
255
+ exportedAt: new Date().toISOString()
256
+ };
257
+ }
258
+
259
+ /**
260
+ * Get last N samples
261
+ * @param {number} n
262
+ * @returns {object[]}
263
+ */
264
+ getLastSamples(n) {
265
+ return this.samples.slice(-n);
266
+ }
267
+
268
+ /**
269
+ * Check if performance meets thresholds
270
+ * @param {object} thresholds
271
+ * @returns {object}
272
+ */
273
+ checkThresholds(thresholds = {}) {
274
+ const stats = this.getStats();
275
+ if (!stats) return { passed: false, reason: 'No data' };
276
+
277
+ const defaults = {
278
+ maxFrameTime: 16.67, // 60fps
279
+ minFPS: 60,
280
+ maxMemory: 200 // MB
281
+ };
282
+
283
+ const limits = { ...defaults, ...thresholds };
284
+ const results = {
285
+ frameTime: stats.frameTime.p95 <= limits.maxFrameTime,
286
+ fps: stats.fps.avg >= limits.minFPS,
287
+ memory: !stats.memory || stats.memory.used <= limits.maxMemory
288
+ };
289
+
290
+ return {
291
+ passed: results.frameTime && results.fps && results.memory,
292
+ results,
293
+ stats,
294
+ thresholds: limits
295
+ };
296
+ }
297
+ }
298
+
299
+ export default MetricsCollector;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * VIB3+ Benchmarks Module
3
+ *
4
+ * Performance testing and metrics collection for the VIB3+ engine.
5
+ */
6
+
7
+ export { MetricsCollector } from './MetricsCollector.js';
8
+ export { BenchmarkRunner } from './BenchmarkRunner.js';
9
+ export { BENCHMARK_SCENES, getScene, getSceneNames, getScenesByTier, getScenesBySystem } from './scenes.js';