@plasius/gpu-renderer 0.1.4 → 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/CHANGELOG.md +46 -0
- package/README.md +55 -0
- package/dist/index.cjs +621 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +612 -6
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
- package/src/index.d.ts +143 -1
- package/src/index.js +644 -3
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
|
|
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
|