@plasius/gpu-renderer 0.1.6 → 0.1.7

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.cjs CHANGED
@@ -21,12 +21,472 @@ var index_exports = {};
21
21
  __export(index_exports, {
22
22
  bindRendererToXrManager: () => bindRendererToXrManager,
23
23
  createGpuRenderer: () => createGpuRenderer,
24
+ createRendererDebugHooks: () => createRendererDebugHooks,
24
25
  defaultRendererClearColor: () => defaultRendererClearColor,
26
+ defaultRendererWorkerProfile: () => defaultRendererWorkerProfile,
27
+ getRendererWorkerManifest: () => getRendererWorkerManifest,
28
+ getRendererWorkerProfile: () => getRendererWorkerProfile,
29
+ rendererDebugOwner: () => rendererDebugOwner,
30
+ rendererWorkerManifests: () => rendererWorkerManifests,
31
+ rendererWorkerProfileNames: () => rendererWorkerProfileNames,
32
+ rendererWorkerProfiles: () => rendererWorkerProfiles,
33
+ rendererWorkerQueueClass: () => rendererWorkerQueueClass,
25
34
  supportsWebGpu: () => supportsWebGpu
26
35
  });
27
36
  module.exports = __toCommonJS(index_exports);
28
37
  var DEFAULT_CLEAR_COLOR = Object.freeze([0.07, 0.11, 0.18, 1]);
29
38
  var DEFAULT_CANVAS_SELECTOR = "canvas[data-plasius-gpu-renderer]";
