@plasius/gpu-world-generator 0.0.10 → 0.0.12
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/README.md +48 -0
- package/dist/index.cjs +769 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -1
- package/dist/index.d.ts +120 -1
- package/dist/index.js +757 -1
- package/dist/index.js.map +1 -1
- package/docs/adrs/adr-0004-worker-dag-manifests-for-chunk-and-voxel-generation.md +37 -0
- package/docs/adrs/adr-0005-render-representation-tiers-and-proxy-outputs.md +51 -0
- package/docs/adrs/index.md +2 -0
- package/docs/design/worker-manifest-integration.md +42 -0
- package/docs/tdrs/index.md +4 -0
- package/docs/tdrs/tdr-0001-world-generator-worker-manifest-contract.md +39 -0
- package/docs/tdrs/tdr-0002-render-representation-tier-contract.md +60 -0
- package/package.json +6 -3
- package/src/index.ts +1 -0
- package/src/worker.ts +978 -0
package/src/worker.ts
ADDED
|
@@ -0,0 +1,978 @@
|
|
|
1
|
+
export type WorldGeneratorWorkerQueueClass = "voxel";
|
|
2
|
+
export type WorldGeneratorWorkerProfileName = "streaming" | "bake";
|
|
3
|
+
export type WorldGeneratorWorkerDomain = "geometry" | "textures" | "custom";
|
|
4
|
+
export type WorldGeneratorWorkerAuthority =
|
|
5
|
+
| "visual"
|
|
6
|
+
| "non-authoritative-simulation"
|
|
7
|
+
| "authoritative";
|
|
8
|
+
export type WorldGeneratorWorkerImportance = "medium" | "high" | "critical";
|
|
9
|
+
export type WorldGeneratorRepresentationBand =
|
|
10
|
+
| "near"
|
|
11
|
+
| "mid"
|
|
12
|
+
| "far"
|
|
13
|
+
| "horizon";
|
|
14
|
+
export type WorldGeneratorRepresentationOutput =
|
|
15
|
+
| "liveGeometry"
|
|
16
|
+
| "simplifiedGeometry"
|
|
17
|
+
| "rtProxy"
|
|
18
|
+
| "mergedProxy"
|
|
19
|
+
| "horizonShell";
|
|
20
|
+
export type WorldGeneratorRepresentationRtParticipation =
|
|
21
|
+
| "full"
|
|
22
|
+
| "selective"
|
|
23
|
+
| "proxy"
|
|
24
|
+
| "disabled";
|
|
25
|
+
export type WorldGeneratorRepresentationShadowRelevance =
|
|
26
|
+
| "ray-traced-primary"
|
|
27
|
+
| "selective-raster"
|
|
28
|
+
| "proxy-caster"
|
|
29
|
+
| "baked-impression";
|
|
30
|
+
|
|
31
|
+
export interface WorldGeneratorRepresentationCadence {
|
|
32
|
+
readonly kind: "per-frame" | "interval";
|
|
33
|
+
readonly divisor: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface WorldGeneratorRepresentationDescriptor {
|
|
37
|
+
readonly id: string;
|
|
38
|
+
readonly chunkId: string;
|
|
39
|
+
readonly profile: WorldGeneratorWorkerProfileName;
|
|
40
|
+
readonly band: WorldGeneratorRepresentationBand;
|
|
41
|
+
readonly output: WorldGeneratorRepresentationOutput;
|
|
42
|
+
readonly rasterMode:
|
|
43
|
+
| "full-live"
|
|
44
|
+
| "simplified-live"
|
|
45
|
+
| "proxy"
|
|
46
|
+
| "not-rendered"
|
|
47
|
+
| "horizon-shell";
|
|
48
|
+
readonly rtParticipation: WorldGeneratorRepresentationRtParticipation;
|
|
49
|
+
readonly shadowRelevance: WorldGeneratorRepresentationShadowRelevance;
|
|
50
|
+
readonly refreshCadence: WorldGeneratorRepresentationCadence;
|
|
51
|
+
readonly preservesChunkIdentity: boolean;
|
|
52
|
+
readonly sourceChunkIds: readonly string[];
|
|
53
|
+
readonly sourceJobKeys: readonly string[];
|
|
54
|
+
readonly suggestedAllocationIds: readonly string[];
|
|
55
|
+
readonly scheduling: Readonly<{
|
|
56
|
+
owner: "renderer";
|
|
57
|
+
queueClass: typeof worldGeneratorWorkerQueueClass;
|
|
58
|
+
priorityHint: number;
|
|
59
|
+
gameplayImportance: WorldGeneratorWorkerImportance;
|
|
60
|
+
representationBand: WorldGeneratorRepresentationBand;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface WorldGeneratorRepresentationPlan {
|
|
65
|
+
readonly schemaVersion: 1;
|
|
66
|
+
readonly owner: typeof worldGeneratorDebugOwner;
|
|
67
|
+
readonly profile: WorldGeneratorWorkerProfileName;
|
|
68
|
+
readonly chunkId: string;
|
|
69
|
+
readonly representations: readonly WorldGeneratorRepresentationDescriptor[];
|
|
70
|
+
readonly bands: readonly WorldGeneratorRepresentationBand[];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface WorldGeneratorWorkerBudgetLevelConfig {
|
|
74
|
+
maxDispatchesPerFrame: number;
|
|
75
|
+
maxJobsPerDispatch: number;
|
|
76
|
+
cadenceDivisor: number;
|
|
77
|
+
workgroupScale: number;
|
|
78
|
+
maxQueueDepth: number;
|
|
79
|
+
metadata: Readonly<{
|
|
80
|
+
owner: typeof worldGeneratorDebugOwner;
|
|
81
|
+
queueClass: typeof worldGeneratorWorkerQueueClass;
|
|
82
|
+
jobType: string;
|
|
83
|
+
quality: string;
|
|
84
|
+
}>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface WorldGeneratorWorkerBudgetLevel {
|
|
88
|
+
id: string;
|
|
89
|
+
estimatedCostMs: number;
|
|
90
|
+
config: WorldGeneratorWorkerBudgetLevelConfig;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface WorldGeneratorWorkerProfile {
|
|
94
|
+
readonly name: WorldGeneratorWorkerProfileName;
|
|
95
|
+
readonly description: string;
|
|
96
|
+
readonly jobs: readonly string[];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface WorldGeneratorWorkerManifestJob {
|
|
100
|
+
readonly key: string;
|
|
101
|
+
readonly label: string;
|
|
102
|
+
readonly worker: Readonly<{
|
|
103
|
+
jobType: string;
|
|
104
|
+
queueClass: typeof worldGeneratorWorkerQueueClass;
|
|
105
|
+
priority: number;
|
|
106
|
+
dependencies: readonly string[];
|
|
107
|
+
schedulerMode: "dag";
|
|
108
|
+
}>;
|
|
109
|
+
readonly performance: Readonly<{
|
|
110
|
+
id: string;
|
|
111
|
+
jobType: string;
|
|
112
|
+
queueClass: typeof worldGeneratorWorkerQueueClass;
|
|
113
|
+
domain: WorldGeneratorWorkerDomain;
|
|
114
|
+
authority: WorldGeneratorWorkerAuthority;
|
|
115
|
+
importance: WorldGeneratorWorkerImportance;
|
|
116
|
+
levels: readonly WorldGeneratorWorkerBudgetLevel[];
|
|
117
|
+
}>;
|
|
118
|
+
readonly debug: Readonly<{
|
|
119
|
+
owner: typeof worldGeneratorDebugOwner;
|
|
120
|
+
queueClass: typeof worldGeneratorWorkerQueueClass;
|
|
121
|
+
jobType: string;
|
|
122
|
+
tags: readonly string[];
|
|
123
|
+
suggestedAllocationIds: readonly string[];
|
|
124
|
+
}>;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface WorldGeneratorWorkerManifest {
|
|
128
|
+
readonly schemaVersion: 1;
|
|
129
|
+
readonly owner: typeof worldGeneratorDebugOwner;
|
|
130
|
+
readonly profile: WorldGeneratorWorkerProfileName;
|
|
131
|
+
readonly description: string;
|
|
132
|
+
readonly queueClass: typeof worldGeneratorWorkerQueueClass;
|
|
133
|
+
readonly schedulerMode: "dag";
|
|
134
|
+
readonly suggestedAllocationIds: readonly string[];
|
|
135
|
+
readonly jobs: readonly WorldGeneratorWorkerManifestJob[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export const worldGeneratorDebugOwner = "world-generator";
|
|
139
|
+
export const worldGeneratorWorkerQueueClass = "voxel";
|
|
140
|
+
export const defaultWorldGeneratorWorkerProfile = "streaming";
|
|
141
|
+
export const worldGeneratorRepresentationBands = Object.freeze([
|
|
142
|
+
"near",
|
|
143
|
+
"mid",
|
|
144
|
+
"far",
|
|
145
|
+
"horizon",
|
|
146
|
+
]) as readonly WorldGeneratorRepresentationBand[];
|
|
147
|
+
export const worldGeneratorRepresentationOutputs = Object.freeze([
|
|
148
|
+
"liveGeometry",
|
|
149
|
+
"simplifiedGeometry",
|
|
150
|
+
"rtProxy",
|
|
151
|
+
"mergedProxy",
|
|
152
|
+
"horizonShell",
|
|
153
|
+
]) as readonly WorldGeneratorRepresentationOutput[];
|
|
154
|
+
|
|
155
|
+
const worldGeneratorRepresentationBandPriorityHints: Readonly<
|
|
156
|
+
Record<WorldGeneratorRepresentationBand, number>
|
|
157
|
+
> = Object.freeze({
|
|
158
|
+
near: 400,
|
|
159
|
+
mid: 300,
|
|
160
|
+
far: 200,
|
|
161
|
+
horizon: 100,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
type WorkerLevelSpec = Omit<WorldGeneratorWorkerBudgetLevel, "config"> & {
|
|
165
|
+
config: Omit<WorldGeneratorWorkerBudgetLevelConfig, "metadata">;
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
type WorkerJobSpec = {
|
|
169
|
+
priority: number;
|
|
170
|
+
dependencies: readonly string[];
|
|
171
|
+
domain: WorldGeneratorWorkerDomain;
|
|
172
|
+
authority: WorldGeneratorWorkerAuthority;
|
|
173
|
+
importance: WorldGeneratorWorkerImportance;
|
|
174
|
+
levels: readonly WorkerLevelSpec[];
|
|
175
|
+
suggestedAllocationIds: readonly string[];
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
type WorkerProfileSpec = {
|
|
179
|
+
description: string;
|
|
180
|
+
suggestedAllocationIds: readonly string[];
|
|
181
|
+
jobs: Readonly<Record<string, WorkerJobSpec>>;
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
function assertWorldGeneratorIdentifier(name: string, value: unknown) {
|
|
185
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
186
|
+
throw new Error(`${name} must be a non-empty string.`);
|
|
187
|
+
}
|
|
188
|
+
return value.trim();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function normalizeWorldGeneratorImportance(
|
|
192
|
+
name: string,
|
|
193
|
+
value: unknown
|
|
194
|
+
): WorldGeneratorWorkerImportance {
|
|
195
|
+
if (value === "medium" || value === "high" || value === "critical") {
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
throw new Error(`${name} must be one of: medium, high, critical.`);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function buildWorldGeneratorRepresentationDescriptor(
|
|
202
|
+
options: {
|
|
203
|
+
profile: WorldGeneratorWorkerProfileName;
|
|
204
|
+
chunkId: string;
|
|
205
|
+
band: WorldGeneratorRepresentationBand;
|
|
206
|
+
output: WorldGeneratorRepresentationOutput;
|
|
207
|
+
rasterMode: WorldGeneratorRepresentationDescriptor["rasterMode"];
|
|
208
|
+
rtParticipation: WorldGeneratorRepresentationRtParticipation;
|
|
209
|
+
shadowRelevance: WorldGeneratorRepresentationShadowRelevance;
|
|
210
|
+
refreshCadence: WorldGeneratorRepresentationCadence;
|
|
211
|
+
preservesChunkIdentity: boolean;
|
|
212
|
+
sourceJobKeys: readonly string[];
|
|
213
|
+
gameplayImportance: WorldGeneratorWorkerImportance;
|
|
214
|
+
suggestedAllocationIds: readonly string[];
|
|
215
|
+
}
|
|
216
|
+
): WorldGeneratorRepresentationDescriptor {
|
|
217
|
+
return Object.freeze({
|
|
218
|
+
id: `${options.chunkId}.${options.band}.${options.output}`,
|
|
219
|
+
chunkId: options.chunkId,
|
|
220
|
+
profile: options.profile,
|
|
221
|
+
band: options.band,
|
|
222
|
+
output: options.output,
|
|
223
|
+
rasterMode: options.rasterMode,
|
|
224
|
+
rtParticipation: options.rtParticipation,
|
|
225
|
+
shadowRelevance: options.shadowRelevance,
|
|
226
|
+
refreshCadence: Object.freeze({
|
|
227
|
+
kind: options.refreshCadence.kind,
|
|
228
|
+
divisor: options.refreshCadence.divisor,
|
|
229
|
+
}),
|
|
230
|
+
preservesChunkIdentity: options.preservesChunkIdentity,
|
|
231
|
+
sourceChunkIds: Object.freeze([options.chunkId]),
|
|
232
|
+
sourceJobKeys: Object.freeze([...options.sourceJobKeys]),
|
|
233
|
+
suggestedAllocationIds: Object.freeze([...options.suggestedAllocationIds]),
|
|
234
|
+
scheduling: Object.freeze({
|
|
235
|
+
owner: "renderer",
|
|
236
|
+
queueClass: worldGeneratorWorkerQueueClass,
|
|
237
|
+
priorityHint: worldGeneratorRepresentationBandPriorityHints[options.band],
|
|
238
|
+
gameplayImportance: options.gameplayImportance,
|
|
239
|
+
representationBand: options.band,
|
|
240
|
+
}),
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function buildBudgetLevels(
|
|
245
|
+
jobType: string,
|
|
246
|
+
queueClass: WorldGeneratorWorkerQueueClass,
|
|
247
|
+
levels: readonly WorkerLevelSpec[]
|
|
248
|
+
) {
|
|
249
|
+
return Object.freeze(
|
|
250
|
+
levels.map((level) =>
|
|
251
|
+
Object.freeze({
|
|
252
|
+
id: level.id,
|
|
253
|
+
estimatedCostMs: level.estimatedCostMs,
|
|
254
|
+
config: Object.freeze({
|
|
255
|
+
maxDispatchesPerFrame: level.config.maxDispatchesPerFrame,
|
|
256
|
+
maxJobsPerDispatch: level.config.maxJobsPerDispatch,
|
|
257
|
+
cadenceDivisor: level.config.cadenceDivisor,
|
|
258
|
+
workgroupScale: level.config.workgroupScale,
|
|
259
|
+
maxQueueDepth: level.config.maxQueueDepth,
|
|
260
|
+
metadata: Object.freeze({
|
|
261
|
+
owner: worldGeneratorDebugOwner,
|
|
262
|
+
queueClass,
|
|
263
|
+
jobType,
|
|
264
|
+
quality: level.id,
|
|
265
|
+
}),
|
|
266
|
+
}),
|
|
267
|
+
})
|
|
268
|
+
)
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const worldGeneratorWorkerProfileSpecs: Record<
|
|
273
|
+
WorldGeneratorWorkerProfileName,
|
|
274
|
+
WorkerProfileSpec
|
|
275
|
+
> = {
|
|
276
|
+
streaming: {
|
|
277
|
+
description:
|
|
278
|
+
"Runtime chunk generation DAG for fractal prepass, terrain synthesis, voxel materialization, mesh build, and tile bake.",
|
|
279
|
+
suggestedAllocationIds: [
|
|
280
|
+
"world.chunk.field.scratch",
|
|
281
|
+
"world.chunk.height.buffer",
|
|
282
|
+
"world.chunk.voxel.buffer",
|
|
283
|
+
"world.chunk.mesh.buffer",
|
|
284
|
+
],
|
|
285
|
+
jobs: {
|
|
286
|
+
fractalPrepass: {
|
|
287
|
+
priority: 4,
|
|
288
|
+
dependencies: [],
|
|
289
|
+
domain: "custom",
|
|
290
|
+
authority: "authoritative",
|
|
291
|
+
importance: "high",
|
|
292
|
+
levels: [
|
|
293
|
+
{
|
|
294
|
+
id: "fixed",
|
|
295
|
+
estimatedCostMs: 0.6,
|
|
296
|
+
config: {
|
|
297
|
+
maxDispatchesPerFrame: 1,
|
|
298
|
+
maxJobsPerDispatch: 1,
|
|
299
|
+
cadenceDivisor: 1,
|
|
300
|
+
workgroupScale: 1,
|
|
301
|
+
maxQueueDepth: 32,
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
],
|
|
305
|
+
suggestedAllocationIds: ["world.chunk.field.scratch"],
|
|
306
|
+
},
|
|
307
|
+
fieldSynthesis: {
|
|
308
|
+
priority: 4,
|
|
309
|
+
dependencies: [],
|
|
310
|
+
domain: "custom",
|
|
311
|
+
authority: "authoritative",
|
|
312
|
+
importance: "critical",
|
|
313
|
+
levels: [
|
|
314
|
+
{
|
|
315
|
+
id: "fixed",
|
|
316
|
+
estimatedCostMs: 0.9,
|
|
317
|
+
config: {
|
|
318
|
+
maxDispatchesPerFrame: 1,
|
|
319
|
+
maxJobsPerDispatch: 2,
|
|
320
|
+
cadenceDivisor: 1,
|
|
321
|
+
workgroupScale: 1,
|
|
322
|
+
maxQueueDepth: 48,
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
],
|
|
326
|
+
suggestedAllocationIds: ["world.chunk.field.scratch"],
|
|
327
|
+
},
|
|
328
|
+
terrainSynthesis: {
|
|
329
|
+
priority: 5,
|
|
330
|
+
dependencies: ["fractalPrepass", "fieldSynthesis"],
|
|
331
|
+
domain: "custom",
|
|
332
|
+
authority: "authoritative",
|
|
333
|
+
importance: "critical",
|
|
334
|
+
levels: [
|
|
335
|
+
{
|
|
336
|
+
id: "fixed",
|
|
337
|
+
estimatedCostMs: 1.4,
|
|
338
|
+
config: {
|
|
339
|
+
maxDispatchesPerFrame: 1,
|
|
340
|
+
maxJobsPerDispatch: 1,
|
|
341
|
+
cadenceDivisor: 1,
|
|
342
|
+
workgroupScale: 1,
|
|
343
|
+
maxQueueDepth: 32,
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
],
|
|
347
|
+
suggestedAllocationIds: ["world.chunk.height.buffer"],
|
|
348
|
+
},
|
|
349
|
+
voxelMaterialize: {
|
|
350
|
+
priority: 3,
|
|
351
|
+
dependencies: ["terrainSynthesis"],
|
|
352
|
+
domain: "custom",
|
|
353
|
+
authority: "non-authoritative-simulation",
|
|
354
|
+
importance: "high",
|
|
355
|
+
levels: [
|
|
356
|
+
{
|
|
357
|
+
id: "low",
|
|
358
|
+
estimatedCostMs: 0.8,
|
|
359
|
+
config: {
|
|
360
|
+
maxDispatchesPerFrame: 1,
|
|
361
|
+
maxJobsPerDispatch: 1,
|
|
362
|
+
cadenceDivisor: 2,
|
|
363
|
+
workgroupScale: 0.6,
|
|
364
|
+
maxQueueDepth: 24,
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
id: "medium",
|
|
369
|
+
estimatedCostMs: 1.2,
|
|
370
|
+
config: {
|
|
371
|
+
maxDispatchesPerFrame: 1,
|
|
372
|
+
maxJobsPerDispatch: 2,
|
|
373
|
+
cadenceDivisor: 1,
|
|
374
|
+
workgroupScale: 0.8,
|
|
375
|
+
maxQueueDepth: 32,
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
id: "high",
|
|
380
|
+
estimatedCostMs: 1.8,
|
|
381
|
+
config: {
|
|
382
|
+
maxDispatchesPerFrame: 2,
|
|
383
|
+
maxJobsPerDispatch: 2,
|
|
384
|
+
cadenceDivisor: 1,
|
|
385
|
+
workgroupScale: 1,
|
|
386
|
+
maxQueueDepth: 40,
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
],
|
|
390
|
+
suggestedAllocationIds: ["world.chunk.voxel.buffer"],
|
|
391
|
+
},
|
|
392
|
+
meshBuild: {
|
|
393
|
+
priority: 2,
|
|
394
|
+
dependencies: ["terrainSynthesis", "voxelMaterialize"],
|
|
395
|
+
domain: "geometry",
|
|
396
|
+
authority: "visual",
|
|
397
|
+
importance: "high",
|
|
398
|
+
levels: [
|
|
399
|
+
{
|
|
400
|
+
id: "low",
|
|
401
|
+
estimatedCostMs: 0.7,
|
|
402
|
+
config: {
|
|
403
|
+
maxDispatchesPerFrame: 1,
|
|
404
|
+
maxJobsPerDispatch: 1,
|
|
405
|
+
cadenceDivisor: 2,
|
|
406
|
+
workgroupScale: 0.6,
|
|
407
|
+
maxQueueDepth: 16,
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
id: "medium",
|
|
412
|
+
estimatedCostMs: 1.1,
|
|
413
|
+
config: {
|
|
414
|
+
maxDispatchesPerFrame: 1,
|
|
415
|
+
maxJobsPerDispatch: 1,
|
|
416
|
+
cadenceDivisor: 1,
|
|
417
|
+
workgroupScale: 0.8,
|
|
418
|
+
maxQueueDepth: 24,
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
id: "high",
|
|
423
|
+
estimatedCostMs: 1.6,
|
|
424
|
+
config: {
|
|
425
|
+
maxDispatchesPerFrame: 2,
|
|
426
|
+
maxJobsPerDispatch: 2,
|
|
427
|
+
cadenceDivisor: 1,
|
|
428
|
+
workgroupScale: 1,
|
|
429
|
+
maxQueueDepth: 32,
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
],
|
|
433
|
+
suggestedAllocationIds: ["world.chunk.mesh.buffer"],
|
|
434
|
+
},
|
|
435
|
+
tileBake: {
|
|
436
|
+
priority: 2,
|
|
437
|
+
dependencies: ["terrainSynthesis"],
|
|
438
|
+
domain: "textures",
|
|
439
|
+
authority: "non-authoritative-simulation",
|
|
440
|
+
importance: "medium",
|
|
441
|
+
levels: [
|
|
442
|
+
{
|
|
443
|
+
id: "low",
|
|
444
|
+
estimatedCostMs: 0.6,
|
|
445
|
+
config: {
|
|
446
|
+
maxDispatchesPerFrame: 1,
|
|
447
|
+
maxJobsPerDispatch: 1,
|
|
448
|
+
cadenceDivisor: 3,
|
|
449
|
+
workgroupScale: 0.5,
|
|
450
|
+
maxQueueDepth: 16,
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
{
|
|
454
|
+
id: "medium",
|
|
455
|
+
estimatedCostMs: 0.9,
|
|
456
|
+
config: {
|
|
457
|
+
maxDispatchesPerFrame: 1,
|
|
458
|
+
maxJobsPerDispatch: 1,
|
|
459
|
+
cadenceDivisor: 2,
|
|
460
|
+
workgroupScale: 0.75,
|
|
461
|
+
maxQueueDepth: 24,
|
|
462
|
+
},
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
id: "high",
|
|
466
|
+
estimatedCostMs: 1.3,
|
|
467
|
+
config: {
|
|
468
|
+
maxDispatchesPerFrame: 2,
|
|
469
|
+
maxJobsPerDispatch: 2,
|
|
470
|
+
cadenceDivisor: 1,
|
|
471
|
+
workgroupScale: 1,
|
|
472
|
+
maxQueueDepth: 32,
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
],
|
|
476
|
+
suggestedAllocationIds: ["world.chunk.height.buffer"],
|
|
477
|
+
},
|
|
478
|
+
},
|
|
479
|
+
},
|
|
480
|
+
bake: {
|
|
481
|
+
description:
|
|
482
|
+
"Offline tile bake DAG for terrain generation, voxel materialization, mesh build, and asset serialization.",
|
|
483
|
+
suggestedAllocationIds: [
|
|
484
|
+
"world.bake.field.scratch",
|
|
485
|
+
"world.bake.height.buffer",
|
|
486
|
+
"world.bake.mesh.buffer",
|
|
487
|
+
"world.bake.asset.binary",
|
|
488
|
+
],
|
|
489
|
+
jobs: {
|
|
490
|
+
fractalPrepass: {
|
|
491
|
+
priority: 4,
|
|
492
|
+
dependencies: [],
|
|
493
|
+
domain: "custom",
|
|
494
|
+
authority: "authoritative",
|
|
495
|
+
importance: "high",
|
|
496
|
+
levels: [
|
|
497
|
+
{
|
|
498
|
+
id: "fixed",
|
|
499
|
+
estimatedCostMs: 0.7,
|
|
500
|
+
config: {
|
|
501
|
+
maxDispatchesPerFrame: 1,
|
|
502
|
+
maxJobsPerDispatch: 1,
|
|
503
|
+
cadenceDivisor: 1,
|
|
504
|
+
workgroupScale: 1,
|
|
505
|
+
maxQueueDepth: 32,
|
|
506
|
+
},
|
|
507
|
+
},
|
|
508
|
+
],
|
|
509
|
+
suggestedAllocationIds: ["world.bake.field.scratch"],
|
|
510
|
+
},
|
|
511
|
+
fieldSynthesis: {
|
|
512
|
+
priority: 4,
|
|
513
|
+
dependencies: [],
|
|
514
|
+
domain: "custom",
|
|
515
|
+
authority: "authoritative",
|
|
516
|
+
importance: "critical",
|
|
517
|
+
levels: [
|
|
518
|
+
{
|
|
519
|
+
id: "fixed",
|
|
520
|
+
estimatedCostMs: 1.0,
|
|
521
|
+
config: {
|
|
522
|
+
maxDispatchesPerFrame: 1,
|
|
523
|
+
maxJobsPerDispatch: 2,
|
|
524
|
+
cadenceDivisor: 1,
|
|
525
|
+
workgroupScale: 1,
|
|
526
|
+
maxQueueDepth: 48,
|
|
527
|
+
},
|
|
528
|
+
},
|
|
529
|
+
],
|
|
530
|
+
suggestedAllocationIds: ["world.bake.field.scratch"],
|
|
531
|
+
},
|
|
532
|
+
terrainSynthesis: {
|
|
533
|
+
priority: 5,
|
|
534
|
+
dependencies: ["fractalPrepass", "fieldSynthesis"],
|
|
535
|
+
domain: "custom",
|
|
536
|
+
authority: "authoritative",
|
|
537
|
+
importance: "critical",
|
|
538
|
+
levels: [
|
|
539
|
+
{
|
|
540
|
+
id: "fixed",
|
|
541
|
+
estimatedCostMs: 1.6,
|
|
542
|
+
config: {
|
|
543
|
+
maxDispatchesPerFrame: 1,
|
|
544
|
+
maxJobsPerDispatch: 1,
|
|
545
|
+
cadenceDivisor: 1,
|
|
546
|
+
workgroupScale: 1,
|
|
547
|
+
maxQueueDepth: 32,
|
|
548
|
+
},
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
suggestedAllocationIds: ["world.bake.height.buffer"],
|
|
552
|
+
},
|
|
553
|
+
voxelMaterialize: {
|
|
554
|
+
priority: 3,
|
|
555
|
+
dependencies: ["terrainSynthesis"],
|
|
556
|
+
domain: "custom",
|
|
557
|
+
authority: "non-authoritative-simulation",
|
|
558
|
+
importance: "high",
|
|
559
|
+
levels: [
|
|
560
|
+
{
|
|
561
|
+
id: "low",
|
|
562
|
+
estimatedCostMs: 0.9,
|
|
563
|
+
config: {
|
|
564
|
+
maxDispatchesPerFrame: 1,
|
|
565
|
+
maxJobsPerDispatch: 1,
|
|
566
|
+
cadenceDivisor: 2,
|
|
567
|
+
workgroupScale: 0.6,
|
|
568
|
+
maxQueueDepth: 24,
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
id: "medium",
|
|
573
|
+
estimatedCostMs: 1.4,
|
|
574
|
+
config: {
|
|
575
|
+
maxDispatchesPerFrame: 1,
|
|
576
|
+
maxJobsPerDispatch: 2,
|
|
577
|
+
cadenceDivisor: 1,
|
|
578
|
+
workgroupScale: 0.8,
|
|
579
|
+
maxQueueDepth: 32,
|
|
580
|
+
},
|
|
581
|
+
},
|
|
582
|
+
{
|
|
583
|
+
id: "high",
|
|
584
|
+
estimatedCostMs: 2.0,
|
|
585
|
+
config: {
|
|
586
|
+
maxDispatchesPerFrame: 2,
|
|
587
|
+
maxJobsPerDispatch: 2,
|
|
588
|
+
cadenceDivisor: 1,
|
|
589
|
+
workgroupScale: 1,
|
|
590
|
+
maxQueueDepth: 48,
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
],
|
|
594
|
+
suggestedAllocationIds: ["world.bake.height.buffer"],
|
|
595
|
+
},
|
|
596
|
+
meshBuild: {
|
|
597
|
+
priority: 2,
|
|
598
|
+
dependencies: ["terrainSynthesis", "voxelMaterialize"],
|
|
599
|
+
domain: "geometry",
|
|
600
|
+
authority: "visual",
|
|
601
|
+
importance: "high",
|
|
602
|
+
levels: [
|
|
603
|
+
{
|
|
604
|
+
id: "low",
|
|
605
|
+
estimatedCostMs: 0.9,
|
|
606
|
+
config: {
|
|
607
|
+
maxDispatchesPerFrame: 1,
|
|
608
|
+
maxJobsPerDispatch: 1,
|
|
609
|
+
cadenceDivisor: 2,
|
|
610
|
+
workgroupScale: 0.6,
|
|
611
|
+
maxQueueDepth: 16,
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
id: "medium",
|
|
616
|
+
estimatedCostMs: 1.3,
|
|
617
|
+
config: {
|
|
618
|
+
maxDispatchesPerFrame: 1,
|
|
619
|
+
maxJobsPerDispatch: 1,
|
|
620
|
+
cadenceDivisor: 1,
|
|
621
|
+
workgroupScale: 0.8,
|
|
622
|
+
maxQueueDepth: 24,
|
|
623
|
+
},
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
id: "high",
|
|
627
|
+
estimatedCostMs: 1.9,
|
|
628
|
+
config: {
|
|
629
|
+
maxDispatchesPerFrame: 2,
|
|
630
|
+
maxJobsPerDispatch: 2,
|
|
631
|
+
cadenceDivisor: 1,
|
|
632
|
+
workgroupScale: 1,
|
|
633
|
+
maxQueueDepth: 32,
|
|
634
|
+
},
|
|
635
|
+
},
|
|
636
|
+
],
|
|
637
|
+
suggestedAllocationIds: ["world.bake.mesh.buffer"],
|
|
638
|
+
},
|
|
639
|
+
tileBake: {
|
|
640
|
+
priority: 2,
|
|
641
|
+
dependencies: ["terrainSynthesis"],
|
|
642
|
+
domain: "textures",
|
|
643
|
+
authority: "non-authoritative-simulation",
|
|
644
|
+
importance: "medium",
|
|
645
|
+
levels: [
|
|
646
|
+
{
|
|
647
|
+
id: "low",
|
|
648
|
+
estimatedCostMs: 0.8,
|
|
649
|
+
config: {
|
|
650
|
+
maxDispatchesPerFrame: 1,
|
|
651
|
+
maxJobsPerDispatch: 1,
|
|
652
|
+
cadenceDivisor: 3,
|
|
653
|
+
workgroupScale: 0.5,
|
|
654
|
+
maxQueueDepth: 16,
|
|
655
|
+
},
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
id: "medium",
|
|
659
|
+
estimatedCostMs: 1.1,
|
|
660
|
+
config: {
|
|
661
|
+
maxDispatchesPerFrame: 1,
|
|
662
|
+
maxJobsPerDispatch: 1,
|
|
663
|
+
cadenceDivisor: 2,
|
|
664
|
+
workgroupScale: 0.75,
|
|
665
|
+
maxQueueDepth: 24,
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
id: "high",
|
|
670
|
+
estimatedCostMs: 1.5,
|
|
671
|
+
config: {
|
|
672
|
+
maxDispatchesPerFrame: 2,
|
|
673
|
+
maxJobsPerDispatch: 2,
|
|
674
|
+
cadenceDivisor: 1,
|
|
675
|
+
workgroupScale: 1,
|
|
676
|
+
maxQueueDepth: 32,
|
|
677
|
+
},
|
|
678
|
+
},
|
|
679
|
+
],
|
|
680
|
+
suggestedAllocationIds: ["world.bake.height.buffer"],
|
|
681
|
+
},
|
|
682
|
+
assetSerialize: {
|
|
683
|
+
priority: 1,
|
|
684
|
+
dependencies: ["meshBuild", "tileBake"],
|
|
685
|
+
domain: "custom",
|
|
686
|
+
authority: "non-authoritative-simulation",
|
|
687
|
+
importance: "medium",
|
|
688
|
+
levels: [
|
|
689
|
+
{
|
|
690
|
+
id: "low",
|
|
691
|
+
estimatedCostMs: 0.4,
|
|
692
|
+
config: {
|
|
693
|
+
maxDispatchesPerFrame: 1,
|
|
694
|
+
maxJobsPerDispatch: 1,
|
|
695
|
+
cadenceDivisor: 4,
|
|
696
|
+
workgroupScale: 0.5,
|
|
697
|
+
maxQueueDepth: 8,
|
|
698
|
+
},
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
id: "medium",
|
|
702
|
+
estimatedCostMs: 0.7,
|
|
703
|
+
config: {
|
|
704
|
+
maxDispatchesPerFrame: 1,
|
|
705
|
+
maxJobsPerDispatch: 1,
|
|
706
|
+
cadenceDivisor: 2,
|
|
707
|
+
workgroupScale: 0.75,
|
|
708
|
+
maxQueueDepth: 12,
|
|
709
|
+
},
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
id: "high",
|
|
713
|
+
estimatedCostMs: 1.0,
|
|
714
|
+
config: {
|
|
715
|
+
maxDispatchesPerFrame: 2,
|
|
716
|
+
maxJobsPerDispatch: 2,
|
|
717
|
+
cadenceDivisor: 1,
|
|
718
|
+
workgroupScale: 1,
|
|
719
|
+
maxQueueDepth: 16,
|
|
720
|
+
},
|
|
721
|
+
},
|
|
722
|
+
],
|
|
723
|
+
suggestedAllocationIds: ["world.bake.asset.binary"],
|
|
724
|
+
},
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
function buildWorldGeneratorWorkerProfile(
|
|
730
|
+
name: WorldGeneratorWorkerProfileName,
|
|
731
|
+
spec: WorkerProfileSpec
|
|
732
|
+
) {
|
|
733
|
+
return Object.freeze({
|
|
734
|
+
name,
|
|
735
|
+
description: spec.description,
|
|
736
|
+
jobs: Object.freeze(Object.keys(spec.jobs)),
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
function buildWorldGeneratorWorkerManifestJob(
|
|
741
|
+
profileName: WorldGeneratorWorkerProfileName,
|
|
742
|
+
jobName: string,
|
|
743
|
+
spec: WorkerJobSpec
|
|
744
|
+
) {
|
|
745
|
+
const label = `world-generator.${profileName}.${jobName}`;
|
|
746
|
+
return Object.freeze({
|
|
747
|
+
key: jobName,
|
|
748
|
+
label,
|
|
749
|
+
worker: Object.freeze({
|
|
750
|
+
jobType: label,
|
|
751
|
+
queueClass: worldGeneratorWorkerQueueClass,
|
|
752
|
+
priority: spec.priority,
|
|
753
|
+
dependencies: Object.freeze(
|
|
754
|
+
spec.dependencies.map(
|
|
755
|
+
(dependency) => `world-generator.${profileName}.${dependency}`
|
|
756
|
+
)
|
|
757
|
+
),
|
|
758
|
+
schedulerMode: "dag",
|
|
759
|
+
}),
|
|
760
|
+
performance: Object.freeze({
|
|
761
|
+
id: label,
|
|
762
|
+
jobType: label,
|
|
763
|
+
queueClass: worldGeneratorWorkerQueueClass,
|
|
764
|
+
domain: spec.domain,
|
|
765
|
+
authority: spec.authority,
|
|
766
|
+
importance: spec.importance,
|
|
767
|
+
levels: buildBudgetLevels(
|
|
768
|
+
label,
|
|
769
|
+
worldGeneratorWorkerQueueClass,
|
|
770
|
+
spec.levels
|
|
771
|
+
),
|
|
772
|
+
}),
|
|
773
|
+
debug: Object.freeze({
|
|
774
|
+
owner: worldGeneratorDebugOwner,
|
|
775
|
+
queueClass: worldGeneratorWorkerQueueClass,
|
|
776
|
+
jobType: label,
|
|
777
|
+
tags: Object.freeze(["world-generator", profileName, jobName, spec.domain]),
|
|
778
|
+
suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),
|
|
779
|
+
}),
|
|
780
|
+
});
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function buildWorldGeneratorWorkerManifest(
|
|
784
|
+
name: WorldGeneratorWorkerProfileName,
|
|
785
|
+
spec: WorkerProfileSpec
|
|
786
|
+
) {
|
|
787
|
+
return Object.freeze({
|
|
788
|
+
schemaVersion: 1,
|
|
789
|
+
owner: worldGeneratorDebugOwner,
|
|
790
|
+
profile: name,
|
|
791
|
+
description: spec.description,
|
|
792
|
+
queueClass: worldGeneratorWorkerQueueClass,
|
|
793
|
+
schedulerMode: "dag",
|
|
794
|
+
suggestedAllocationIds: Object.freeze([...spec.suggestedAllocationIds]),
|
|
795
|
+
jobs: Object.freeze(
|
|
796
|
+
Object.entries(spec.jobs).map(([jobName, jobSpec]) =>
|
|
797
|
+
buildWorldGeneratorWorkerManifestJob(name, jobName, jobSpec)
|
|
798
|
+
)
|
|
799
|
+
),
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
export const worldGeneratorWorkerProfiles = Object.freeze(
|
|
804
|
+
Object.fromEntries(
|
|
805
|
+
Object.entries(worldGeneratorWorkerProfileSpecs).map(([name, spec]) => [
|
|
806
|
+
name,
|
|
807
|
+
buildWorldGeneratorWorkerProfile(
|
|
808
|
+
name as WorldGeneratorWorkerProfileName,
|
|
809
|
+
spec
|
|
810
|
+
),
|
|
811
|
+
])
|
|
812
|
+
)
|
|
813
|
+
) as Readonly<Record<WorldGeneratorWorkerProfileName, WorldGeneratorWorkerProfile>>;
|
|
814
|
+
|
|
815
|
+
export const worldGeneratorWorkerProfileNames = Object.freeze(
|
|
816
|
+
Object.keys(worldGeneratorWorkerProfiles)
|
|
817
|
+
) as readonly WorldGeneratorWorkerProfileName[];
|
|
818
|
+
|
|
819
|
+
export const worldGeneratorWorkerManifests = Object.freeze(
|
|
820
|
+
Object.fromEntries(
|
|
821
|
+
Object.entries(worldGeneratorWorkerProfileSpecs).map(([name, spec]) => [
|
|
822
|
+
name,
|
|
823
|
+
buildWorldGeneratorWorkerManifest(
|
|
824
|
+
name as WorldGeneratorWorkerProfileName,
|
|
825
|
+
spec
|
|
826
|
+
),
|
|
827
|
+
])
|
|
828
|
+
)
|
|
829
|
+
) as Readonly<Record<WorldGeneratorWorkerProfileName, WorldGeneratorWorkerManifest>>;
|
|
830
|
+
|
|
831
|
+
export function getWorldGeneratorWorkerProfile(
|
|
832
|
+
name: WorldGeneratorWorkerProfileName = defaultWorldGeneratorWorkerProfile
|
|
833
|
+
) {
|
|
834
|
+
const profile = worldGeneratorWorkerProfiles[name];
|
|
835
|
+
if (!profile) {
|
|
836
|
+
const available = worldGeneratorWorkerProfileNames.join(", ");
|
|
837
|
+
throw new Error(
|
|
838
|
+
`Unknown world-generator worker profile "${name}". Available: ${available}.`
|
|
839
|
+
);
|
|
840
|
+
}
|
|
841
|
+
return profile;
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
export function getWorldGeneratorWorkerManifest(
|
|
845
|
+
name: WorldGeneratorWorkerProfileName = defaultWorldGeneratorWorkerProfile
|
|
846
|
+
) {
|
|
847
|
+
const manifest = worldGeneratorWorkerManifests[name];
|
|
848
|
+
if (!manifest) {
|
|
849
|
+
const available = worldGeneratorWorkerProfileNames.join(", ");
|
|
850
|
+
throw new Error(
|
|
851
|
+
`Unknown world-generator worker profile "${name}". Available: ${available}.`
|
|
852
|
+
);
|
|
853
|
+
}
|
|
854
|
+
return manifest;
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
export function createWorldGeneratorRepresentationPlan(options: {
|
|
858
|
+
profile?: WorldGeneratorWorkerProfileName;
|
|
859
|
+
chunkId: string;
|
|
860
|
+
gameplayImportance?: WorldGeneratorWorkerImportance;
|
|
861
|
+
}): WorldGeneratorRepresentationPlan {
|
|
862
|
+
const profile =
|
|
863
|
+
options.profile ?? defaultWorldGeneratorWorkerProfile;
|
|
864
|
+
const spec = worldGeneratorWorkerProfileSpecs[profile];
|
|
865
|
+
if (!spec) {
|
|
866
|
+
const available = worldGeneratorWorkerProfileNames.join(", ");
|
|
867
|
+
throw new Error(
|
|
868
|
+
`Unknown world-generator worker profile "${profile}". Available: ${available}.`
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
const chunkId = assertWorldGeneratorIdentifier("chunkId", options.chunkId);
|
|
873
|
+
const gameplayImportance = normalizeWorldGeneratorImportance(
|
|
874
|
+
"gameplayImportance",
|
|
875
|
+
options.gameplayImportance ?? "high"
|
|
876
|
+
);
|
|
877
|
+
|
|
878
|
+
const highValueAllocations = spec.suggestedAllocationIds;
|
|
879
|
+
const farFieldAllocations = spec.suggestedAllocationIds.filter(
|
|
880
|
+
(allocationId) =>
|
|
881
|
+
allocationId.includes("mesh") ||
|
|
882
|
+
allocationId.includes("asset") ||
|
|
883
|
+
allocationId.includes("tile")
|
|
884
|
+
);
|
|
885
|
+
|
|
886
|
+
const bakeSourceJobKeys =
|
|
887
|
+
profile === "bake"
|
|
888
|
+
? ["meshBuild", "tileBake", "assetSerialize"]
|
|
889
|
+
: ["meshBuild", "tileBake"];
|
|
890
|
+
|
|
891
|
+
const representations = Object.freeze([
|
|
892
|
+
buildWorldGeneratorRepresentationDescriptor({
|
|
893
|
+
profile,
|
|
894
|
+
chunkId,
|
|
895
|
+
band: "near",
|
|
896
|
+
output: "liveGeometry",
|
|
897
|
+
rasterMode: "full-live",
|
|
898
|
+
rtParticipation: "full",
|
|
899
|
+
shadowRelevance: "ray-traced-primary",
|
|
900
|
+
refreshCadence: { kind: "per-frame", divisor: 1 },
|
|
901
|
+
preservesChunkIdentity: true,
|
|
902
|
+
sourceJobKeys: ["meshBuild"],
|
|
903
|
+
gameplayImportance:
|
|
904
|
+
gameplayImportance === "medium" ? "high" : gameplayImportance,
|
|
905
|
+
suggestedAllocationIds: highValueAllocations,
|
|
906
|
+
}),
|
|
907
|
+
buildWorldGeneratorRepresentationDescriptor({
|
|
908
|
+
profile,
|
|
909
|
+
chunkId,
|
|
910
|
+
band: "mid",
|
|
911
|
+
output: "simplifiedGeometry",
|
|
912
|
+
rasterMode: "simplified-live",
|
|
913
|
+
rtParticipation: "selective",
|
|
914
|
+
shadowRelevance: "selective-raster",
|
|
915
|
+
refreshCadence: { kind: "interval", divisor: 2 },
|
|
916
|
+
preservesChunkIdentity: true,
|
|
917
|
+
sourceJobKeys: ["meshBuild"],
|
|
918
|
+
gameplayImportance,
|
|
919
|
+
suggestedAllocationIds: highValueAllocations,
|
|
920
|
+
}),
|
|
921
|
+
buildWorldGeneratorRepresentationDescriptor({
|
|
922
|
+
profile,
|
|
923
|
+
chunkId,
|
|
924
|
+
band: "mid",
|
|
925
|
+
output: "rtProxy",
|
|
926
|
+
rasterMode: "not-rendered",
|
|
927
|
+
rtParticipation: "proxy",
|
|
928
|
+
shadowRelevance: "selective-raster",
|
|
929
|
+
refreshCadence: { kind: "interval", divisor: 2 },
|
|
930
|
+
preservesChunkIdentity: true,
|
|
931
|
+
sourceJobKeys: ["meshBuild", "tileBake"],
|
|
932
|
+
gameplayImportance,
|
|
933
|
+
suggestedAllocationIds: highValueAllocations,
|
|
934
|
+
}),
|
|
935
|
+
buildWorldGeneratorRepresentationDescriptor({
|
|
936
|
+
profile,
|
|
937
|
+
chunkId,
|
|
938
|
+
band: "far",
|
|
939
|
+
output: "mergedProxy",
|
|
940
|
+
rasterMode: "proxy",
|
|
941
|
+
rtParticipation: "proxy",
|
|
942
|
+
shadowRelevance: "proxy-caster",
|
|
943
|
+
refreshCadence: { kind: "interval", divisor: 8 },
|
|
944
|
+
preservesChunkIdentity: true,
|
|
945
|
+
sourceJobKeys: bakeSourceJobKeys,
|
|
946
|
+
gameplayImportance: "medium",
|
|
947
|
+
suggestedAllocationIds:
|
|
948
|
+
farFieldAllocations.length > 0 ? farFieldAllocations : highValueAllocations,
|
|
949
|
+
}),
|
|
950
|
+
buildWorldGeneratorRepresentationDescriptor({
|
|
951
|
+
profile,
|
|
952
|
+
chunkId,
|
|
953
|
+
band: "horizon",
|
|
954
|
+
output: "horizonShell",
|
|
955
|
+
rasterMode: "horizon-shell",
|
|
956
|
+
rtParticipation: "disabled",
|
|
957
|
+
shadowRelevance: "baked-impression",
|
|
958
|
+
refreshCadence: { kind: "interval", divisor: 60 },
|
|
959
|
+
preservesChunkIdentity: true,
|
|
960
|
+
sourceJobKeys:
|
|
961
|
+
profile === "bake" ? ["tileBake", "assetSerialize"] : ["tileBake"],
|
|
962
|
+
gameplayImportance: "medium",
|
|
963
|
+
suggestedAllocationIds:
|
|
964
|
+
farFieldAllocations.length > 0 ? farFieldAllocations : highValueAllocations,
|
|
965
|
+
}),
|
|
966
|
+
] satisfies readonly WorldGeneratorRepresentationDescriptor[]);
|
|
967
|
+
|
|
968
|
+
return Object.freeze({
|
|
969
|
+
schemaVersion: 1,
|
|
970
|
+
owner: worldGeneratorDebugOwner,
|
|
971
|
+
profile,
|
|
972
|
+
chunkId,
|
|
973
|
+
representations,
|
|
974
|
+
bands: Object.freeze(
|
|
975
|
+
[...new Set(representations.map((representation) => representation.band))]
|
|
976
|
+
),
|
|
977
|
+
});
|
|
978
|
+
}
|