39
+ var rendererDebugOwner = "renderer";
40
+ var rendererWorkerQueueClass = "render";
41
+ var defaultRendererWorkerProfile = "realtime";
42
+ function buildRendererWorkerBudgetLevels(jobType, queueClass, levels) {
43
+ return Object.freeze(
44
+ levels.map(
45
+ (level) => Object.freeze({
46
+ id: level.id,
47
+ estimatedCostMs: level.estimatedCostMs,
48
+ config: Object.freeze({
49
+ maxDispatchesPerFrame: level.config.maxDispatchesPerFrame,
50
+ maxJobsPerDispatch: level.config.maxJobsPerDispatch,
51
+ cadenceDivisor: level.config.cadenceDivisor,
52
+ workgroupScale: level.config.workgroupScale,
53
+ maxQueueDepth: level.config.maxQueueDepth,
54
+ metadata: Object.freeze({
55
+ owner: rendererDebugOwner,
56
+ queueClass,
57
+ jobType,
58
+ quality: level.id
59
+ })
60
+ })
61
+ })
62
+ )
63
+ );
64
+ }
65
+ var rendererWorkerProfileSpecs = {
66
+ realtime: {
67
+ description: "Frame-stage DAG for flat rendering with visibility, main encode, post-processing, and submit.",
68
+ suggestedAllocationIds: [
69
+ "renderer.surface.current",
70
+ "renderer.visibility.worklist",
71
+ "renderer.post-process.history"
72
+ ],
73
+ jobs: {
74
+ acquire: {
75
+ priority: 5,
76
+ dependencies: [],
77
+ domain: "resolution",
78
+ importance: "critical",
79
+ levels: [
80
+ {
81
+ id: "fixed",
82
+ estimatedCostMs: 0.2,
83
+ config: {
84
+ maxDispatchesPerFrame: 1,
85
+ maxJobsPerDispatch: 1,
86
+ cadenceDivisor: 1,
87
+ workgroupScale: 1,
88
+ maxQueueDepth: 1
89
+ }
90
+ }
91
+ ],
92
+ suggestedAllocationIds: ["renderer.surface.current"]
93
+ },
94
+ visibility: {
95
+ priority: 4,
96
+ dependencies: [],
97
+ domain: "geometry",
98
+ importance: "high",
99
+ levels: [
100
+ {
101
+ id: "low",
102
+ estimatedCostMs: 0.4,
103
+ config: {
104
+ maxDispatchesPerFrame: 1,
105
+ maxJobsPerDispatch: 128,
106
+ cadenceDivisor: 2,
107
+ workgroupScale: 0.5,
108
+ maxQueueDepth: 256
109
+ }
110
+ },
111
+ {
112
+ id: "medium",
113
+ estimatedCostMs: 0.8,
114
+ config: {
115
+ maxDispatchesPerFrame: 1,
116
+ maxJobsPerDispatch: 256,
117
+ cadenceDivisor: 1,
118
+ workgroupScale: 0.75,
119
+ maxQueueDepth: 384
120
+ }
121
+ },
122
+ {
123
+ id: "high",
124
+ estimatedCostMs: 1.2,
125
+ config: {
126
+ maxDispatchesPerFrame: 2,
127
+ maxJobsPerDispatch: 512,
128
+ cadenceDivisor: 1,
129
+ workgroupScale: 1,
130
+ maxQueueDepth: 512
131
+ }
132
+ }
133
+ ],
134
+ suggestedAllocationIds: ["renderer.visibility.worklist"]
135
+ },
136
+ mainEncode: {
137
+ priority: 4,
138
+ dependencies: ["acquire", "visibility"],
139
+ domain: "geometry",
140
+ importance: "critical",
141
+ levels: [
142
+ {
143
+ id: "low",
144
+ estimatedCostMs: 1.2,
145
+ config: {
146
+ maxDispatchesPerFrame: 1,
147
+ maxJobsPerDispatch: 128,
148
+ cadenceDivisor: 1,
149
+ workgroupScale: 0.6,
150
+ maxQueueDepth: 192
151
+ }
152
+ },
153
+ {
154
+ id: "medium",
155
+ estimatedCostMs: 2.1,
156
+ config: {
157
+ maxDispatchesPerFrame: 1,
158
+ maxJobsPerDispatch: 256,
159
+ cadenceDivisor: 1,
160
+ workgroupScale: 0.8,
161
+ maxQueueDepth: 256
162
+ }
163
+ },
164
+ {
165
+ id: "high",
166
+ estimatedCostMs: 3,
167
+ config: {
168
+ maxDispatchesPerFrame: 1,
169
+ maxJobsPerDispatch: 384,
170
+ cadenceDivisor: 1,
171
+ workgroupScale: 1,
172
+ maxQueueDepth: 384
173
+ }
174
+ }
175
+ ],
176
+ suggestedAllocationIds: ["renderer.surface.current"]
177
+ },
178
+ postProcess: {
179
+ priority: 3,
180
+ dependencies: ["mainEncode"],
181
+ domain: "post-processing",
182
+ importance: "high",
183
+ levels: [
184
+ {
185
+ id: "low",
186
+ estimatedCostMs: 0.5,
187
+ config: {
188
+ maxDispatchesPerFrame: 1,
189
+ maxJobsPerDispatch: 64,
190
+ cadenceDivisor: 2,
191
+ workgroupScale: 0.5,
192
+ maxQueueDepth: 96
193
+ }
194
+ },
195
+ {
196
+ id: "medium",
197
+ estimatedCostMs: 0.9,
198
+ config: {
199
+ maxDispatchesPerFrame: 1,
200
+ maxJobsPerDispatch: 128,
201
+ cadenceDivisor: 1,
202
+ workgroupScale: 0.75,
203
+ maxQueueDepth: 128
204
+ }
205
+ },
206
+ {
207
+ id: "high",
208
+ estimatedCostMs: 1.4,
209
+ config: {
210
+ maxDispatchesPerFrame: 2,
211
+ maxJobsPerDispatch: 192,
212
+ cadenceDivisor: 1,
213
+ workgroupScale: 1,
214
+ maxQueueDepth: 192
215
+ }
216
+ }
217
+ ],
218
+ suggestedAllocationIds: ["renderer.post-process.history"]
219
+ },
220
+ submit: {
221
+ priority: 2,
222
+ dependencies: ["postProcess"],
223
+ domain: "resolution",
224
+ importance: "critical",
225
+ levels: [
226
+ {
227
+ id: "fixed",
228
+ estimatedCostMs: 0.2,
229
+ config: {
230
+ maxDispatchesPerFrame: 1,
231
+ maxJobsPerDispatch: 1,
232
+ cadenceDivisor: 1,
233
+ workgroupScale: 1,
234
+ maxQueueDepth: 1
235
+ }
236
+ }
237
+ ],
238
+ suggestedAllocationIds: ["renderer.surface.current"]
239
+ }
240
+ }
241
+ },
242
+ xr: {
243
+ description: "Frame-stage DAG for XR rendering with late-latch coordination before main encode and submit.",
244
+ suggestedAllocationIds: [
245
+ "renderer.xr.surface.current",
246
+ "renderer.xr.visibility.worklist"
247
+ ],
248
+ jobs: {
249
+ acquire: {
250
+ priority: 5,
251
+ dependencies: [],
252
+ domain: "xr",
253
+ importance: "critical",
254
+ levels: [
255
+ {
256
+ id: "fixed",
257
+ estimatedCostMs: 0.2,
258
+ config: {
259
+ maxDispatchesPerFrame: 1,
260
+ maxJobsPerDispatch: 1,
261
+ cadenceDivisor: 1,
262
+ workgroupScale: 1,
263
+ maxQueueDepth: 1
264
+ }
265
+ }
266
+ ],
267
+ suggestedAllocationIds: ["renderer.xr.surface.current"]
268
+ },
269
+ visibility: {
270
+ priority: 4,
271
+ dependencies: [],
272
+ domain: "geometry",
273
+ importance: "high",
274
+ levels: [
275
+ {
276
+ id: "low",
277
+ estimatedCostMs: 0.5,
278
+ config: {
279
+ maxDispatchesPerFrame: 1,
280
+ maxJobsPerDispatch: 96,
281
+ cadenceDivisor: 2,
282
+ workgroupScale: 0.5,
283
+ maxQueueDepth: 192
284
+ }
285
+ },
286
+ {
287
+ id: "medium",
288
+ estimatedCostMs: 0.9,
289
+ config: {
290
+ maxDispatchesPerFrame: 1,
291
+ maxJobsPerDispatch: 192,
292
+ cadenceDivisor: 1,
293
+ workgroupScale: 0.75,
294
+ maxQueueDepth: 256
295
+ }
296
+ },
297
+ {
298
+ id: "high",
299
+ estimatedCostMs: 1.3,
300
+ config: {
301
+ maxDispatchesPerFrame: 2,
302
+ maxJobsPerDispatch: 320,
303
+ cadenceDivisor: 1,
304
+ workgroupScale: 1,
305
+ maxQueueDepth: 320
306
+ }
307
+ }
308
+ ],
309
+ suggestedAllocationIds: ["renderer.xr.visibility.worklist"]
310
+ },
311
+ lateLatch: {
312
+ priority: 5,
313
+ dependencies: ["acquire"],
314
+ domain: "xr",
315
+ importance: "critical",
316
+ levels: [
317
+ {
318
+ id: "fixed",
319
+ estimatedCostMs: 0.15,
320
+ config: {
321
+ maxDispatchesPerFrame: 1,
322
+ maxJobsPerDispatch: 1,
323
+ cadenceDivisor: 1,
324
+ workgroupScale: 1,
325
+ maxQueueDepth: 1
326
+ }
327
+ }
328
+ ],
329
+ suggestedAllocationIds: ["renderer.xr.surface.current"]
330
+ },
331
+ mainEncode: {
332
+ priority: 4,
333
+ dependencies: ["visibility", "lateLatch"],
334
+ domain: "xr",
335
+ importance: "critical",
336
+ levels: [
337
+ {
338
+ id: "low",
339
+ estimatedCostMs: 1.1,
340
+ config: {
341
+ maxDispatchesPerFrame: 1,
342
+ maxJobsPerDispatch: 96,
343
+ cadenceDivisor: 1,
344
+ workgroupScale: 0.6,
345
+ maxQueueDepth: 128
346
+ }
347
+ },
348
+ {
349
+ id: "medium",
350
+ estimatedCostMs: 1.8,
351
+ config: {
352
+ maxDispatchesPerFrame: 1,
353
+ maxJobsPerDispatch: 192,
354
+ cadenceDivisor: 1,
355
+ workgroupScale: 0.8,
356
+ maxQueueDepth: 192
357
+ }
358
+ },
359
+ {
360
+ id: "high",
361
+ estimatedCostMs: 2.6,
362
+ config: {
363
+ maxDispatchesPerFrame: 1,
364
+ maxJobsPerDispatch: 256,
365
+ cadenceDivisor: 1,
366
+ workgroupScale: 1,
367
+ maxQueueDepth: 256
368
+ }
369
+ }
370
+ ],
371
+ suggestedAllocationIds: ["renderer.xr.surface.current"]
372
+ },
373
+ submit: {
374
+ priority: 2,
375
+ dependencies: ["mainEncode"],
376
+ domain: "xr",
377
+ importance: "critical",
378
+ levels: [
379
+ {
380
+ id: "fixed",
381
+ estimatedCostMs: 0.2,
382
+ config: {
383
+ maxDispatchesPerFrame: 1,
384
+ maxJobsPerDispatch: 1,
385
+ cadenceDivisor: 1,
386
+ workgroupScale: 1,
387
+ maxQueueDepth: 1
388
+ }
389
+ }
390
+ ],
391
+ suggestedAllocationIds: ["renderer.xr.surface.current"]
392
+ }
393
+ }
394
+ }
395
+ };
396
+ function buildRendererWorkerProfile(name, spec) {
397
+ return Object.freeze({
398
+ name,
399
+ description: spec.description,
400
+ jobs: Object.freeze(Object.keys(spec.jobs))
401
+ });
402
+ }
403
+ function buildRendererWorkerManifestJob(profileName, jobName, spec) {
404
+ const label = `renderer.${profileName}.${jobName}`;
405
+ return Object.freeze({
406
+ key: jobName,
407
+ label,
408
+ worker: Object.freeze({
409
+ jobType: label,
410
+ queueClass: rendererWorkerQueueClass,
411
+ priority: spec.priority,
412
+ dependencies: Object.freeze(
413
+ spec.dependencies.map((dependency) => `renderer.${profileName}.${dependency}`)
414
+ ),
415
+ schedulerMode: "dag"
416
+ }),
417
+ performance: Object.freeze({
418
+ id: label,
419
+ jobType: label,
420
+ queueClass: rendererWorkerQueueClass,
421
+ domain: spec.domain,
422
+ authority: "visual",
423
+ importance: spec.importance,
424
+ levels: buildRendererWorkerBudgetLevels(
425
+ label,
426
+ rendererWorkerQueueClass,
427
+ spec.levels
428
+ )
429
+ }),
430
+ debug: Object.freeze({
431
+ owner: rendererDebugOwner,
432
+ queueClass: rendererWorkerQueueClass,
433
+ jobType: label,
434
+ tags: Object.freeze(["renderer", profileName, jobName, spec.domain]),
435
+ suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds])
436
+ })
437
+ });
438
+ }
439
+ function buildRendererWorkerManifest(name, spec) {
440
+ return Object.freeze({
441
+ schemaVersion: 1,
442
+ owner: rendererDebugOwner,
443
+ profile: name,
444
+ description: spec.description,
445
+ queueClass: rendererWorkerQueueClass,
446
+ schedulerMode: "dag",
447
+ suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),
448
+ jobs: Object.freeze(
449
+ Object.entries(spec.jobs).map(
450
+ ([jobName, jobSpec]) => buildRendererWorkerManifestJob(name, jobName, jobSpec)
451
+ )
452
+ )
453
+ });
454
+ }
455
+ var rendererWorkerProfiles = Object.freeze(
456
+ Object.fromEntries(
457
+ Object.entries(rendererWorkerProfileSpecs).map(([name, spec]) => [
458
+ name,
459
+ buildRendererWorkerProfile(name, spec)
460
+ ])
461
+ )
462
+ );
463
+ var rendererWorkerProfileNames = Object.freeze(
464
+ Object.keys(rendererWorkerProfiles)
465
+ );
466
+ var rendererWorkerManifests = Object.freeze(
467
+ Object.fromEntries(
468
+ Object.entries(rendererWorkerProfileSpecs).map(([name, spec]) => [
469
+ name,
470
+ buildRendererWorkerManifest(name, spec)
471
+ ])
472
+ )
473
+ );
474
+ function getRendererWorkerProfile(name = defaultRendererWorkerProfile) {
475
+ const profile = rendererWorkerProfiles[name];
476
+ if (!profile) {
477
+ const available = rendererWorkerProfileNames.join(", ");
478
+ throw new Error(`Unknown renderer worker profile "${name}". Available: ${available}.`);
479
+ }
480
+ return profile;
481
+ }
482
+ function getRendererWorkerManifest(name = defaultRendererWorkerProfile) {
483
+ const manifest = rendererWorkerManifests[name];
484
+ if (!manifest) {
485
+ const available = rendererWorkerProfileNames.join(", ");
486
+ throw new Error(`Unknown renderer worker profile "${name}". Available: ${available}.`);
487
+ }
488
+ return manifest;
489
+ }
30
490
  function clamp01(value) {
31
491
  return Math.min(1, Math.max(0, value));
32
492
  }
@@ -62,12 +522,111 @@ function normalizeColor(value) {
62
522
  }
63
523
  return [...DEFAULT_CLEAR_COLOR];
64
524
  }
525
+ function readPositiveNumber(name, value) {
526
+ if (value === void 0) {
527
+ return void 0;
528
+ }
529
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
530
+ throw new Error(`${name} must be a finite number greater than zero.`);
531
+ }
532
+ return value;
533
+ }
65
534
  function now() {
66
535
  if (typeof performance !== "undefined" && typeof performance.now === "function") {
67
536
  return performance.now();
68
537
  }
69
538
  return Date.now();
70
539
  }
540
+ function normalizeFrameId(value) {
541
+ if (typeof value !== "string" || value.trim().length === 0) {
542
+ throw new Error("frameIdFactory must return a non-empty string.");
543
+ }
544
+ return value.trim();
545
+ }
546
+ function resolveTargetFrameTimeMs(options, event) {
547
+ const {
548
+ targetFrameTimeMs: fixedTargetFrameTimeMs,
549
+ targetFrameRate,
550
+ getTargetFrameTimeMs
551
+ } = options;
552
+ if (typeof getTargetFrameTimeMs === "function") {
553
+ const resolved = getTargetFrameTimeMs(event);
554
+ return readPositiveNumber("getTargetFrameTimeMs()", resolved);
555
+ }
556
+ if (fixedTargetFrameTimeMs !== void 0) {
557
+ return fixedTargetFrameTimeMs;
558
+ }
559
+ if (targetFrameRate !== void 0) {
560
+ return 1e3 / targetFrameRate;
561
+ }
562
+ return void 0;
563
+ }
564
+ function createRendererDebugHooks(options = {}) {
565
+ const {
566
+ debugSession,
567
+ targetFrameTimeMs,
568
+ targetFrameRate,
569
+ getTargetFrameTimeMs,
570
+ onFrameStart,
571
+ onFrameComplete
572
+ } = options;
573
+ if (!debugSession || typeof debugSession.recordFrame !== "function") {
574
+ throw new Error(
575
+ "debugSession must expose recordFrame(sample). Use @plasius/gpu-debug createGpuDebugSession()."
576
+ );
577
+ }
578
+ const fixedTargetFrameTimeMs = readPositiveNumber(
579
+ "targetFrameTimeMs",
580
+ targetFrameTimeMs
581
+ );
582
+ const fixedTargetFrameRate = readPositiveNumber(
583
+ "targetFrameRate",
584
+ targetFrameRate
585
+ );
586
+ if (fixedTargetFrameTimeMs !== void 0 && fixedTargetFrameRate !== void 0) {
587
+ throw new Error(
588
+ "Provide either targetFrameTimeMs or targetFrameRate, not both."
589
+ );
590
+ }
591
+ if (getTargetFrameTimeMs !== void 0 && typeof getTargetFrameTimeMs !== "function") {
592
+ throw new Error("getTargetFrameTimeMs must be a function when provided.");
593
+ }
594
+ const resolvedOptions = {
595
+ targetFrameTimeMs: fixedTargetFrameTimeMs,
596
+ targetFrameRate: fixedTargetFrameRate,
597
+ getTargetFrameTimeMs
598
+ };
599
+ return {
600
+ onFrameStart(event) {
601
+ if (typeof onFrameStart === "function") {
602
+ onFrameStart({
603
+ ...event,
604
+ owner: rendererDebugOwner
605
+ });
606
+ }
607
+ },
608
+ onFrameComplete(event) {
609
+ const resolvedTargetFrameTimeMs = resolveTargetFrameTimeMs(
610
+ resolvedOptions,
611
+ event
612
+ );
613
+ if (typeof event.frameTimeMs === "number" && Number.isFinite(event.frameTimeMs) && event.frameTimeMs > 0) {
614
+ debugSession.recordFrame({
615
+ frameId: event.frameId,
616
+ frameTimeMs: event.frameTimeMs,
617
+ targetFrameTimeMs: resolvedTargetFrameTimeMs
618
+ });
619
+ }
620
+ if (typeof onFrameComplete === "function") {
621
+ onFrameComplete({
622
+ ...event,
623
+ owner: rendererDebugOwner,
624
+ targetFrameTimeMs: resolvedTargetFrameTimeMs
625
+ });
626
+ }
627
+ }
628
+ };
629
+ }
71
630
  function readNavigator(navigatorOverride) {
72
631
  const currentNavigator = navigatorOverride ?? globalThis.navigator;
73
632
  if (!currentNavigator || typeof currentNavigator !== "object") {
@@ -148,8 +707,11 @@ async function createGpuRenderer(options = {}) {
148
707
  clearColor = DEFAULT_CLEAR_COLOR,
149
708
  requestAnimationFrame = globalThis.requestAnimationFrame?.bind(globalThis),
150
709
  cancelAnimationFrame = globalThis.cancelAnimationFrame?.bind(globalThis),
710
+ frameIdFactory,
711
+ onFrameStart,
151
712
  onBeforeEncode,
152
- onAfterSubmit
713
+ onAfterSubmit,
714
+ onFrameComplete
153
715
  } = options;
154
716
  const gpu = readGpu(navigatorOverride);
155
717
  const adapter = await gpu.requestAdapter({ powerPreference });
@@ -176,6 +738,28 @@ async function createGpuRenderer(options = {}) {
176
738
  if (destroyed) {
177
739
  throw new Error("Renderer was destroyed.");
178
740
  }
741
+ const frameNumber = frame + 1;
742
+ const frameId = normalizeFrameId(
743
+ typeof frameIdFactory === "function" ? frameIdFactory({
744
+ frame: frameNumber,
745
+ timestamp,
746
+ canvas: targetCanvas,
747
+ xrActive
748
+ }) : `renderer.frame.${frameNumber}`
749
+ );
750
+ const frameTimeMs = lastTimestamp > 0 ? Math.max(0, timestamp - lastTimestamp) : void 0;
751
+ if (typeof onFrameStart === "function") {
752
+ onFrameStart({
753
+ frame: frameNumber,
754
+ frameId,
755
+ frameTimeMs,
756
+ timestamp,
757
+ device,
758
+ context,
759
+ canvas: targetCanvas,
760
+ xrActive
761
+ });
762
+ }
179
763
  const texture = context.getCurrentTexture?.();
180
764
  if (!texture || typeof texture.createView !== "function") {
181
765
  throw new Error("WebGPU context returned an invalid current texture.");
@@ -188,12 +772,16 @@ async function createGpuRenderer(options = {}) {
188
772
  if (typeof onBeforeEncode === "function") {
189
773
  onBeforeEncode({
190
774
  frame,
775
+ frameNumber,
776
+ frameId,
777
+ frameTimeMs,
191
778
  timestamp,
192
779
  device,
193
780
  context,
194
781
  encoder,
195
782
  pass,
196
- canvas: targetCanvas
783
+ canvas: targetCanvas,
784
+ xrActive
197
785
  });
198
786
  }
199
787
  if (typeof pass.end === "function") {
@@ -201,19 +789,37 @@ async function createGpuRenderer(options = {}) {
201
789
  }
202
790
  const commandBuffer = encoder.finish();
203
791
  device.queue.submit([commandBuffer]);
204
- frame += 1;
792
+ frame = frameNumber;
205
793
  lastTimestamp = timestamp;
206
794
  if (typeof onAfterSubmit === "function") {
207
795
  onAfterSubmit({
208
- frame,
796
+ frame: frameNumber,
797
+ frameNumber,
798
+ frameId,
799
+ frameTimeMs,
209
800
  timestamp,
210
801
  device,
211
802
  context,
212
- canvas: targetCanvas
803
+ canvas: targetCanvas,
804
+ xrActive
805
+ });
806
+ }
807
+ if (typeof onFrameComplete === "function") {
808
+ onFrameComplete({
809
+ frame: frameNumber,
810
+ frameId,
811
+ frameTimeMs,
812
+ timestamp,
813
+ device,
814
+ context,
815
+ canvas: targetCanvas,
816
+ xrActive
213
817
  });
214
818
  }
215
819
  return {
216
- frame,
820
+ frame: frameNumber,
821
+ frameId,
822
+ frameTimeMs,
217
823
  timestamp
218
824
  };
219
825
  };
@@ -355,7 +961,16 @@ var defaultRendererClearColor = DEFAULT_CLEAR_COLOR;
355
961
  0 && (module.exports = {
356
962
  bindRendererToXrManager,
357
963
  createGpuRenderer,
964
+ createRendererDebugHooks,
358
965
  defaultRendererClearColor,
966
+ defaultRendererWorkerProfile,
967
+ getRendererWorkerManifest,
968
+ getRendererWorkerProfile,
969
+ rendererDebugOwner,
970
+ rendererWorkerManifests,
971
+ rendererWorkerProfileNames,
972
+ rendererWorkerProfiles,
973
+ rendererWorkerQueueClass,
359
974
  supportsWebGpu
360
975
  });
361
976
  //# sourceMappingURL=index.cjs.map