Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@plasius/gpu-worker

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@plasius/gpu-worker - npm Package Compare versions

Comparing version
0.1.10
to
0.1.11
+22
-1
CHANGELOG.md

@@ -23,2 +23,22 @@ # Changelog

## [0.1.11] - 2026-03-15
- **Added**
- ADR, TDR, and test-first planning coverage for snapshot-driven
scene-preparation DAG manifests in the ray-tracing-first world pipeline.
- Added `createScenePreparationManifest(...)` plus scene-preparation
representation-band and stage-family exports for snapshot-driven chunk DAG
planning.
- Added contract tests covering stable snapshot roots, multi-chunk priority
lanes, local joins, and render-preparation safety guards.
- **Changed**
- TDR-0004 now reflects the implemented scene-preparation manifest helper.
- **Fixed**
- (placeholder)
- **Security**
- (placeholder)
## [0.1.10] - 2026-03-14

@@ -214,3 +234,3 @@

[Unreleased]: https://github.com/Plasius-LTD/gpu-worker/compare/v0.1.10...HEAD
[Unreleased]: https://github.com/Plasius-LTD/gpu-worker/compare/v0.1.11...HEAD
[0.1.0-beta.1]: https://github.com/Plasius-LTD/gpu-worker/releases/tag/v0.1.0-beta.1

@@ -238,1 +258,2 @@ [0.1.0]: https://github.com/Plasius-LTD/gpu-worker/releases/tag/v0.1.0

[0.1.10]: https://github.com/Plasius-LTD/gpu-worker/releases/tag/v0.1.10
[0.1.11]: https://github.com/Plasius-LTD/gpu-worker/releases/tag/v0.1.11

@@ -33,2 +33,3 @@ var __create = Object.create;

assembleWorkerWgsl: () => assembleWorkerWgsl,
createScenePreparationManifest: () => createScenePreparationManifest,
createWorkerLoop: () => createWorkerLoop,

@@ -38,2 +39,4 @@ loadJobWgsl: () => loadJobWgsl,

loadWorkerWgsl: () => loadWorkerWgsl,
scenePreparationRepresentationBands: () => scenePreparationRepresentationBands,
scenePreparationStageFamilies: () => scenePreparationStageFamilies,
workerWgslUrl: () => workerWgslUrl

@@ -698,5 +701,314 @@ });

}
var scenePreparationRepresentationBands = Object.freeze([
"near",
"mid",
"far",
"horizon"
]);
var scenePreparationStageFamilies = Object.freeze([
"snapshotSelection",
"transformPropagation",
"animationPose",
"proceduralAnimation",
"skinningOrDeformation",
"boundsUpdate",
"lodSelection",
"rtRepresentationSelection",
"visibility",
"lightAssignment",
"renderProxyBuild",
"rtInstancePreparation"
]);
var scenePreparationDefaultStageDependencies = Object.freeze({
snapshotSelection: Object.freeze([]),
transformPropagation: Object.freeze(["snapshotSelection"]),
animationPose: Object.freeze(["transformPropagation"]),
proceduralAnimation: Object.freeze(["animationPose"]),
skinningOrDeformation: Object.freeze([
"animationPose",
"proceduralAnimation"
]),
boundsUpdate: Object.freeze(["skinningOrDeformation"]),
lodSelection: Object.freeze(["boundsUpdate"]),
rtRepresentationSelection: Object.freeze(["lodSelection"]),
visibility: Object.freeze(["boundsUpdate", "lodSelection"]),
lightAssignment: Object.freeze(["visibility"]),
renderProxyBuild: Object.freeze(["visibility", "lodSelection"]),
rtInstancePreparation: Object.freeze([
"visibility",
"rtRepresentationSelection"
])
});
var scenePreparationBandPriorityWeights = Object.freeze({
near: 400,
mid: 300,
far: 200,
horizon: 100
});
var scenePreparationImportanceWeights = Object.freeze({
low: 0,
medium: 15,
high: 30,
critical: 60
});
var scenePreparationStagePriorityWeights = Object.freeze({
snapshotSelection: 60,
transformPropagation: 54,
animationPose: 50,
proceduralAnimation: 46,
skinningOrDeformation: 42,
boundsUpdate: 38,
lodSelection: 32,
rtRepresentationSelection: 28,
visibility: 34,
lightAssignment: 24,
renderProxyBuild: 22,
rtInstancePreparation: 26
});
function assertScenePreparationIdentifier(name, value) {
if (typeof value !== "string" || value.trim().length === 0) {
throw new Error(`${name} must be a non-empty string.`);
}
return value.trim();
}
function assertScenePreparationEnum(name, value, allowed) {
const normalized = assertScenePreparationIdentifier(name, value);
if (!allowed.includes(normalized)) {
throw new Error(`${name} must be one of: ${allowed.join(", ")}.`);
}
return normalized;
}
function normalizeScenePreparationStages(stages, chunkLabel) {
const requested = stages === void 0 ? scenePreparationStageFamilies : stages;
if (!Array.isArray(requested) || requested.length === 0) {
throw new Error(`${chunkLabel}.stages must be a non-empty array when provided.`);
}
const normalized = [...new Set(
requested.map(
(stage, index) => assertScenePreparationEnum(
`${chunkLabel}.stages[${index}]`,
stage,
scenePreparationStageFamilies
)
)
)];
return normalized.sort(
(left, right) => scenePreparationStageFamilies.indexOf(left) - scenePreparationStageFamilies.indexOf(right)
);
}
function collectScenePreparationDependencies(stageFamily, includedStages, seen = /* @__PURE__ */ new Set()) {
const dependencies = scenePreparationDefaultStageDependencies[stageFamily] ?? [];
for (const dependency of dependencies) {
if (includedStages.has(dependency)) {
seen.add(dependency);
continue;
}
collectScenePreparationDependencies(dependency, includedStages, seen);
}
return [...seen].sort(
(left, right) => scenePreparationStageFamilies.indexOf(left) - scenePreparationStageFamilies.indexOf(right)
);
}
function buildScenePreparationPriority(chunk, stageFamily) {
const bandWeight = scenePreparationBandPriorityWeights[chunk.representationBand] ?? 0;
const importanceWeight = scenePreparationImportanceWeights[chunk.gameplayImportance] ?? 0;
const stageWeight = scenePreparationStagePriorityWeights[stageFamily] ?? 0;
return bandWeight + importanceWeight + stageWeight + (chunk.visible ? 20 : 0) + (chunk.playerRelevant ? 20 : 0) + (chunk.imageCritical ? 15 : 0);
}
function buildScenePreparationPriorityLanes(jobs) {
const lanes = /* @__PURE__ */ new Map();
for (const job of jobs) {
const lane = lanes.get(job.priority) ?? {
priority: job.priority,
jobIds: [],
chunkIds: []
};
lane.jobIds.push(job.id);
if (!lane.chunkIds.includes(job.chunkId)) {
lane.chunkIds.push(job.chunkId);
}
lanes.set(job.priority, lane);
}
return Object.freeze(
[...lanes.values()].sort((left, right) => right.priority - left.priority).map(
(lane) => Object.freeze({
priority: lane.priority,
jobIds: Object.freeze([...lane.jobIds]),
chunkIds: Object.freeze([...lane.chunkIds]),
jobCount: lane.jobIds.length
})
)
);
}
function buildScenePreparationTopologicalOrder(jobs) {
const indegree = new Map(jobs.map((job) => [job.id, job.dependencies.length]));
const dependentsById = new Map(jobs.map((job) => [job.id, []]));
for (const job of jobs) {
for (const dependency of job.dependencies) {
dependentsById.get(dependency)?.push(job.id);
}
}
const queue = jobs.filter((job) => job.dependencies.length === 0).sort((left, right) => right.priority - left.priority).map((job) => job.id);
const jobById = new Map(jobs.map((job) => [job.id, job]));
const order = [];
while (queue.length > 0) {
const currentId = queue.shift();
if (!currentId) {
continue;
}
order.push(currentId);
const unlocked = [];
for (const dependentId of dependentsById.get(currentId) ?? []) {
const next = (indegree.get(dependentId) ?? 0) - 1;
indegree.set(dependentId, next);
if (next === 0) {
unlocked.push(dependentId);
}
}
unlocked.sort(
(left, right) => (jobById.get(right)?.priority ?? 0) - (jobById.get(left)?.priority ?? 0)
).forEach((jobId) => {
queue.push(jobId);
});
}
if (order.length !== jobs.length) {
throw new Error("Scene-preparation manifest contains a cycle.");
}
return Object.freeze(order);
}
function createScenePreparationManifest(options = {}) {
const snapshotId = assertScenePreparationIdentifier(
"snapshotId",
options.snapshotId
);
const chunkEntries = Array.isArray(options.chunks) ? options.chunks : [];
if (chunkEntries.length === 0) {
throw new Error("createScenePreparationManifest requires at least one chunk.");
}
const normalizedChunks = chunkEntries.map((chunk, index) => {
if (!chunk || typeof chunk !== "object" || Array.isArray(chunk)) {
throw new Error(`chunks[${index}] must be an object.`);
}
const chunkLabel = `chunks[${index}]`;
if (chunk.mutatesSimulation === true) {
throw new Error(
`${chunkLabel}.mutatesSimulation cannot be true for render preparation.`
);
}
return Object.freeze({
chunkId: assertScenePreparationIdentifier(`${chunkLabel}.chunkId`, chunk.chunkId),
representationBand: assertScenePreparationEnum(
`${chunkLabel}.representationBand`,
chunk.representationBand ?? "mid",
scenePreparationRepresentationBands
),
gameplayImportance: assertScenePreparationEnum(
`${chunkLabel}.gameplayImportance`,
chunk.gameplayImportance ?? "medium",
Object.keys(scenePreparationImportanceWeights)
),
visible: chunk.visible !== false,
playerRelevant: chunk.playerRelevant === true,
imageCritical: chunk.imageCritical === true,
stages: normalizeScenePreparationStages(chunk.stages, chunkLabel)
});
});
const chunkIds = /* @__PURE__ */ new Set();
for (const chunk of normalizedChunks) {
if (chunkIds.has(chunk.chunkId)) {
throw new Error(`Duplicate scene-preparation chunk id detected: ${chunk.chunkId}`);
}
chunkIds.add(chunk.chunkId);
}
const jobs = [];
for (const chunk of normalizedChunks) {
const includedStages = new Set(chunk.stages);
for (const stageFamily of chunk.stages) {
const dependencies = collectScenePreparationDependencies(
stageFamily,
includedStages
).map(
(dependency) => `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${dependency}`
);
jobs.push(
Object.freeze({
id: `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${stageFamily}`,
snapshotId,
chunkId: chunk.chunkId,
representationBand: chunk.representationBand,
stageFamily,
priority: buildScenePreparationPriority(chunk, stageFamily),
dependencies: Object.freeze(dependencies),
dependencyCount: dependencies.length,
root: dependencies.length === 0,
authority: "visual",
mutatesSimulation: false,
gameplayImportance: chunk.gameplayImportance,
visible: chunk.visible,
playerRelevant: chunk.playerRelevant,
imageCritical: chunk.imageCritical
})
);
}
}
const jobById = new Map(jobs.map((job) => [job.id, job]));
let crossChunkDependencyCount = 0;
let localJoinCount = 0;
const finalizedJobs = Object.freeze(
jobs.map((job) => {
const dependents = jobs.filter((candidate) => candidate.dependencies.includes(job.id)).map((candidate) => candidate.id);
const crossChunkDependencies = job.dependencies.filter((dependency) => {
const parent = jobById.get(dependency);
return parent && parent.chunkId !== job.chunkId;
});
crossChunkDependencyCount += crossChunkDependencies.length;
if (job.dependencies.length > 1 && crossChunkDependencies.length === 0) {
localJoinCount += 1;
}
return Object.freeze({
...job,
dependents: Object.freeze(dependents),
dependentCount: dependents.length,
unresolvedDependencyCount: job.dependencies.length,
localJoin: job.dependencies.length > 1 && crossChunkDependencies.length === 0
});
})
);
const graph = Object.freeze({
schedulerMode: "dag",
jobCount: finalizedJobs.length,
chunkCount: normalizedChunks.length,
chunkIds: Object.freeze(normalizedChunks.map((chunk) => chunk.chunkId)),
representationBands: Object.freeze(
[...new Set(normalizedChunks.map((chunk) => chunk.representationBand))]
),
roots: Object.freeze(
finalizedJobs.filter((job) => job.root).map((job) => job.id)
),
chunkRoots: Object.freeze(
Object.fromEntries(
normalizedChunks.map((chunk) => [
chunk.chunkId,
finalizedJobs.filter((job) => job.chunkId === chunk.chunkId && job.root).map((job) => job.id)
])
)
),
topologicalOrder: buildScenePreparationTopologicalOrder(finalizedJobs),
priorityLanes: buildScenePreparationPriorityLanes(finalizedJobs),
localJoinCount,
crossChunkDependencyCount
});
return Object.freeze({
schemaVersion: 1,
owner: "scene-preparation",
schedulerMode: "dag",
snapshotId,
jobs: finalizedJobs,
graph
});
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
assembleWorkerWgsl,
createScenePreparationManifest,
createWorkerLoop,

@@ -706,4 +1018,6 @@ loadJobWgsl,

loadWorkerWgsl,
scenePreparationRepresentationBands,
scenePreparationStageFamilies,
workerWgslUrl
});
//# sourceMappingURL=index.cjs.map
+1
-1

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.js"],"sourcesContent":["import {\n loadSchedulerWgsl as loadSchedulerWgslRaw,\n schedulerModes as workerSchedulerModes,\n} from \"@plasius/gpu-lock-free-queue\";\n\nexport const workerWgslUrl = (() => {\n if (typeof __IMPORT_META_URL__ !== \"undefined\") {\n return new URL(\"./worker.wgsl\", __IMPORT_META_URL__);\n }\n if (typeof __filename !== \"undefined\" && typeof require !== \"undefined\") {\n const { pathToFileURL } = require(\"node:url\");\n return new URL(\"./worker.wgsl\", pathToFileURL(__filename));\n }\n const base =\n typeof process !== \"undefined\" && process.cwd\n ? `file://${process.cwd()}/`\n : \"file:///\";\n return new URL(\"./worker.wgsl\", base);\n})();\n\nconst jobRegistry = [];\nlet nextJobType = 0;\n\nasync function loadWgslSource(options = {}) {\n const { wgsl, url, fetcher = globalThis.fetch, baseUrl } = options ?? {};\n if (typeof wgsl === \"string\") {\n assertNotHtmlWgsl(wgsl, \"inline WGSL\");\n return wgsl;\n }\n if (!url) {\n return null;\n }\n const resolved = url instanceof URL ? url : new URL(url, baseUrl);\n if (!fetcher) {\n if (resolved.protocol !== \"file:\") {\n throw new Error(\"No fetcher available for non-file WGSL URL.\");\n }\n const { readFile } = await import(\"fs/promises\");\n const { fileURLToPath } = await import(\"url\");\n const source = await readFile(fileURLToPath(resolved), \"utf8\");\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n }\n const response = await fetcher(resolved);\n if (!response.ok) {\n const status = \"status\" in response ? response.status : \"unknown\";\n const statusText = \"statusText\" in response ? response.statusText : \"\";\n const detail = statusText ? `${status} ${statusText}` : `${status}`;\n throw new Error(`Failed to load WGSL (${detail})`);\n }\n const source = await response.text();\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n}\n\nfunction stripComments(source) {\n return source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/\\/\\/.*$/gm, \"\");\n}\n\nfunction tokenize(source) {\n return source.match(/[A-Za-z_][A-Za-z0-9_]*|[{}();<>,:=]/g) ?? [];\n}\n\nfunction isIdentifier(token) {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(token);\n}\n\nfunction readNameAfterType(tokens, startIndex) {\n let i = startIndex;\n if (tokens[i] === \"<\") {\n let depth = 1;\n i += 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i] === \"<\") {\n depth += 1;\n } else if (tokens[i] === \">\") {\n depth -= 1;\n }\n i += 1;\n }\n }\n return tokens[i];\n}\n\nfunction scanModuleNames(source) {\n const cleaned = stripComments(source);\n const tokens = tokenize(cleaned);\n const names = [];\n let depth = 0;\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i];\n if (token === \"{\") {\n depth += 1;\n continue;\n }\n if (token === \"}\") {\n depth = Math.max(0, depth - 1);\n continue;\n }\n if (depth !== 0) {\n continue;\n }\n if (token === \"fn\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"fn\", name });\n }\n continue;\n }\n if (token === \"struct\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"struct\", name });\n }\n continue;\n }\n if (token === \"alias\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"alias\", name });\n }\n continue;\n }\n if (token === \"var\" || token === \"let\" || token === \"const\" || token === \"override\") {\n const name = readNameAfterType(tokens, i + 1);\n if (isIdentifier(name)) {\n names.push({ kind: token, name });\n }\n }\n }\n return names;\n}\n\nfunction buildNameIndex(modules) {\n const index = new Map();\n for (const module of modules) {\n for (const item of scanModuleNames(module.source)) {\n const bucket = index.get(item.name) ?? [];\n bucket.push({ kind: item.kind, module: module.name });\n index.set(item.name, bucket);\n }\n }\n return index;\n}\n\nfunction assertNoNameClashes(modules) {\n const index = buildNameIndex(modules);\n const clashes = [];\n for (const [name, entries] of index.entries()) {\n if (entries.length > 1) {\n clashes.push({ name, entries });\n }\n }\n if (clashes.length === 0) {\n return;\n }\n const lines = [\"WGSL debug: identifier clashes detected:\"];\n for (const clash of clashes) {\n const locations = clash.entries\n .map((entry) => `${entry.module} (${entry.kind})`)\n .join(\", \");\n lines.push(`- ${clash.name}: ${locations}`);\n }\n throw new Error(lines.join(\"\\n\"));\n}\n\nfunction assertNotHtmlWgsl(source, context) {\n const sample = source.slice(0, 200).toLowerCase();\n if (\n sample.includes(\"<!doctype\") ||\n sample.includes(\"<html\") ||\n sample.includes(\"<meta\")\n ) {\n const label = context ? ` for ${context}` : \"\";\n throw new Error(\n `Expected WGSL${label} but received HTML. Check the URL or server root.`\n );\n }\n}\n\nfunction renameProcessJob(source, name) {\n return source.replace(/\\bprocess_job\\b/g, name);\n}\n\nfunction getQueueCompatMap(source) {\n if (!/\\bJobMeta\\b/.test(source)) {\n return null;\n }\n return [{ from: /\\bJobMeta\\b/g, to: \"JobDesc\" }];\n}\n\nfunction normalizeQueueMode(mode) {\n const resolved = mode ?? \"flat\";\n if (!workerSchedulerModes.includes(resolved)) {\n throw new Error(\n `queueMode must be one of: ${workerSchedulerModes.join(\", \")}.`\n );\n }\n return resolved;\n}\n\nfunction applyCompatMap(source, map) {\n if (!map || map.length === 0) {\n return source;\n }\n let next = source;\n for (const entry of map) {\n next = next.replace(entry.from, entry.to);\n }\n return next;\n}\n\nfunction normalizeJobs(jobs) {\n const normalized = jobs.map((job, index) => {\n if (typeof job === \"string\") {\n return {\n jobType: index,\n wgsl: job,\n label: `job_${index}`,\n sourceName: `job-${index}`,\n };\n }\n if (!job || typeof job.wgsl !== \"string\") {\n throw new Error(\"Job entries must provide WGSL source strings.\");\n }\n const jobType = job.jobType ?? index;\n const label = job.label ?? `job_${jobType}`;\n return {\n jobType,\n wgsl: job.wgsl,\n label,\n sourceName: job.sourceName ?? job.label ?? `job-${jobType}`,\n };\n });\n const seen = new Set();\n for (const job of normalized) {\n if (seen.has(job.jobType)) {\n throw new Error(`Duplicate job_type detected: ${job.jobType}`);\n }\n seen.add(job.jobType);\n }\n return normalized;\n}\n\nfunction buildProcessJobDispatch(jobs) {\n const lines = [\n \"fn process_job(job_index: u32, job_type: u32, payload_words: u32) {\",\n ];\n if (jobs.length === 0) {\n lines.push(\" return;\");\n lines.push(\"}\");\n return lines.join(\"\\n\");\n }\n jobs.forEach((job, idx) => {\n const clause = idx === 0 ? \"if\" : \"else if\";\n lines.push(` ${clause} (job_type == ${job.jobType}u) {`);\n lines.push(\n ` ${job.entryName}(job_index, job_type, payload_words);`\n );\n lines.push(\" }\");\n });\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nexport async function loadWorkerWgsl(options = {}) {\n const { url = workerWgslUrl, fetcher } = options ?? {};\n const source = await loadWgslSource({\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load worker WGSL source.\");\n }\n return source;\n}\n\nexport async function loadQueueWgsl(options = {}) {\n const { queueCompat = true, queueMode = \"flat\", ...rest } = options ?? {};\n const source = await loadSchedulerWgslRaw({\n mode: normalizeQueueMode(queueMode),\n ...rest,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load queue WGSL source.\");\n }\n assertNotHtmlWgsl(source, rest?.url ? String(rest.url) : \"queue WGSL\");\n if (!queueCompat) {\n return source;\n }\n const compatMap = getQueueCompatMap(source);\n return applyCompatMap(source, compatMap);\n}\n\nfunction ensureQueueLifecycleHooks(source) {\n if (/\\bfn\\s+complete_job\\b/.test(source)) {\n return source;\n }\n return `${source}\\n\\nfn complete_job(job_index: u32) {\\n _ = job_index;\\n}`;\n}\n\nexport async function loadJobWgsl(options = {}) {\n const { wgsl, url, fetcher, label } = options ?? {};\n const source = await loadWgslSource({\n wgsl,\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"loadJobWgsl requires a WGSL string or URL.\");\n }\n const jobType = nextJobType;\n nextJobType += 1;\n jobRegistry.push({\n jobType,\n wgsl: source,\n label: label ?? `job_${jobType}`,\n sourceName: label ?? `job-${jobType}`,\n });\n return jobType;\n}\n\nexport async function assembleWorkerWgsl(workerWgsl, options = {}) {\n const {\n queueWgsl,\n queueUrl,\n preludeWgsl,\n preludeUrl,\n fetcher,\n jobs,\n debug,\n queueCompat = true,\n queueMode = \"flat\",\n } = options ?? {};\n const resolvedQueueMode = normalizeQueueMode(queueMode);\n const rawQueueSource =\n queueWgsl ??\n (await loadSchedulerWgslRaw({\n mode: resolvedQueueMode,\n url: queueUrl,\n fetcher,\n }));\n const bodyRaw = workerWgsl ?? (await loadWorkerWgsl({ fetcher }));\n const compatMap = queueCompat ? getQueueCompatMap(rawQueueSource) : null;\n const queueSource = ensureQueueLifecycleHooks(\n applyCompatMap(rawQueueSource, compatMap)\n );\n const preludeRaw =\n preludeWgsl ??\n (preludeUrl\n ? await loadWgslSource({ url: preludeUrl, fetcher, baseUrl: workerWgslUrl })\n : \"\");\n if ((preludeWgsl || preludeUrl) && typeof preludeRaw !== \"string\") {\n throw new Error(\"Failed to load prelude WGSL source.\");\n }\n const preludeSource =\n typeof preludeRaw === \"string\" && preludeRaw.length > 0\n ? applyCompatMap(preludeRaw, compatMap)\n : \"\";\n const body = applyCompatMap(bodyRaw, compatMap);\n const jobList = normalizeJobs(\n typeof jobs === \"undefined\" ? jobRegistry : jobs\n );\n if (!jobList || jobList.length === 0) {\n return `${queueSource}\\n\\n${body}`;\n }\n const rewrittenJobs = jobList.map((job) => {\n const source = applyCompatMap(job.wgsl, compatMap);\n const hasProcessJob = /\\bfn\\s+process_job\\b/.test(source);\n if (!hasProcessJob) {\n throw new Error(\n `Job ${job.sourceName} is missing a process_job() entry function.`\n );\n }\n const entryName = `process_job__${job.jobType}`;\n const renamed = renameProcessJob(source, entryName);\n return { ...job, entryName, wgsl: renamed };\n });\n const dispatch = buildProcessJobDispatch(rewrittenJobs);\n const modulesForDebug = debug\n ? [\n { name: \"queue.wgsl\", source: queueSource },\n ...(preludeSource\n ? [{ name: \"jobs.prelude.wgsl\", source: preludeSource }]\n : []),\n ...rewrittenJobs.map((job) => ({\n name: job.sourceName,\n source: job.wgsl,\n })),\n { name: \"jobs.dispatch.wgsl\", source: dispatch },\n { name: \"worker.wgsl\", source: body },\n ]\n : null;\n if (modulesForDebug) {\n assertNoNameClashes(modulesForDebug);\n }\n const jobBlocks = rewrittenJobs\n .map((job) => `// Job ${job.jobType}: ${job.label}\\n${job.wgsl}`)\n .join(\"\\n\\n\");\n const preludeBlock = preludeSource ? `${preludeSource}\\n\\n` : \"\";\n return `${queueSource}\\n\\n${preludeBlock}${jobBlocks}\\n\\n${dispatch}\\n\\n${body}`;\n}\n\nfunction normalizeWorkgroups(value, label) {\n if (typeof value === \"number\") {\n return [value, 1, 1];\n }\n if (Array.isArray(value)) {\n const [x = 0, y = 1, z = 1] = value;\n return [x, y, z];\n }\n throw new Error(`Invalid workgroup count for ${label}.`);\n}\n\nfunction resolveWorkgroups(value, label) {\n if (typeof value === \"function\") {\n return normalizeWorkgroups(value(), label);\n }\n if (value == null) {\n return null;\n }\n return normalizeWorkgroups(value, label);\n}\n\nfunction normalizeTelemetryText(value, fallback) {\n if (typeof value !== \"string\") {\n return fallback;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : fallback;\n}\n\nfunction resolveFrameId(value) {\n if (typeof value === \"function\") {\n return resolveFrameId(value());\n }\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : undefined;\n}\n\nfunction toVector(workgroups) {\n return { x: workgroups[0], y: workgroups[1], z: workgroups[2] };\n}\n\nfunction resolveTelemetryWorkgroupSize(descriptor, fallback, label) {\n const size =\n descriptor?.workgroupSize == null ? fallback : descriptor.workgroupSize;\n if (size == null) {\n return undefined;\n }\n const normalized =\n typeof size === \"number\" ? normalizeWorkgroups(size, label) : resolveWorkgroups(size, label);\n if (!normalized) {\n return undefined;\n }\n return toVector(normalized);\n}\n\nfunction getNow() {\n if (globalThis.performance && typeof globalThis.performance.now === \"function\") {\n return globalThis.performance.now();\n }\n return Date.now();\n}\n\nfunction reportOptionalError(error, onError) {\n if (!onError) {\n return;\n }\n if (error instanceof Error) {\n onError(error);\n return;\n }\n onError(new Error(String(error)));\n}\n\nfunction emitOptionalHook(callback, payload, onError) {\n if (typeof callback !== \"function\") {\n return;\n }\n try {\n callback(payload);\n } catch (error) {\n reportOptionalError(error, onError);\n }\n}\n\nfunction buildDispatchTelemetrySample({\n kind,\n descriptor,\n index,\n frameId,\n workgroups,\n workgroupSize,\n}) {\n const labelFallback = kind === \"worker\" ? \"worker\" : `job_${index}`;\n const label = normalizeTelemetryText(descriptor?.label, labelFallback);\n return {\n kind,\n index,\n label,\n owner: normalizeTelemetryText(descriptor?.owner, label),\n queueClass: normalizeTelemetryText(descriptor?.queueClass, \"custom\"),\n jobType: normalizeTelemetryText(\n descriptor?.jobType,\n kind === \"worker\" ? \"worker.dispatch\" : label\n ),\n frameId,\n workgroups: toVector(workgroups),\n workgroupSize,\n };\n}\n\nfunction setBindGroups(pass, bindGroups) {\n if (!bindGroups) {\n return;\n }\n bindGroups.forEach((group, index) => {\n if (group) {\n pass.setBindGroup(index, group);\n }\n });\n}\n\nfunction computeWorkerWorkgroups(maxJobs, workgroupSize) {\n const jobs =\n typeof maxJobs === \"function\" ? Number(maxJobs()) : Number(maxJobs);\n if (!Number.isFinite(jobs) || jobs <= 0) {\n throw new Error(\"maxJobsPerDispatch must be a positive number.\");\n }\n const size = Number(workgroupSize);\n if (!Number.isFinite(size) || size <= 0) {\n throw new Error(\"workgroupSize must be a positive number.\");\n }\n return Math.max(1, Math.ceil(jobs / size));\n}\n\nexport function createWorkerLoop(options = {}) {\n const {\n device,\n worker,\n jobs = [],\n workgroupSize = 64,\n maxJobsPerDispatch,\n rateHz,\n label,\n onTick,\n onError,\n frameId,\n telemetry,\n } = options ?? {};\n\n if (!device) {\n throw new Error(\"createWorkerLoop requires a GPUDevice.\");\n }\n if (!worker || !worker.pipeline) {\n throw new Error(\"createWorkerLoop requires a worker pipeline.\");\n }\n\n let running = false;\n let handle = null;\n let usingRaf = false;\n const intervalMs =\n Number.isFinite(rateHz) && rateHz > 0 ? 1000 / rateHz : null;\n\n const tick = () => {\n try {\n const tickStartMs = getNow();\n const currentFrameId = resolveFrameId(frameId);\n const telemetryDispatches = [];\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass(\n label ? { label } : undefined\n );\n\n pass.setPipeline(worker.pipeline);\n setBindGroups(pass, worker.bindGroups);\n\n const explicitWorkerGroups =\n resolveWorkgroups(worker.workgroups, \"worker\") ??\n resolveWorkgroups(worker.workgroupCount, \"worker\") ??\n resolveWorkgroups(worker.dispatch, \"worker\");\n\n const workerGroups = explicitWorkerGroups\n ? explicitWorkerGroups\n : [computeWorkerWorkgroups(maxJobsPerDispatch, workgroupSize), 1, 1];\n\n if (workerGroups[0] > 0) {\n pass.dispatchWorkgroups(...workerGroups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"worker\",\n descriptor: worker,\n index: 0,\n frameId: currentFrameId,\n workgroups: workerGroups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n worker,\n workgroupSize,\n \"worker workgroupSize\"\n ),\n })\n );\n }\n\n jobs.forEach((job, index) => {\n if (!job || !job.pipeline) {\n throw new Error(`Job pipeline missing at index ${index}.`);\n }\n pass.setPipeline(job.pipeline);\n setBindGroups(pass, job.bindGroups);\n const groups = resolveWorkgroups(\n job.workgroups ?? job.workgroupCount ?? job.dispatch,\n `job ${index}`\n );\n if (!groups) {\n throw new Error(`Job ${index} requires a workgroup count.`);\n }\n if (groups[0] > 0) {\n pass.dispatchWorkgroups(...groups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"job\",\n descriptor: job,\n index,\n frameId: currentFrameId,\n workgroups: groups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n job,\n undefined,\n `job ${index} workgroupSize`\n ),\n })\n );\n }\n });\n\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n telemetryDispatches.forEach((sample) => {\n emitOptionalHook(telemetry?.onDispatch, sample, onError);\n });\n emitOptionalHook(\n telemetry?.onTick,\n {\n frameId: currentFrameId,\n tickDurationMs: getNow() - tickStartMs,\n dispatchCount: telemetryDispatches.length,\n workerDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"worker\"\n ).length,\n jobDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"job\"\n ).length,\n dispatches: telemetryDispatches,\n },\n onError\n );\n\n if (onTick) {\n onTick();\n }\n } catch (err) {\n if (onError) {\n onError(err);\n return;\n }\n throw err;\n }\n };\n\n const scheduleNext = () => {\n if (!running) {\n return;\n }\n if (intervalMs != null) {\n tick();\n usingRaf = false;\n handle = setTimeout(scheduleNext, intervalMs);\n return;\n }\n tick();\n if (typeof requestAnimationFrame === \"function\") {\n usingRaf = true;\n handle = requestAnimationFrame(scheduleNext);\n } else {\n usingRaf = false;\n handle = setTimeout(scheduleNext, 0);\n }\n };\n\n const start = () => {\n if (running) {\n return;\n }\n running = true;\n scheduleNext();\n };\n\n const stop = () => {\n running = false;\n if (handle == null) {\n return;\n }\n if (usingRaf && typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(handle);\n } else {\n clearTimeout(handle);\n }\n handle = null;\n };\n\n return {\n start,\n stop,\n tick,\n get running() {\n return running;\n },\n };\n}\n"],"mappings":"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","names":["source","module","workerSchedulerModes","loadSchedulerWgslRaw"]}
{"version":3,"sources":["../src/index.js"],"sourcesContent":["import {\n loadSchedulerWgsl as loadSchedulerWgslRaw,\n schedulerModes as workerSchedulerModes,\n} from \"@plasius/gpu-lock-free-queue\";\n\nexport const workerWgslUrl = (() => {\n if (typeof __IMPORT_META_URL__ !== \"undefined\") {\n return new URL(\"./worker.wgsl\", __IMPORT_META_URL__);\n }\n if (typeof __filename !== \"undefined\" && typeof require !== \"undefined\") {\n const { pathToFileURL } = require(\"node:url\");\n return new URL(\"./worker.wgsl\", pathToFileURL(__filename));\n }\n const base =\n typeof process !== \"undefined\" && process.cwd\n ? `file://${process.cwd()}/`\n : \"file:///\";\n return new URL(\"./worker.wgsl\", base);\n})();\n\nconst jobRegistry = [];\nlet nextJobType = 0;\n\nasync function loadWgslSource(options = {}) {\n const { wgsl, url, fetcher = globalThis.fetch, baseUrl } = options ?? {};\n if (typeof wgsl === \"string\") {\n assertNotHtmlWgsl(wgsl, \"inline WGSL\");\n return wgsl;\n }\n if (!url) {\n return null;\n }\n const resolved = url instanceof URL ? url : new URL(url, baseUrl);\n if (!fetcher) {\n if (resolved.protocol !== \"file:\") {\n throw new Error(\"No fetcher available for non-file WGSL URL.\");\n }\n const { readFile } = await import(\"fs/promises\");\n const { fileURLToPath } = await import(\"url\");\n const source = await readFile(fileURLToPath(resolved), \"utf8\");\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n }\n const response = await fetcher(resolved);\n if (!response.ok) {\n const status = \"status\" in response ? response.status : \"unknown\";\n const statusText = \"statusText\" in response ? response.statusText : \"\";\n const detail = statusText ? `${status} ${statusText}` : `${status}`;\n throw new Error(`Failed to load WGSL (${detail})`);\n }\n const source = await response.text();\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n}\n\nfunction stripComments(source) {\n return source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/\\/\\/.*$/gm, \"\");\n}\n\nfunction tokenize(source) {\n return source.match(/[A-Za-z_][A-Za-z0-9_]*|[{}();<>,:=]/g) ?? [];\n}\n\nfunction isIdentifier(token) {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(token);\n}\n\nfunction readNameAfterType(tokens, startIndex) {\n let i = startIndex;\n if (tokens[i] === \"<\") {\n let depth = 1;\n i += 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i] === \"<\") {\n depth += 1;\n } else if (tokens[i] === \">\") {\n depth -= 1;\n }\n i += 1;\n }\n }\n return tokens[i];\n}\n\nfunction scanModuleNames(source) {\n const cleaned = stripComments(source);\n const tokens = tokenize(cleaned);\n const names = [];\n let depth = 0;\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i];\n if (token === \"{\") {\n depth += 1;\n continue;\n }\n if (token === \"}\") {\n depth = Math.max(0, depth - 1);\n continue;\n }\n if (depth !== 0) {\n continue;\n }\n if (token === \"fn\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"fn\", name });\n }\n continue;\n }\n if (token === \"struct\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"struct\", name });\n }\n continue;\n }\n if (token === \"alias\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"alias\", name });\n }\n continue;\n }\n if (token === \"var\" || token === \"let\" || token === \"const\" || token === \"override\") {\n const name = readNameAfterType(tokens, i + 1);\n if (isIdentifier(name)) {\n names.push({ kind: token, name });\n }\n }\n }\n return names;\n}\n\nfunction buildNameIndex(modules) {\n const index = new Map();\n for (const module of modules) {\n for (const item of scanModuleNames(module.source)) {\n const bucket = index.get(item.name) ?? [];\n bucket.push({ kind: item.kind, module: module.name });\n index.set(item.name, bucket);\n }\n }\n return index;\n}\n\nfunction assertNoNameClashes(modules) {\n const index = buildNameIndex(modules);\n const clashes = [];\n for (const [name, entries] of index.entries()) {\n if (entries.length > 1) {\n clashes.push({ name, entries });\n }\n }\n if (clashes.length === 0) {\n return;\n }\n const lines = [\"WGSL debug: identifier clashes detected:\"];\n for (const clash of clashes) {\n const locations = clash.entries\n .map((entry) => `${entry.module} (${entry.kind})`)\n .join(\", \");\n lines.push(`- ${clash.name}: ${locations}`);\n }\n throw new Error(lines.join(\"\\n\"));\n}\n\nfunction assertNotHtmlWgsl(source, context) {\n const sample = source.slice(0, 200).toLowerCase();\n if (\n sample.includes(\"<!doctype\") ||\n sample.includes(\"<html\") ||\n sample.includes(\"<meta\")\n ) {\n const label = context ? ` for ${context}` : \"\";\n throw new Error(\n `Expected WGSL${label} but received HTML. Check the URL or server root.`\n );\n }\n}\n\nfunction renameProcessJob(source, name) {\n return source.replace(/\\bprocess_job\\b/g, name);\n}\n\nfunction getQueueCompatMap(source) {\n if (!/\\bJobMeta\\b/.test(source)) {\n return null;\n }\n return [{ from: /\\bJobMeta\\b/g, to: \"JobDesc\" }];\n}\n\nfunction normalizeQueueMode(mode) {\n const resolved = mode ?? \"flat\";\n if (!workerSchedulerModes.includes(resolved)) {\n throw new Error(\n `queueMode must be one of: ${workerSchedulerModes.join(\", \")}.`\n );\n }\n return resolved;\n}\n\nfunction applyCompatMap(source, map) {\n if (!map || map.length === 0) {\n return source;\n }\n let next = source;\n for (const entry of map) {\n next = next.replace(entry.from, entry.to);\n }\n return next;\n}\n\nfunction normalizeJobs(jobs) {\n const normalized = jobs.map((job, index) => {\n if (typeof job === \"string\") {\n return {\n jobType: index,\n wgsl: job,\n label: `job_${index}`,\n sourceName: `job-${index}`,\n };\n }\n if (!job || typeof job.wgsl !== \"string\") {\n throw new Error(\"Job entries must provide WGSL source strings.\");\n }\n const jobType = job.jobType ?? index;\n const label = job.label ?? `job_${jobType}`;\n return {\n jobType,\n wgsl: job.wgsl,\n label,\n sourceName: job.sourceName ?? job.label ?? `job-${jobType}`,\n };\n });\n const seen = new Set();\n for (const job of normalized) {\n if (seen.has(job.jobType)) {\n throw new Error(`Duplicate job_type detected: ${job.jobType}`);\n }\n seen.add(job.jobType);\n }\n return normalized;\n}\n\nfunction buildProcessJobDispatch(jobs) {\n const lines = [\n \"fn process_job(job_index: u32, job_type: u32, payload_words: u32) {\",\n ];\n if (jobs.length === 0) {\n lines.push(\" return;\");\n lines.push(\"}\");\n return lines.join(\"\\n\");\n }\n jobs.forEach((job, idx) => {\n const clause = idx === 0 ? \"if\" : \"else if\";\n lines.push(` ${clause} (job_type == ${job.jobType}u) {`);\n lines.push(\n ` ${job.entryName}(job_index, job_type, payload_words);`\n );\n lines.push(\" }\");\n });\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nexport async function loadWorkerWgsl(options = {}) {\n const { url = workerWgslUrl, fetcher } = options ?? {};\n const source = await loadWgslSource({\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load worker WGSL source.\");\n }\n return source;\n}\n\nexport async function loadQueueWgsl(options = {}) {\n const { queueCompat = true, queueMode = \"flat\", ...rest } = options ?? {};\n const source = await loadSchedulerWgslRaw({\n mode: normalizeQueueMode(queueMode),\n ...rest,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load queue WGSL source.\");\n }\n assertNotHtmlWgsl(source, rest?.url ? String(rest.url) : \"queue WGSL\");\n if (!queueCompat) {\n return source;\n }\n const compatMap = getQueueCompatMap(source);\n return applyCompatMap(source, compatMap);\n}\n\nfunction ensureQueueLifecycleHooks(source) {\n if (/\\bfn\\s+complete_job\\b/.test(source)) {\n return source;\n }\n return `${source}\\n\\nfn complete_job(job_index: u32) {\\n _ = job_index;\\n}`;\n}\n\nexport async function loadJobWgsl(options = {}) {\n const { wgsl, url, fetcher, label } = options ?? {};\n const source = await loadWgslSource({\n wgsl,\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"loadJobWgsl requires a WGSL string or URL.\");\n }\n const jobType = nextJobType;\n nextJobType += 1;\n jobRegistry.push({\n jobType,\n wgsl: source,\n label: label ?? `job_${jobType}`,\n sourceName: label ?? `job-${jobType}`,\n });\n return jobType;\n}\n\nexport async function assembleWorkerWgsl(workerWgsl, options = {}) {\n const {\n queueWgsl,\n queueUrl,\n preludeWgsl,\n preludeUrl,\n fetcher,\n jobs,\n debug,\n queueCompat = true,\n queueMode = \"flat\",\n } = options ?? {};\n const resolvedQueueMode = normalizeQueueMode(queueMode);\n const rawQueueSource =\n queueWgsl ??\n (await loadSchedulerWgslRaw({\n mode: resolvedQueueMode,\n url: queueUrl,\n fetcher,\n }));\n const bodyRaw = workerWgsl ?? (await loadWorkerWgsl({ fetcher }));\n const compatMap = queueCompat ? getQueueCompatMap(rawQueueSource) : null;\n const queueSource = ensureQueueLifecycleHooks(\n applyCompatMap(rawQueueSource, compatMap)\n );\n const preludeRaw =\n preludeWgsl ??\n (preludeUrl\n ? await loadWgslSource({ url: preludeUrl, fetcher, baseUrl: workerWgslUrl })\n : \"\");\n if ((preludeWgsl || preludeUrl) && typeof preludeRaw !== \"string\") {\n throw new Error(\"Failed to load prelude WGSL source.\");\n }\n const preludeSource =\n typeof preludeRaw === \"string\" && preludeRaw.length > 0\n ? applyCompatMap(preludeRaw, compatMap)\n : \"\";\n const body = applyCompatMap(bodyRaw, compatMap);\n const jobList = normalizeJobs(\n typeof jobs === \"undefined\" ? jobRegistry : jobs\n );\n if (!jobList || jobList.length === 0) {\n return `${queueSource}\\n\\n${body}`;\n }\n const rewrittenJobs = jobList.map((job) => {\n const source = applyCompatMap(job.wgsl, compatMap);\n const hasProcessJob = /\\bfn\\s+process_job\\b/.test(source);\n if (!hasProcessJob) {\n throw new Error(\n `Job ${job.sourceName} is missing a process_job() entry function.`\n );\n }\n const entryName = `process_job__${job.jobType}`;\n const renamed = renameProcessJob(source, entryName);\n return { ...job, entryName, wgsl: renamed };\n });\n const dispatch = buildProcessJobDispatch(rewrittenJobs);\n const modulesForDebug = debug\n ? [\n { name: \"queue.wgsl\", source: queueSource },\n ...(preludeSource\n ? [{ name: \"jobs.prelude.wgsl\", source: preludeSource }]\n : []),\n ...rewrittenJobs.map((job) => ({\n name: job.sourceName,\n source: job.wgsl,\n })),\n { name: \"jobs.dispatch.wgsl\", source: dispatch },\n { name: \"worker.wgsl\", source: body },\n ]\n : null;\n if (modulesForDebug) {\n assertNoNameClashes(modulesForDebug);\n }\n const jobBlocks = rewrittenJobs\n .map((job) => `// Job ${job.jobType}: ${job.label}\\n${job.wgsl}`)\n .join(\"\\n\\n\");\n const preludeBlock = preludeSource ? `${preludeSource}\\n\\n` : \"\";\n return `${queueSource}\\n\\n${preludeBlock}${jobBlocks}\\n\\n${dispatch}\\n\\n${body}`;\n}\n\nfunction normalizeWorkgroups(value, label) {\n if (typeof value === \"number\") {\n return [value, 1, 1];\n }\n if (Array.isArray(value)) {\n const [x = 0, y = 1, z = 1] = value;\n return [x, y, z];\n }\n throw new Error(`Invalid workgroup count for ${label}.`);\n}\n\nfunction resolveWorkgroups(value, label) {\n if (typeof value === \"function\") {\n return normalizeWorkgroups(value(), label);\n }\n if (value == null) {\n return null;\n }\n return normalizeWorkgroups(value, label);\n}\n\nfunction normalizeTelemetryText(value, fallback) {\n if (typeof value !== \"string\") {\n return fallback;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : fallback;\n}\n\nfunction resolveFrameId(value) {\n if (typeof value === \"function\") {\n return resolveFrameId(value());\n }\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : undefined;\n}\n\nfunction toVector(workgroups) {\n return { x: workgroups[0], y: workgroups[1], z: workgroups[2] };\n}\n\nfunction resolveTelemetryWorkgroupSize(descriptor, fallback, label) {\n const size =\n descriptor?.workgroupSize == null ? fallback : descriptor.workgroupSize;\n if (size == null) {\n return undefined;\n }\n const normalized =\n typeof size === \"number\" ? normalizeWorkgroups(size, label) : resolveWorkgroups(size, label);\n if (!normalized) {\n return undefined;\n }\n return toVector(normalized);\n}\n\nfunction getNow() {\n if (globalThis.performance && typeof globalThis.performance.now === \"function\") {\n return globalThis.performance.now();\n }\n return Date.now();\n}\n\nfunction reportOptionalError(error, onError) {\n if (!onError) {\n return;\n }\n if (error instanceof Error) {\n onError(error);\n return;\n }\n onError(new Error(String(error)));\n}\n\nfunction emitOptionalHook(callback, payload, onError) {\n if (typeof callback !== \"function\") {\n return;\n }\n try {\n callback(payload);\n } catch (error) {\n reportOptionalError(error, onError);\n }\n}\n\nfunction buildDispatchTelemetrySample({\n kind,\n descriptor,\n index,\n frameId,\n workgroups,\n workgroupSize,\n}) {\n const labelFallback = kind === \"worker\" ? \"worker\" : `job_${index}`;\n const label = normalizeTelemetryText(descriptor?.label, labelFallback);\n return {\n kind,\n index,\n label,\n owner: normalizeTelemetryText(descriptor?.owner, label),\n queueClass: normalizeTelemetryText(descriptor?.queueClass, \"custom\"),\n jobType: normalizeTelemetryText(\n descriptor?.jobType,\n kind === \"worker\" ? \"worker.dispatch\" : label\n ),\n frameId,\n workgroups: toVector(workgroups),\n workgroupSize,\n };\n}\n\nfunction setBindGroups(pass, bindGroups) {\n if (!bindGroups) {\n return;\n }\n bindGroups.forEach((group, index) => {\n if (group) {\n pass.setBindGroup(index, group);\n }\n });\n}\n\nfunction computeWorkerWorkgroups(maxJobs, workgroupSize) {\n const jobs =\n typeof maxJobs === \"function\" ? Number(maxJobs()) : Number(maxJobs);\n if (!Number.isFinite(jobs) || jobs <= 0) {\n throw new Error(\"maxJobsPerDispatch must be a positive number.\");\n }\n const size = Number(workgroupSize);\n if (!Number.isFinite(size) || size <= 0) {\n throw new Error(\"workgroupSize must be a positive number.\");\n }\n return Math.max(1, Math.ceil(jobs / size));\n}\n\nexport function createWorkerLoop(options = {}) {\n const {\n device,\n worker,\n jobs = [],\n workgroupSize = 64,\n maxJobsPerDispatch,\n rateHz,\n label,\n onTick,\n onError,\n frameId,\n telemetry,\n } = options ?? {};\n\n if (!device) {\n throw new Error(\"createWorkerLoop requires a GPUDevice.\");\n }\n if (!worker || !worker.pipeline) {\n throw new Error(\"createWorkerLoop requires a worker pipeline.\");\n }\n\n let running = false;\n let handle = null;\n let usingRaf = false;\n const intervalMs =\n Number.isFinite(rateHz) && rateHz > 0 ? 1000 / rateHz : null;\n\n const tick = () => {\n try {\n const tickStartMs = getNow();\n const currentFrameId = resolveFrameId(frameId);\n const telemetryDispatches = [];\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass(\n label ? { label } : undefined\n );\n\n pass.setPipeline(worker.pipeline);\n setBindGroups(pass, worker.bindGroups);\n\n const explicitWorkerGroups =\n resolveWorkgroups(worker.workgroups, \"worker\") ??\n resolveWorkgroups(worker.workgroupCount, \"worker\") ??\n resolveWorkgroups(worker.dispatch, \"worker\");\n\n const workerGroups = explicitWorkerGroups\n ? explicitWorkerGroups\n : [computeWorkerWorkgroups(maxJobsPerDispatch, workgroupSize), 1, 1];\n\n if (workerGroups[0] > 0) {\n pass.dispatchWorkgroups(...workerGroups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"worker\",\n descriptor: worker,\n index: 0,\n frameId: currentFrameId,\n workgroups: workerGroups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n worker,\n workgroupSize,\n \"worker workgroupSize\"\n ),\n })\n );\n }\n\n jobs.forEach((job, index) => {\n if (!job || !job.pipeline) {\n throw new Error(`Job pipeline missing at index ${index}.`);\n }\n pass.setPipeline(job.pipeline);\n setBindGroups(pass, job.bindGroups);\n const groups = resolveWorkgroups(\n job.workgroups ?? job.workgroupCount ?? job.dispatch,\n `job ${index}`\n );\n if (!groups) {\n throw new Error(`Job ${index} requires a workgroup count.`);\n }\n if (groups[0] > 0) {\n pass.dispatchWorkgroups(...groups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"job\",\n descriptor: job,\n index,\n frameId: currentFrameId,\n workgroups: groups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n job,\n undefined,\n `job ${index} workgroupSize`\n ),\n })\n );\n }\n });\n\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n telemetryDispatches.forEach((sample) => {\n emitOptionalHook(telemetry?.onDispatch, sample, onError);\n });\n emitOptionalHook(\n telemetry?.onTick,\n {\n frameId: currentFrameId,\n tickDurationMs: getNow() - tickStartMs,\n dispatchCount: telemetryDispatches.length,\n workerDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"worker\"\n ).length,\n jobDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"job\"\n ).length,\n dispatches: telemetryDispatches,\n },\n onError\n );\n\n if (onTick) {\n onTick();\n }\n } catch (err) {\n if (onError) {\n onError(err);\n return;\n }\n throw err;\n }\n };\n\n const scheduleNext = () => {\n if (!running) {\n return;\n }\n if (intervalMs != null) {\n tick();\n usingRaf = false;\n handle = setTimeout(scheduleNext, intervalMs);\n return;\n }\n tick();\n if (typeof requestAnimationFrame === \"function\") {\n usingRaf = true;\n handle = requestAnimationFrame(scheduleNext);\n } else {\n usingRaf = false;\n handle = setTimeout(scheduleNext, 0);\n }\n };\n\n const start = () => {\n if (running) {\n return;\n }\n running = true;\n scheduleNext();\n };\n\n const stop = () => {\n running = false;\n if (handle == null) {\n return;\n }\n if (usingRaf && typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(handle);\n } else {\n clearTimeout(handle);\n }\n handle = null;\n };\n\n return {\n start,\n stop,\n tick,\n get running() {\n return running;\n },\n };\n}\n\nexport const scenePreparationRepresentationBands = Object.freeze([\n \"near\",\n \"mid\",\n \"far\",\n \"horizon\",\n]);\n\nexport const scenePreparationStageFamilies = Object.freeze([\n \"snapshotSelection\",\n \"transformPropagation\",\n \"animationPose\",\n \"proceduralAnimation\",\n \"skinningOrDeformation\",\n \"boundsUpdate\",\n \"lodSelection\",\n \"rtRepresentationSelection\",\n \"visibility\",\n \"lightAssignment\",\n \"renderProxyBuild\",\n \"rtInstancePreparation\",\n]);\n\nconst scenePreparationDefaultStageDependencies = Object.freeze({\n snapshotSelection: Object.freeze([]),\n transformPropagation: Object.freeze([\"snapshotSelection\"]),\n animationPose: Object.freeze([\"transformPropagation\"]),\n proceduralAnimation: Object.freeze([\"animationPose\"]),\n skinningOrDeformation: Object.freeze([\n \"animationPose\",\n \"proceduralAnimation\",\n ]),\n boundsUpdate: Object.freeze([\"skinningOrDeformation\"]),\n lodSelection: Object.freeze([\"boundsUpdate\"]),\n rtRepresentationSelection: Object.freeze([\"lodSelection\"]),\n visibility: Object.freeze([\"boundsUpdate\", \"lodSelection\"]),\n lightAssignment: Object.freeze([\"visibility\"]),\n renderProxyBuild: Object.freeze([\"visibility\", \"lodSelection\"]),\n rtInstancePreparation: Object.freeze([\n \"visibility\",\n \"rtRepresentationSelection\",\n ]),\n});\n\nconst scenePreparationBandPriorityWeights = Object.freeze({\n near: 400,\n mid: 300,\n far: 200,\n horizon: 100,\n});\n\nconst scenePreparationImportanceWeights = Object.freeze({\n low: 0,\n medium: 15,\n high: 30,\n critical: 60,\n});\n\nconst scenePreparationStagePriorityWeights = Object.freeze({\n snapshotSelection: 60,\n transformPropagation: 54,\n animationPose: 50,\n proceduralAnimation: 46,\n skinningOrDeformation: 42,\n boundsUpdate: 38,\n lodSelection: 32,\n rtRepresentationSelection: 28,\n visibility: 34,\n lightAssignment: 24,\n renderProxyBuild: 22,\n rtInstancePreparation: 26,\n});\n\nfunction assertScenePreparationIdentifier(name, value) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new Error(`${name} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction assertScenePreparationEnum(name, value, allowed) {\n const normalized = assertScenePreparationIdentifier(name, value);\n if (!allowed.includes(normalized)) {\n throw new Error(`${name} must be one of: ${allowed.join(\", \")}.`);\n }\n return normalized;\n}\n\nfunction normalizeScenePreparationStages(stages, chunkLabel) {\n const requested =\n stages === undefined ? scenePreparationStageFamilies : stages;\n if (!Array.isArray(requested) || requested.length === 0) {\n throw new Error(`${chunkLabel}.stages must be a non-empty array when provided.`);\n }\n\n const normalized = [...new Set(\n requested.map((stage, index) =>\n assertScenePreparationEnum(\n `${chunkLabel}.stages[${index}]`,\n stage,\n scenePreparationStageFamilies\n )\n )\n )];\n\n return normalized.sort(\n (left, right) =>\n scenePreparationStageFamilies.indexOf(left) -\n scenePreparationStageFamilies.indexOf(right)\n );\n}\n\nfunction collectScenePreparationDependencies(\n stageFamily,\n includedStages,\n seen = new Set()\n) {\n const dependencies =\n scenePreparationDefaultStageDependencies[stageFamily] ?? [];\n for (const dependency of dependencies) {\n if (includedStages.has(dependency)) {\n seen.add(dependency);\n continue;\n }\n collectScenePreparationDependencies(dependency, includedStages, seen);\n }\n return [...seen].sort(\n (left, right) =>\n scenePreparationStageFamilies.indexOf(left) -\n scenePreparationStageFamilies.indexOf(right)\n );\n}\n\nfunction buildScenePreparationPriority(chunk, stageFamily) {\n const bandWeight =\n scenePreparationBandPriorityWeights[chunk.representationBand] ?? 0;\n const importanceWeight =\n scenePreparationImportanceWeights[chunk.gameplayImportance] ?? 0;\n const stageWeight =\n scenePreparationStagePriorityWeights[stageFamily] ?? 0;\n\n return (\n bandWeight +\n importanceWeight +\n stageWeight +\n (chunk.visible ? 20 : 0) +\n (chunk.playerRelevant ? 20 : 0) +\n (chunk.imageCritical ? 15 : 0)\n );\n}\n\nfunction buildScenePreparationPriorityLanes(jobs) {\n const lanes = new Map();\n for (const job of jobs) {\n const lane = lanes.get(job.priority) ?? {\n priority: job.priority,\n jobIds: [],\n chunkIds: [],\n };\n lane.jobIds.push(job.id);\n if (!lane.chunkIds.includes(job.chunkId)) {\n lane.chunkIds.push(job.chunkId);\n }\n lanes.set(job.priority, lane);\n }\n\n return Object.freeze(\n [...lanes.values()]\n .sort((left, right) => right.priority - left.priority)\n .map((lane) =>\n Object.freeze({\n priority: lane.priority,\n jobIds: Object.freeze([...lane.jobIds]),\n chunkIds: Object.freeze([...lane.chunkIds]),\n jobCount: lane.jobIds.length,\n })\n )\n );\n}\n\nfunction buildScenePreparationTopologicalOrder(jobs) {\n const indegree = new Map(jobs.map((job) => [job.id, job.dependencies.length]));\n const dependentsById = new Map(jobs.map((job) => [job.id, []]));\n\n for (const job of jobs) {\n for (const dependency of job.dependencies) {\n dependentsById.get(dependency)?.push(job.id);\n }\n }\n\n const queue = jobs\n .filter((job) => job.dependencies.length === 0)\n .sort((left, right) => right.priority - left.priority)\n .map((job) => job.id);\n const jobById = new Map(jobs.map((job) => [job.id, job]));\n const order = [];\n\n while (queue.length > 0) {\n const currentId = queue.shift();\n if (!currentId) {\n continue;\n }\n order.push(currentId);\n const unlocked = [];\n for (const dependentId of dependentsById.get(currentId) ?? []) {\n const next = (indegree.get(dependentId) ?? 0) - 1;\n indegree.set(dependentId, next);\n if (next === 0) {\n unlocked.push(dependentId);\n }\n }\n unlocked\n .sort(\n (left, right) =>\n (jobById.get(right)?.priority ?? 0) -\n (jobById.get(left)?.priority ?? 0)\n )\n .forEach((jobId) => {\n queue.push(jobId);\n });\n }\n\n if (order.length !== jobs.length) {\n throw new Error(\"Scene-preparation manifest contains a cycle.\");\n }\n\n return Object.freeze(order);\n}\n\nexport function createScenePreparationManifest(options = {}) {\n const snapshotId = assertScenePreparationIdentifier(\n \"snapshotId\",\n options.snapshotId\n );\n const chunkEntries = Array.isArray(options.chunks) ? options.chunks : [];\n if (chunkEntries.length === 0) {\n throw new Error(\"createScenePreparationManifest requires at least one chunk.\");\n }\n\n const normalizedChunks = chunkEntries.map((chunk, index) => {\n if (!chunk || typeof chunk !== \"object\" || Array.isArray(chunk)) {\n throw new Error(`chunks[${index}] must be an object.`);\n }\n const chunkLabel = `chunks[${index}]`;\n if (chunk.mutatesSimulation === true) {\n throw new Error(\n `${chunkLabel}.mutatesSimulation cannot be true for render preparation.`\n );\n }\n\n return Object.freeze({\n chunkId: assertScenePreparationIdentifier(`${chunkLabel}.chunkId`, chunk.chunkId),\n representationBand: assertScenePreparationEnum(\n `${chunkLabel}.representationBand`,\n chunk.representationBand ?? \"mid\",\n scenePreparationRepresentationBands\n ),\n gameplayImportance: assertScenePreparationEnum(\n `${chunkLabel}.gameplayImportance`,\n chunk.gameplayImportance ?? \"medium\",\n Object.keys(scenePreparationImportanceWeights)\n ),\n visible: chunk.visible !== false,\n playerRelevant: chunk.playerRelevant === true,\n imageCritical: chunk.imageCritical === true,\n stages: normalizeScenePreparationStages(chunk.stages, chunkLabel),\n });\n });\n\n const chunkIds = new Set();\n for (const chunk of normalizedChunks) {\n if (chunkIds.has(chunk.chunkId)) {\n throw new Error(`Duplicate scene-preparation chunk id detected: ${chunk.chunkId}`);\n }\n chunkIds.add(chunk.chunkId);\n }\n\n const jobs = [];\n for (const chunk of normalizedChunks) {\n const includedStages = new Set(chunk.stages);\n for (const stageFamily of chunk.stages) {\n const dependencies = collectScenePreparationDependencies(\n stageFamily,\n includedStages\n ).map(\n (dependency) =>\n `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${dependency}`\n );\n\n jobs.push(\n Object.freeze({\n id: `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${stageFamily}`,\n snapshotId,\n chunkId: chunk.chunkId,\n representationBand: chunk.representationBand,\n stageFamily,\n priority: buildScenePreparationPriority(chunk, stageFamily),\n dependencies: Object.freeze(dependencies),\n dependencyCount: dependencies.length,\n root: dependencies.length === 0,\n authority: \"visual\",\n mutatesSimulation: false,\n gameplayImportance: chunk.gameplayImportance,\n visible: chunk.visible,\n playerRelevant: chunk.playerRelevant,\n imageCritical: chunk.imageCritical,\n })\n );\n }\n }\n\n const jobById = new Map(jobs.map((job) => [job.id, job]));\n let crossChunkDependencyCount = 0;\n let localJoinCount = 0;\n\n const finalizedJobs = Object.freeze(\n jobs.map((job) => {\n const dependents = jobs\n .filter((candidate) => candidate.dependencies.includes(job.id))\n .map((candidate) => candidate.id);\n const crossChunkDependencies = job.dependencies.filter((dependency) => {\n const parent = jobById.get(dependency);\n return parent && parent.chunkId !== job.chunkId;\n });\n crossChunkDependencyCount += crossChunkDependencies.length;\n if (\n job.dependencies.length > 1 &&\n crossChunkDependencies.length === 0\n ) {\n localJoinCount += 1;\n }\n\n return Object.freeze({\n ...job,\n dependents: Object.freeze(dependents),\n dependentCount: dependents.length,\n unresolvedDependencyCount: job.dependencies.length,\n localJoin:\n job.dependencies.length > 1 && crossChunkDependencies.length === 0,\n });\n })\n );\n\n const graph = Object.freeze({\n schedulerMode: \"dag\",\n jobCount: finalizedJobs.length,\n chunkCount: normalizedChunks.length,\n chunkIds: Object.freeze(normalizedChunks.map((chunk) => chunk.chunkId)),\n representationBands: Object.freeze(\n [...new Set(normalizedChunks.map((chunk) => chunk.representationBand))]\n ),\n roots: Object.freeze(\n finalizedJobs.filter((job) => job.root).map((job) => job.id)\n ),\n chunkRoots: Object.freeze(\n Object.fromEntries(\n normalizedChunks.map((chunk) => [\n chunk.chunkId,\n finalizedJobs\n .filter((job) => job.chunkId === chunk.chunkId && job.root)\n .map((job) => job.id),\n ])\n )\n ),\n topologicalOrder: buildScenePreparationTopologicalOrder(finalizedJobs),\n priorityLanes: buildScenePreparationPriorityLanes(finalizedJobs),\n localJoinCount,\n crossChunkDependencyCount,\n });\n\n return Object.freeze({\n schemaVersion: 1,\n owner: \"scene-preparation\",\n schedulerMode: \"dag\",\n snapshotId,\n jobs: finalizedJobs,\n graph,\n });\n}\n"],"mappings":"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","names":["source","module","workerSchedulerModes","loadSchedulerWgslRaw"]}

@@ -668,4 +668,313 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {

}
var scenePreparationRepresentationBands = Object.freeze([
"near",
"mid",
"far",
"horizon"
]);
var scenePreparationStageFamilies = Object.freeze([
"snapshotSelection",
"transformPropagation",
"animationPose",
"proceduralAnimation",
"skinningOrDeformation",
"boundsUpdate",
"lodSelection",
"rtRepresentationSelection",
"visibility",
"lightAssignment",
"renderProxyBuild",
"rtInstancePreparation"
]);
var scenePreparationDefaultStageDependencies = Object.freeze({
snapshotSelection: Object.freeze([]),
transformPropagation: Object.freeze(["snapshotSelection"]),
animationPose: Object.freeze(["transformPropagation"]),
proceduralAnimation: Object.freeze(["animationPose"]),
skinningOrDeformation: Object.freeze([
"animationPose",
"proceduralAnimation"
]),
boundsUpdate: Object.freeze(["skinningOrDeformation"]),
lodSelection: Object.freeze(["boundsUpdate"]),
rtRepresentationSelection: Object.freeze(["lodSelection"]),
visibility: Object.freeze(["boundsUpdate", "lodSelection"]),
lightAssignment: Object.freeze(["visibility"]),
renderProxyBuild: Object.freeze(["visibility", "lodSelection"]),
rtInstancePreparation: Object.freeze([
"visibility",
"rtRepresentationSelection"
])
});
var scenePreparationBandPriorityWeights = Object.freeze({
near: 400,
mid: 300,
far: 200,
horizon: 100
});
var scenePreparationImportanceWeights = Object.freeze({
low: 0,
medium: 15,
high: 30,
critical: 60
});
var scenePreparationStagePriorityWeights = Object.freeze({
snapshotSelection: 60,
transformPropagation: 54,
animationPose: 50,
proceduralAnimation: 46,
skinningOrDeformation: 42,
boundsUpdate: 38,
lodSelection: 32,
rtRepresentationSelection: 28,
visibility: 34,
lightAssignment: 24,
renderProxyBuild: 22,
rtInstancePreparation: 26
});
function assertScenePreparationIdentifier(name, value) {
if (typeof value !== "string" || value.trim().length === 0) {
throw new Error(`${name} must be a non-empty string.`);
}
return value.trim();
}
function assertScenePreparationEnum(name, value, allowed) {
const normalized = assertScenePreparationIdentifier(name, value);
if (!allowed.includes(normalized)) {
throw new Error(`${name} must be one of: ${allowed.join(", ")}.`);
}
return normalized;
}
function normalizeScenePreparationStages(stages, chunkLabel) {
const requested = stages === void 0 ? scenePreparationStageFamilies : stages;
if (!Array.isArray(requested) || requested.length === 0) {
throw new Error(`${chunkLabel}.stages must be a non-empty array when provided.`);
}
const normalized = [...new Set(
requested.map(
(stage, index) => assertScenePreparationEnum(
`${chunkLabel}.stages[${index}]`,
stage,
scenePreparationStageFamilies
)
)
)];
return normalized.sort(
(left, right) => scenePreparationStageFamilies.indexOf(left) - scenePreparationStageFamilies.indexOf(right)
);
}
function collectScenePreparationDependencies(stageFamily, includedStages, seen = /* @__PURE__ */ new Set()) {
const dependencies = scenePreparationDefaultStageDependencies[stageFamily] ?? [];
for (const dependency of dependencies) {
if (includedStages.has(dependency)) {
seen.add(dependency);
continue;
}
collectScenePreparationDependencies(dependency, includedStages, seen);
}
return [...seen].sort(
(left, right) => scenePreparationStageFamilies.indexOf(left) - scenePreparationStageFamilies.indexOf(right)
);
}
function buildScenePreparationPriority(chunk, stageFamily) {
const bandWeight = scenePreparationBandPriorityWeights[chunk.representationBand] ?? 0;
const importanceWeight = scenePreparationImportanceWeights[chunk.gameplayImportance] ?? 0;
const stageWeight = scenePreparationStagePriorityWeights[stageFamily] ?? 0;
return bandWeight + importanceWeight + stageWeight + (chunk.visible ? 20 : 0) + (chunk.playerRelevant ? 20 : 0) + (chunk.imageCritical ? 15 : 0);
}
function buildScenePreparationPriorityLanes(jobs) {
const lanes = /* @__PURE__ */ new Map();
for (const job of jobs) {
const lane = lanes.get(job.priority) ?? {
priority: job.priority,
jobIds: [],
chunkIds: []
};
lane.jobIds.push(job.id);
if (!lane.chunkIds.includes(job.chunkId)) {
lane.chunkIds.push(job.chunkId);
}
lanes.set(job.priority, lane);
}
return Object.freeze(
[...lanes.values()].sort((left, right) => right.priority - left.priority).map(
(lane) => Object.freeze({
priority: lane.priority,
jobIds: Object.freeze([...lane.jobIds]),
chunkIds: Object.freeze([...lane.chunkIds]),
jobCount: lane.jobIds.length
})
)
);
}
function buildScenePreparationTopologicalOrder(jobs) {
const indegree = new Map(jobs.map((job) => [job.id, job.dependencies.length]));
const dependentsById = new Map(jobs.map((job) => [job.id, []]));
for (const job of jobs) {
for (const dependency of job.dependencies) {
dependentsById.get(dependency)?.push(job.id);
}
}
const queue = jobs.filter((job) => job.dependencies.length === 0).sort((left, right) => right.priority - left.priority).map((job) => job.id);
const jobById = new Map(jobs.map((job) => [job.id, job]));
const order = [];
while (queue.length > 0) {
const currentId = queue.shift();
if (!currentId) {
continue;
}
order.push(currentId);
const unlocked = [];
for (const dependentId of dependentsById.get(currentId) ?? []) {
const next = (indegree.get(dependentId) ?? 0) - 1;
indegree.set(dependentId, next);
if (next === 0) {
unlocked.push(dependentId);
}
}
unlocked.sort(
(left, right) => (jobById.get(right)?.priority ?? 0) - (jobById.get(left)?.priority ?? 0)
).forEach((jobId) => {
queue.push(jobId);
});
}
if (order.length !== jobs.length) {
throw new Error("Scene-preparation manifest contains a cycle.");
}
return Object.freeze(order);
}
function createScenePreparationManifest(options = {}) {
const snapshotId = assertScenePreparationIdentifier(
"snapshotId",
options.snapshotId
);
const chunkEntries = Array.isArray(options.chunks) ? options.chunks : [];
if (chunkEntries.length === 0) {
throw new Error("createScenePreparationManifest requires at least one chunk.");
}
const normalizedChunks = chunkEntries.map((chunk, index) => {
if (!chunk || typeof chunk !== "object" || Array.isArray(chunk)) {
throw new Error(`chunks[${index}] must be an object.`);
}
const chunkLabel = `chunks[${index}]`;
if (chunk.mutatesSimulation === true) {
throw new Error(
`${chunkLabel}.mutatesSimulation cannot be true for render preparation.`
);
}
return Object.freeze({
chunkId: assertScenePreparationIdentifier(`${chunkLabel}.chunkId`, chunk.chunkId),
representationBand: assertScenePreparationEnum(
`${chunkLabel}.representationBand`,
chunk.representationBand ?? "mid",
scenePreparationRepresentationBands
),
gameplayImportance: assertScenePreparationEnum(
`${chunkLabel}.gameplayImportance`,
chunk.gameplayImportance ?? "medium",
Object.keys(scenePreparationImportanceWeights)
),
visible: chunk.visible !== false,
playerRelevant: chunk.playerRelevant === true,
imageCritical: chunk.imageCritical === true,
stages: normalizeScenePreparationStages(chunk.stages, chunkLabel)
});
});
const chunkIds = /* @__PURE__ */ new Set();
for (const chunk of normalizedChunks) {
if (chunkIds.has(chunk.chunkId)) {
throw new Error(`Duplicate scene-preparation chunk id detected: ${chunk.chunkId}`);
}
chunkIds.add(chunk.chunkId);
}
const jobs = [];
for (const chunk of normalizedChunks) {
const includedStages = new Set(chunk.stages);
for (const stageFamily of chunk.stages) {
const dependencies = collectScenePreparationDependencies(
stageFamily,
includedStages
).map(
(dependency) => `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${dependency}`
);
jobs.push(
Object.freeze({
id: `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${stageFamily}`,
snapshotId,
chunkId: chunk.chunkId,
representationBand: chunk.representationBand,
stageFamily,
priority: buildScenePreparationPriority(chunk, stageFamily),
dependencies: Object.freeze(dependencies),
dependencyCount: dependencies.length,
root: dependencies.length === 0,
authority: "visual",
mutatesSimulation: false,
gameplayImportance: chunk.gameplayImportance,
visible: chunk.visible,
playerRelevant: chunk.playerRelevant,
imageCritical: chunk.imageCritical
})
);
}
}
const jobById = new Map(jobs.map((job) => [job.id, job]));
let crossChunkDependencyCount = 0;
let localJoinCount = 0;
const finalizedJobs = Object.freeze(
jobs.map((job) => {
const dependents = jobs.filter((candidate) => candidate.dependencies.includes(job.id)).map((candidate) => candidate.id);
const crossChunkDependencies = job.dependencies.filter((dependency) => {
const parent = jobById.get(dependency);
return parent && parent.chunkId !== job.chunkId;
});
crossChunkDependencyCount += crossChunkDependencies.length;
if (job.dependencies.length > 1 && crossChunkDependencies.length === 0) {
localJoinCount += 1;
}
return Object.freeze({
...job,
dependents: Object.freeze(dependents),
dependentCount: dependents.length,
unresolvedDependencyCount: job.dependencies.length,
localJoin: job.dependencies.length > 1 && crossChunkDependencies.length === 0
});
})
);
const graph = Object.freeze({
schedulerMode: "dag",
jobCount: finalizedJobs.length,
chunkCount: normalizedChunks.length,
chunkIds: Object.freeze(normalizedChunks.map((chunk) => chunk.chunkId)),
representationBands: Object.freeze(
[...new Set(normalizedChunks.map((chunk) => chunk.representationBand))]
),
roots: Object.freeze(
finalizedJobs.filter((job) => job.root).map((job) => job.id)
),
chunkRoots: Object.freeze(
Object.fromEntries(
normalizedChunks.map((chunk) => [
chunk.chunkId,
finalizedJobs.filter((job) => job.chunkId === chunk.chunkId && job.root).map((job) => job.id)
])
)
),
topologicalOrder: buildScenePreparationTopologicalOrder(finalizedJobs),
priorityLanes: buildScenePreparationPriorityLanes(finalizedJobs),
localJoinCount,
crossChunkDependencyCount
});
return Object.freeze({
schemaVersion: 1,
owner: "scene-preparation",
schedulerMode: "dag",
snapshotId,
jobs: finalizedJobs,
graph
});
}
export {
assembleWorkerWgsl,
createScenePreparationManifest,
createWorkerLoop,

@@ -675,4 +984,6 @@ loadJobWgsl,

loadWorkerWgsl,
scenePreparationRepresentationBands,
scenePreparationStageFamilies,
workerWgslUrl
};
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/index.js"],"sourcesContent":["import {\n loadSchedulerWgsl as loadSchedulerWgslRaw,\n schedulerModes as workerSchedulerModes,\n} from \"@plasius/gpu-lock-free-queue\";\n\nexport const workerWgslUrl = (() => {\n if (typeof __IMPORT_META_URL__ !== \"undefined\") {\n return new URL(\"./worker.wgsl\", __IMPORT_META_URL__);\n }\n if (typeof __filename !== \"undefined\" && typeof require !== \"undefined\") {\n const { pathToFileURL } = require(\"node:url\");\n return new URL(\"./worker.wgsl\", pathToFileURL(__filename));\n }\n const base =\n typeof process !== \"undefined\" && process.cwd\n ? `file://${process.cwd()}/`\n : \"file:///\";\n return new URL(\"./worker.wgsl\", base);\n})();\n\nconst jobRegistry = [];\nlet nextJobType = 0;\n\nasync function loadWgslSource(options = {}) {\n const { wgsl, url, fetcher = globalThis.fetch, baseUrl } = options ?? {};\n if (typeof wgsl === \"string\") {\n assertNotHtmlWgsl(wgsl, \"inline WGSL\");\n return wgsl;\n }\n if (!url) {\n return null;\n }\n const resolved = url instanceof URL ? url : new URL(url, baseUrl);\n if (!fetcher) {\n if (resolved.protocol !== \"file:\") {\n throw new Error(\"No fetcher available for non-file WGSL URL.\");\n }\n const { readFile } = await import(\"fs/promises\");\n const { fileURLToPath } = await import(\"url\");\n const source = await readFile(fileURLToPath(resolved), \"utf8\");\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n }\n const response = await fetcher(resolved);\n if (!response.ok) {\n const status = \"status\" in response ? response.status : \"unknown\";\n const statusText = \"statusText\" in response ? response.statusText : \"\";\n const detail = statusText ? `${status} ${statusText}` : `${status}`;\n throw new Error(`Failed to load WGSL (${detail})`);\n }\n const source = await response.text();\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n}\n\nfunction stripComments(source) {\n return source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/\\/\\/.*$/gm, \"\");\n}\n\nfunction tokenize(source) {\n return source.match(/[A-Za-z_][A-Za-z0-9_]*|[{}();<>,:=]/g) ?? [];\n}\n\nfunction isIdentifier(token) {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(token);\n}\n\nfunction readNameAfterType(tokens, startIndex) {\n let i = startIndex;\n if (tokens[i] === \"<\") {\n let depth = 1;\n i += 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i] === \"<\") {\n depth += 1;\n } else if (tokens[i] === \">\") {\n depth -= 1;\n }\n i += 1;\n }\n }\n return tokens[i];\n}\n\nfunction scanModuleNames(source) {\n const cleaned = stripComments(source);\n const tokens = tokenize(cleaned);\n const names = [];\n let depth = 0;\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i];\n if (token === \"{\") {\n depth += 1;\n continue;\n }\n if (token === \"}\") {\n depth = Math.max(0, depth - 1);\n continue;\n }\n if (depth !== 0) {\n continue;\n }\n if (token === \"fn\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"fn\", name });\n }\n continue;\n }\n if (token === \"struct\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"struct\", name });\n }\n continue;\n }\n if (token === \"alias\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"alias\", name });\n }\n continue;\n }\n if (token === \"var\" || token === \"let\" || token === \"const\" || token === \"override\") {\n const name = readNameAfterType(tokens, i + 1);\n if (isIdentifier(name)) {\n names.push({ kind: token, name });\n }\n }\n }\n return names;\n}\n\nfunction buildNameIndex(modules) {\n const index = new Map();\n for (const module of modules) {\n for (const item of scanModuleNames(module.source)) {\n const bucket = index.get(item.name) ?? [];\n bucket.push({ kind: item.kind, module: module.name });\n index.set(item.name, bucket);\n }\n }\n return index;\n}\n\nfunction assertNoNameClashes(modules) {\n const index = buildNameIndex(modules);\n const clashes = [];\n for (const [name, entries] of index.entries()) {\n if (entries.length > 1) {\n clashes.push({ name, entries });\n }\n }\n if (clashes.length === 0) {\n return;\n }\n const lines = [\"WGSL debug: identifier clashes detected:\"];\n for (const clash of clashes) {\n const locations = clash.entries\n .map((entry) => `${entry.module} (${entry.kind})`)\n .join(\", \");\n lines.push(`- ${clash.name}: ${locations}`);\n }\n throw new Error(lines.join(\"\\n\"));\n}\n\nfunction assertNotHtmlWgsl(source, context) {\n const sample = source.slice(0, 200).toLowerCase();\n if (\n sample.includes(\"<!doctype\") ||\n sample.includes(\"<html\") ||\n sample.includes(\"<meta\")\n ) {\n const label = context ? ` for ${context}` : \"\";\n throw new Error(\n `Expected WGSL${label} but received HTML. Check the URL or server root.`\n );\n }\n}\n\nfunction renameProcessJob(source, name) {\n return source.replace(/\\bprocess_job\\b/g, name);\n}\n\nfunction getQueueCompatMap(source) {\n if (!/\\bJobMeta\\b/.test(source)) {\n return null;\n }\n return [{ from: /\\bJobMeta\\b/g, to: \"JobDesc\" }];\n}\n\nfunction normalizeQueueMode(mode) {\n const resolved = mode ?? \"flat\";\n if (!workerSchedulerModes.includes(resolved)) {\n throw new Error(\n `queueMode must be one of: ${workerSchedulerModes.join(\", \")}.`\n );\n }\n return resolved;\n}\n\nfunction applyCompatMap(source, map) {\n if (!map || map.length === 0) {\n return source;\n }\n let next = source;\n for (const entry of map) {\n next = next.replace(entry.from, entry.to);\n }\n return next;\n}\n\nfunction normalizeJobs(jobs) {\n const normalized = jobs.map((job, index) => {\n if (typeof job === \"string\") {\n return {\n jobType: index,\n wgsl: job,\n label: `job_${index}`,\n sourceName: `job-${index}`,\n };\n }\n if (!job || typeof job.wgsl !== \"string\") {\n throw new Error(\"Job entries must provide WGSL source strings.\");\n }\n const jobType = job.jobType ?? index;\n const label = job.label ?? `job_${jobType}`;\n return {\n jobType,\n wgsl: job.wgsl,\n label,\n sourceName: job.sourceName ?? job.label ?? `job-${jobType}`,\n };\n });\n const seen = new Set();\n for (const job of normalized) {\n if (seen.has(job.jobType)) {\n throw new Error(`Duplicate job_type detected: ${job.jobType}`);\n }\n seen.add(job.jobType);\n }\n return normalized;\n}\n\nfunction buildProcessJobDispatch(jobs) {\n const lines = [\n \"fn process_job(job_index: u32, job_type: u32, payload_words: u32) {\",\n ];\n if (jobs.length === 0) {\n lines.push(\" return;\");\n lines.push(\"}\");\n return lines.join(\"\\n\");\n }\n jobs.forEach((job, idx) => {\n const clause = idx === 0 ? \"if\" : \"else if\";\n lines.push(` ${clause} (job_type == ${job.jobType}u) {`);\n lines.push(\n ` ${job.entryName}(job_index, job_type, payload_words);`\n );\n lines.push(\" }\");\n });\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nexport async function loadWorkerWgsl(options = {}) {\n const { url = workerWgslUrl, fetcher } = options ?? {};\n const source = await loadWgslSource({\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load worker WGSL source.\");\n }\n return source;\n}\n\nexport async function loadQueueWgsl(options = {}) {\n const { queueCompat = true, queueMode = \"flat\", ...rest } = options ?? {};\n const source = await loadSchedulerWgslRaw({\n mode: normalizeQueueMode(queueMode),\n ...rest,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load queue WGSL source.\");\n }\n assertNotHtmlWgsl(source, rest?.url ? String(rest.url) : \"queue WGSL\");\n if (!queueCompat) {\n return source;\n }\n const compatMap = getQueueCompatMap(source);\n return applyCompatMap(source, compatMap);\n}\n\nfunction ensureQueueLifecycleHooks(source) {\n if (/\\bfn\\s+complete_job\\b/.test(source)) {\n return source;\n }\n return `${source}\\n\\nfn complete_job(job_index: u32) {\\n _ = job_index;\\n}`;\n}\n\nexport async function loadJobWgsl(options = {}) {\n const { wgsl, url, fetcher, label } = options ?? {};\n const source = await loadWgslSource({\n wgsl,\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"loadJobWgsl requires a WGSL string or URL.\");\n }\n const jobType = nextJobType;\n nextJobType += 1;\n jobRegistry.push({\n jobType,\n wgsl: source,\n label: label ?? `job_${jobType}`,\n sourceName: label ?? `job-${jobType}`,\n });\n return jobType;\n}\n\nexport async function assembleWorkerWgsl(workerWgsl, options = {}) {\n const {\n queueWgsl,\n queueUrl,\n preludeWgsl,\n preludeUrl,\n fetcher,\n jobs,\n debug,\n queueCompat = true,\n queueMode = \"flat\",\n } = options ?? {};\n const resolvedQueueMode = normalizeQueueMode(queueMode);\n const rawQueueSource =\n queueWgsl ??\n (await loadSchedulerWgslRaw({\n mode: resolvedQueueMode,\n url: queueUrl,\n fetcher,\n }));\n const bodyRaw = workerWgsl ?? (await loadWorkerWgsl({ fetcher }));\n const compatMap = queueCompat ? getQueueCompatMap(rawQueueSource) : null;\n const queueSource = ensureQueueLifecycleHooks(\n applyCompatMap(rawQueueSource, compatMap)\n );\n const preludeRaw =\n preludeWgsl ??\n (preludeUrl\n ? await loadWgslSource({ url: preludeUrl, fetcher, baseUrl: workerWgslUrl })\n : \"\");\n if ((preludeWgsl || preludeUrl) && typeof preludeRaw !== \"string\") {\n throw new Error(\"Failed to load prelude WGSL source.\");\n }\n const preludeSource =\n typeof preludeRaw === \"string\" && preludeRaw.length > 0\n ? applyCompatMap(preludeRaw, compatMap)\n : \"\";\n const body = applyCompatMap(bodyRaw, compatMap);\n const jobList = normalizeJobs(\n typeof jobs === \"undefined\" ? jobRegistry : jobs\n );\n if (!jobList || jobList.length === 0) {\n return `${queueSource}\\n\\n${body}`;\n }\n const rewrittenJobs = jobList.map((job) => {\n const source = applyCompatMap(job.wgsl, compatMap);\n const hasProcessJob = /\\bfn\\s+process_job\\b/.test(source);\n if (!hasProcessJob) {\n throw new Error(\n `Job ${job.sourceName} is missing a process_job() entry function.`\n );\n }\n const entryName = `process_job__${job.jobType}`;\n const renamed = renameProcessJob(source, entryName);\n return { ...job, entryName, wgsl: renamed };\n });\n const dispatch = buildProcessJobDispatch(rewrittenJobs);\n const modulesForDebug = debug\n ? [\n { name: \"queue.wgsl\", source: queueSource },\n ...(preludeSource\n ? [{ name: \"jobs.prelude.wgsl\", source: preludeSource }]\n : []),\n ...rewrittenJobs.map((job) => ({\n name: job.sourceName,\n source: job.wgsl,\n })),\n { name: \"jobs.dispatch.wgsl\", source: dispatch },\n { name: \"worker.wgsl\", source: body },\n ]\n : null;\n if (modulesForDebug) {\n assertNoNameClashes(modulesForDebug);\n }\n const jobBlocks = rewrittenJobs\n .map((job) => `// Job ${job.jobType}: ${job.label}\\n${job.wgsl}`)\n .join(\"\\n\\n\");\n const preludeBlock = preludeSource ? `${preludeSource}\\n\\n` : \"\";\n return `${queueSource}\\n\\n${preludeBlock}${jobBlocks}\\n\\n${dispatch}\\n\\n${body}`;\n}\n\nfunction normalizeWorkgroups(value, label) {\n if (typeof value === \"number\") {\n return [value, 1, 1];\n }\n if (Array.isArray(value)) {\n const [x = 0, y = 1, z = 1] = value;\n return [x, y, z];\n }\n throw new Error(`Invalid workgroup count for ${label}.`);\n}\n\nfunction resolveWorkgroups(value, label) {\n if (typeof value === \"function\") {\n return normalizeWorkgroups(value(), label);\n }\n if (value == null) {\n return null;\n }\n return normalizeWorkgroups(value, label);\n}\n\nfunction normalizeTelemetryText(value, fallback) {\n if (typeof value !== \"string\") {\n return fallback;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : fallback;\n}\n\nfunction resolveFrameId(value) {\n if (typeof value === \"function\") {\n return resolveFrameId(value());\n }\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : undefined;\n}\n\nfunction toVector(workgroups) {\n return { x: workgroups[0], y: workgroups[1], z: workgroups[2] };\n}\n\nfunction resolveTelemetryWorkgroupSize(descriptor, fallback, label) {\n const size =\n descriptor?.workgroupSize == null ? fallback : descriptor.workgroupSize;\n if (size == null) {\n return undefined;\n }\n const normalized =\n typeof size === \"number\" ? normalizeWorkgroups(size, label) : resolveWorkgroups(size, label);\n if (!normalized) {\n return undefined;\n }\n return toVector(normalized);\n}\n\nfunction getNow() {\n if (globalThis.performance && typeof globalThis.performance.now === \"function\") {\n return globalThis.performance.now();\n }\n return Date.now();\n}\n\nfunction reportOptionalError(error, onError) {\n if (!onError) {\n return;\n }\n if (error instanceof Error) {\n onError(error);\n return;\n }\n onError(new Error(String(error)));\n}\n\nfunction emitOptionalHook(callback, payload, onError) {\n if (typeof callback !== \"function\") {\n return;\n }\n try {\n callback(payload);\n } catch (error) {\n reportOptionalError(error, onError);\n }\n}\n\nfunction buildDispatchTelemetrySample({\n kind,\n descriptor,\n index,\n frameId,\n workgroups,\n workgroupSize,\n}) {\n const labelFallback = kind === \"worker\" ? \"worker\" : `job_${index}`;\n const label = normalizeTelemetryText(descriptor?.label, labelFallback);\n return {\n kind,\n index,\n label,\n owner: normalizeTelemetryText(descriptor?.owner, label),\n queueClass: normalizeTelemetryText(descriptor?.queueClass, \"custom\"),\n jobType: normalizeTelemetryText(\n descriptor?.jobType,\n kind === \"worker\" ? \"worker.dispatch\" : label\n ),\n frameId,\n workgroups: toVector(workgroups),\n workgroupSize,\n };\n}\n\nfunction setBindGroups(pass, bindGroups) {\n if (!bindGroups) {\n return;\n }\n bindGroups.forEach((group, index) => {\n if (group) {\n pass.setBindGroup(index, group);\n }\n });\n}\n\nfunction computeWorkerWorkgroups(maxJobs, workgroupSize) {\n const jobs =\n typeof maxJobs === \"function\" ? Number(maxJobs()) : Number(maxJobs);\n if (!Number.isFinite(jobs) || jobs <= 0) {\n throw new Error(\"maxJobsPerDispatch must be a positive number.\");\n }\n const size = Number(workgroupSize);\n if (!Number.isFinite(size) || size <= 0) {\n throw new Error(\"workgroupSize must be a positive number.\");\n }\n return Math.max(1, Math.ceil(jobs / size));\n}\n\nexport function createWorkerLoop(options = {}) {\n const {\n device,\n worker,\n jobs = [],\n workgroupSize = 64,\n maxJobsPerDispatch,\n rateHz,\n label,\n onTick,\n onError,\n frameId,\n telemetry,\n } = options ?? {};\n\n if (!device) {\n throw new Error(\"createWorkerLoop requires a GPUDevice.\");\n }\n if (!worker || !worker.pipeline) {\n throw new Error(\"createWorkerLoop requires a worker pipeline.\");\n }\n\n let running = false;\n let handle = null;\n let usingRaf = false;\n const intervalMs =\n Number.isFinite(rateHz) && rateHz > 0 ? 1000 / rateHz : null;\n\n const tick = () => {\n try {\n const tickStartMs = getNow();\n const currentFrameId = resolveFrameId(frameId);\n const telemetryDispatches = [];\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass(\n label ? { label } : undefined\n );\n\n pass.setPipeline(worker.pipeline);\n setBindGroups(pass, worker.bindGroups);\n\n const explicitWorkerGroups =\n resolveWorkgroups(worker.workgroups, \"worker\") ??\n resolveWorkgroups(worker.workgroupCount, \"worker\") ??\n resolveWorkgroups(worker.dispatch, \"worker\");\n\n const workerGroups = explicitWorkerGroups\n ? explicitWorkerGroups\n : [computeWorkerWorkgroups(maxJobsPerDispatch, workgroupSize), 1, 1];\n\n if (workerGroups[0] > 0) {\n pass.dispatchWorkgroups(...workerGroups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"worker\",\n descriptor: worker,\n index: 0,\n frameId: currentFrameId,\n workgroups: workerGroups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n worker,\n workgroupSize,\n \"worker workgroupSize\"\n ),\n })\n );\n }\n\n jobs.forEach((job, index) => {\n if (!job || !job.pipeline) {\n throw new Error(`Job pipeline missing at index ${index}.`);\n }\n pass.setPipeline(job.pipeline);\n setBindGroups(pass, job.bindGroups);\n const groups = resolveWorkgroups(\n job.workgroups ?? job.workgroupCount ?? job.dispatch,\n `job ${index}`\n );\n if (!groups) {\n throw new Error(`Job ${index} requires a workgroup count.`);\n }\n if (groups[0] > 0) {\n pass.dispatchWorkgroups(...groups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"job\",\n descriptor: job,\n index,\n frameId: currentFrameId,\n workgroups: groups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n job,\n undefined,\n `job ${index} workgroupSize`\n ),\n })\n );\n }\n });\n\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n telemetryDispatches.forEach((sample) => {\n emitOptionalHook(telemetry?.onDispatch, sample, onError);\n });\n emitOptionalHook(\n telemetry?.onTick,\n {\n frameId: currentFrameId,\n tickDurationMs: getNow() - tickStartMs,\n dispatchCount: telemetryDispatches.length,\n workerDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"worker\"\n ).length,\n jobDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"job\"\n ).length,\n dispatches: telemetryDispatches,\n },\n onError\n );\n\n if (onTick) {\n onTick();\n }\n } catch (err) {\n if (onError) {\n onError(err);\n return;\n }\n throw err;\n }\n };\n\n const scheduleNext = () => {\n if (!running) {\n return;\n }\n if (intervalMs != null) {\n tick();\n usingRaf = false;\n handle = setTimeout(scheduleNext, intervalMs);\n return;\n }\n tick();\n if (typeof requestAnimationFrame === \"function\") {\n usingRaf = true;\n handle = requestAnimationFrame(scheduleNext);\n } else {\n usingRaf = false;\n handle = setTimeout(scheduleNext, 0);\n }\n };\n\n const start = () => {\n if (running) {\n return;\n }\n running = true;\n scheduleNext();\n };\n\n const stop = () => {\n running = false;\n if (handle == null) {\n return;\n }\n if (usingRaf && typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(handle);\n } else {\n clearTimeout(handle);\n }\n handle = null;\n };\n\n return {\n start,\n stop,\n tick,\n get running() {\n return running;\n },\n };\n}\n"],"mappings":"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","names":["source"]}
{"version":3,"sources":["../src/index.js"],"sourcesContent":["import {\n loadSchedulerWgsl as loadSchedulerWgslRaw,\n schedulerModes as workerSchedulerModes,\n} from \"@plasius/gpu-lock-free-queue\";\n\nexport const workerWgslUrl = (() => {\n if (typeof __IMPORT_META_URL__ !== \"undefined\") {\n return new URL(\"./worker.wgsl\", __IMPORT_META_URL__);\n }\n if (typeof __filename !== \"undefined\" && typeof require !== \"undefined\") {\n const { pathToFileURL } = require(\"node:url\");\n return new URL(\"./worker.wgsl\", pathToFileURL(__filename));\n }\n const base =\n typeof process !== \"undefined\" && process.cwd\n ? `file://${process.cwd()}/`\n : \"file:///\";\n return new URL(\"./worker.wgsl\", base);\n})();\n\nconst jobRegistry = [];\nlet nextJobType = 0;\n\nasync function loadWgslSource(options = {}) {\n const { wgsl, url, fetcher = globalThis.fetch, baseUrl } = options ?? {};\n if (typeof wgsl === \"string\") {\n assertNotHtmlWgsl(wgsl, \"inline WGSL\");\n return wgsl;\n }\n if (!url) {\n return null;\n }\n const resolved = url instanceof URL ? url : new URL(url, baseUrl);\n if (!fetcher) {\n if (resolved.protocol !== \"file:\") {\n throw new Error(\"No fetcher available for non-file WGSL URL.\");\n }\n const { readFile } = await import(\"fs/promises\");\n const { fileURLToPath } = await import(\"url\");\n const source = await readFile(fileURLToPath(resolved), \"utf8\");\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n }\n const response = await fetcher(resolved);\n if (!response.ok) {\n const status = \"status\" in response ? response.status : \"unknown\";\n const statusText = \"statusText\" in response ? response.statusText : \"\";\n const detail = statusText ? `${status} ${statusText}` : `${status}`;\n throw new Error(`Failed to load WGSL (${detail})`);\n }\n const source = await response.text();\n assertNotHtmlWgsl(source, resolved.href);\n return source;\n}\n\nfunction stripComments(source) {\n return source\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, \"\")\n .replace(/\\/\\/.*$/gm, \"\");\n}\n\nfunction tokenize(source) {\n return source.match(/[A-Za-z_][A-Za-z0-9_]*|[{}();<>,:=]/g) ?? [];\n}\n\nfunction isIdentifier(token) {\n return /^[A-Za-z_][A-Za-z0-9_]*$/.test(token);\n}\n\nfunction readNameAfterType(tokens, startIndex) {\n let i = startIndex;\n if (tokens[i] === \"<\") {\n let depth = 1;\n i += 1;\n while (i < tokens.length && depth > 0) {\n if (tokens[i] === \"<\") {\n depth += 1;\n } else if (tokens[i] === \">\") {\n depth -= 1;\n }\n i += 1;\n }\n }\n return tokens[i];\n}\n\nfunction scanModuleNames(source) {\n const cleaned = stripComments(source);\n const tokens = tokenize(cleaned);\n const names = [];\n let depth = 0;\n for (let i = 0; i < tokens.length; i += 1) {\n const token = tokens[i];\n if (token === \"{\") {\n depth += 1;\n continue;\n }\n if (token === \"}\") {\n depth = Math.max(0, depth - 1);\n continue;\n }\n if (depth !== 0) {\n continue;\n }\n if (token === \"fn\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"fn\", name });\n }\n continue;\n }\n if (token === \"struct\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"struct\", name });\n }\n continue;\n }\n if (token === \"alias\") {\n const name = tokens[i + 1];\n if (isIdentifier(name)) {\n names.push({ kind: \"alias\", name });\n }\n continue;\n }\n if (token === \"var\" || token === \"let\" || token === \"const\" || token === \"override\") {\n const name = readNameAfterType(tokens, i + 1);\n if (isIdentifier(name)) {\n names.push({ kind: token, name });\n }\n }\n }\n return names;\n}\n\nfunction buildNameIndex(modules) {\n const index = new Map();\n for (const module of modules) {\n for (const item of scanModuleNames(module.source)) {\n const bucket = index.get(item.name) ?? [];\n bucket.push({ kind: item.kind, module: module.name });\n index.set(item.name, bucket);\n }\n }\n return index;\n}\n\nfunction assertNoNameClashes(modules) {\n const index = buildNameIndex(modules);\n const clashes = [];\n for (const [name, entries] of index.entries()) {\n if (entries.length > 1) {\n clashes.push({ name, entries });\n }\n }\n if (clashes.length === 0) {\n return;\n }\n const lines = [\"WGSL debug: identifier clashes detected:\"];\n for (const clash of clashes) {\n const locations = clash.entries\n .map((entry) => `${entry.module} (${entry.kind})`)\n .join(\", \");\n lines.push(`- ${clash.name}: ${locations}`);\n }\n throw new Error(lines.join(\"\\n\"));\n}\n\nfunction assertNotHtmlWgsl(source, context) {\n const sample = source.slice(0, 200).toLowerCase();\n if (\n sample.includes(\"<!doctype\") ||\n sample.includes(\"<html\") ||\n sample.includes(\"<meta\")\n ) {\n const label = context ? ` for ${context}` : \"\";\n throw new Error(\n `Expected WGSL${label} but received HTML. Check the URL or server root.`\n );\n }\n}\n\nfunction renameProcessJob(source, name) {\n return source.replace(/\\bprocess_job\\b/g, name);\n}\n\nfunction getQueueCompatMap(source) {\n if (!/\\bJobMeta\\b/.test(source)) {\n return null;\n }\n return [{ from: /\\bJobMeta\\b/g, to: \"JobDesc\" }];\n}\n\nfunction normalizeQueueMode(mode) {\n const resolved = mode ?? \"flat\";\n if (!workerSchedulerModes.includes(resolved)) {\n throw new Error(\n `queueMode must be one of: ${workerSchedulerModes.join(\", \")}.`\n );\n }\n return resolved;\n}\n\nfunction applyCompatMap(source, map) {\n if (!map || map.length === 0) {\n return source;\n }\n let next = source;\n for (const entry of map) {\n next = next.replace(entry.from, entry.to);\n }\n return next;\n}\n\nfunction normalizeJobs(jobs) {\n const normalized = jobs.map((job, index) => {\n if (typeof job === \"string\") {\n return {\n jobType: index,\n wgsl: job,\n label: `job_${index}`,\n sourceName: `job-${index}`,\n };\n }\n if (!job || typeof job.wgsl !== \"string\") {\n throw new Error(\"Job entries must provide WGSL source strings.\");\n }\n const jobType = job.jobType ?? index;\n const label = job.label ?? `job_${jobType}`;\n return {\n jobType,\n wgsl: job.wgsl,\n label,\n sourceName: job.sourceName ?? job.label ?? `job-${jobType}`,\n };\n });\n const seen = new Set();\n for (const job of normalized) {\n if (seen.has(job.jobType)) {\n throw new Error(`Duplicate job_type detected: ${job.jobType}`);\n }\n seen.add(job.jobType);\n }\n return normalized;\n}\n\nfunction buildProcessJobDispatch(jobs) {\n const lines = [\n \"fn process_job(job_index: u32, job_type: u32, payload_words: u32) {\",\n ];\n if (jobs.length === 0) {\n lines.push(\" return;\");\n lines.push(\"}\");\n return lines.join(\"\\n\");\n }\n jobs.forEach((job, idx) => {\n const clause = idx === 0 ? \"if\" : \"else if\";\n lines.push(` ${clause} (job_type == ${job.jobType}u) {`);\n lines.push(\n ` ${job.entryName}(job_index, job_type, payload_words);`\n );\n lines.push(\" }\");\n });\n lines.push(\"}\");\n return lines.join(\"\\n\");\n}\n\nexport async function loadWorkerWgsl(options = {}) {\n const { url = workerWgslUrl, fetcher } = options ?? {};\n const source = await loadWgslSource({\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load worker WGSL source.\");\n }\n return source;\n}\n\nexport async function loadQueueWgsl(options = {}) {\n const { queueCompat = true, queueMode = \"flat\", ...rest } = options ?? {};\n const source = await loadSchedulerWgslRaw({\n mode: normalizeQueueMode(queueMode),\n ...rest,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"Failed to load queue WGSL source.\");\n }\n assertNotHtmlWgsl(source, rest?.url ? String(rest.url) : \"queue WGSL\");\n if (!queueCompat) {\n return source;\n }\n const compatMap = getQueueCompatMap(source);\n return applyCompatMap(source, compatMap);\n}\n\nfunction ensureQueueLifecycleHooks(source) {\n if (/\\bfn\\s+complete_job\\b/.test(source)) {\n return source;\n }\n return `${source}\\n\\nfn complete_job(job_index: u32) {\\n _ = job_index;\\n}`;\n}\n\nexport async function loadJobWgsl(options = {}) {\n const { wgsl, url, fetcher, label } = options ?? {};\n const source = await loadWgslSource({\n wgsl,\n url,\n fetcher,\n baseUrl: workerWgslUrl,\n });\n if (typeof source !== \"string\") {\n throw new Error(\"loadJobWgsl requires a WGSL string or URL.\");\n }\n const jobType = nextJobType;\n nextJobType += 1;\n jobRegistry.push({\n jobType,\n wgsl: source,\n label: label ?? `job_${jobType}`,\n sourceName: label ?? `job-${jobType}`,\n });\n return jobType;\n}\n\nexport async function assembleWorkerWgsl(workerWgsl, options = {}) {\n const {\n queueWgsl,\n queueUrl,\n preludeWgsl,\n preludeUrl,\n fetcher,\n jobs,\n debug,\n queueCompat = true,\n queueMode = \"flat\",\n } = options ?? {};\n const resolvedQueueMode = normalizeQueueMode(queueMode);\n const rawQueueSource =\n queueWgsl ??\n (await loadSchedulerWgslRaw({\n mode: resolvedQueueMode,\n url: queueUrl,\n fetcher,\n }));\n const bodyRaw = workerWgsl ?? (await loadWorkerWgsl({ fetcher }));\n const compatMap = queueCompat ? getQueueCompatMap(rawQueueSource) : null;\n const queueSource = ensureQueueLifecycleHooks(\n applyCompatMap(rawQueueSource, compatMap)\n );\n const preludeRaw =\n preludeWgsl ??\n (preludeUrl\n ? await loadWgslSource({ url: preludeUrl, fetcher, baseUrl: workerWgslUrl })\n : \"\");\n if ((preludeWgsl || preludeUrl) && typeof preludeRaw !== \"string\") {\n throw new Error(\"Failed to load prelude WGSL source.\");\n }\n const preludeSource =\n typeof preludeRaw === \"string\" && preludeRaw.length > 0\n ? applyCompatMap(preludeRaw, compatMap)\n : \"\";\n const body = applyCompatMap(bodyRaw, compatMap);\n const jobList = normalizeJobs(\n typeof jobs === \"undefined\" ? jobRegistry : jobs\n );\n if (!jobList || jobList.length === 0) {\n return `${queueSource}\\n\\n${body}`;\n }\n const rewrittenJobs = jobList.map((job) => {\n const source = applyCompatMap(job.wgsl, compatMap);\n const hasProcessJob = /\\bfn\\s+process_job\\b/.test(source);\n if (!hasProcessJob) {\n throw new Error(\n `Job ${job.sourceName} is missing a process_job() entry function.`\n );\n }\n const entryName = `process_job__${job.jobType}`;\n const renamed = renameProcessJob(source, entryName);\n return { ...job, entryName, wgsl: renamed };\n });\n const dispatch = buildProcessJobDispatch(rewrittenJobs);\n const modulesForDebug = debug\n ? [\n { name: \"queue.wgsl\", source: queueSource },\n ...(preludeSource\n ? [{ name: \"jobs.prelude.wgsl\", source: preludeSource }]\n : []),\n ...rewrittenJobs.map((job) => ({\n name: job.sourceName,\n source: job.wgsl,\n })),\n { name: \"jobs.dispatch.wgsl\", source: dispatch },\n { name: \"worker.wgsl\", source: body },\n ]\n : null;\n if (modulesForDebug) {\n assertNoNameClashes(modulesForDebug);\n }\n const jobBlocks = rewrittenJobs\n .map((job) => `// Job ${job.jobType}: ${job.label}\\n${job.wgsl}`)\n .join(\"\\n\\n\");\n const preludeBlock = preludeSource ? `${preludeSource}\\n\\n` : \"\";\n return `${queueSource}\\n\\n${preludeBlock}${jobBlocks}\\n\\n${dispatch}\\n\\n${body}`;\n}\n\nfunction normalizeWorkgroups(value, label) {\n if (typeof value === \"number\") {\n return [value, 1, 1];\n }\n if (Array.isArray(value)) {\n const [x = 0, y = 1, z = 1] = value;\n return [x, y, z];\n }\n throw new Error(`Invalid workgroup count for ${label}.`);\n}\n\nfunction resolveWorkgroups(value, label) {\n if (typeof value === \"function\") {\n return normalizeWorkgroups(value(), label);\n }\n if (value == null) {\n return null;\n }\n return normalizeWorkgroups(value, label);\n}\n\nfunction normalizeTelemetryText(value, fallback) {\n if (typeof value !== \"string\") {\n return fallback;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : fallback;\n}\n\nfunction resolveFrameId(value) {\n if (typeof value === \"function\") {\n return resolveFrameId(value());\n }\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed ? trimmed.slice(0, 120) : undefined;\n}\n\nfunction toVector(workgroups) {\n return { x: workgroups[0], y: workgroups[1], z: workgroups[2] };\n}\n\nfunction resolveTelemetryWorkgroupSize(descriptor, fallback, label) {\n const size =\n descriptor?.workgroupSize == null ? fallback : descriptor.workgroupSize;\n if (size == null) {\n return undefined;\n }\n const normalized =\n typeof size === \"number\" ? normalizeWorkgroups(size, label) : resolveWorkgroups(size, label);\n if (!normalized) {\n return undefined;\n }\n return toVector(normalized);\n}\n\nfunction getNow() {\n if (globalThis.performance && typeof globalThis.performance.now === \"function\") {\n return globalThis.performance.now();\n }\n return Date.now();\n}\n\nfunction reportOptionalError(error, onError) {\n if (!onError) {\n return;\n }\n if (error instanceof Error) {\n onError(error);\n return;\n }\n onError(new Error(String(error)));\n}\n\nfunction emitOptionalHook(callback, payload, onError) {\n if (typeof callback !== \"function\") {\n return;\n }\n try {\n callback(payload);\n } catch (error) {\n reportOptionalError(error, onError);\n }\n}\n\nfunction buildDispatchTelemetrySample({\n kind,\n descriptor,\n index,\n frameId,\n workgroups,\n workgroupSize,\n}) {\n const labelFallback = kind === \"worker\" ? \"worker\" : `job_${index}`;\n const label = normalizeTelemetryText(descriptor?.label, labelFallback);\n return {\n kind,\n index,\n label,\n owner: normalizeTelemetryText(descriptor?.owner, label),\n queueClass: normalizeTelemetryText(descriptor?.queueClass, \"custom\"),\n jobType: normalizeTelemetryText(\n descriptor?.jobType,\n kind === \"worker\" ? \"worker.dispatch\" : label\n ),\n frameId,\n workgroups: toVector(workgroups),\n workgroupSize,\n };\n}\n\nfunction setBindGroups(pass, bindGroups) {\n if (!bindGroups) {\n return;\n }\n bindGroups.forEach((group, index) => {\n if (group) {\n pass.setBindGroup(index, group);\n }\n });\n}\n\nfunction computeWorkerWorkgroups(maxJobs, workgroupSize) {\n const jobs =\n typeof maxJobs === \"function\" ? Number(maxJobs()) : Number(maxJobs);\n if (!Number.isFinite(jobs) || jobs <= 0) {\n throw new Error(\"maxJobsPerDispatch must be a positive number.\");\n }\n const size = Number(workgroupSize);\n if (!Number.isFinite(size) || size <= 0) {\n throw new Error(\"workgroupSize must be a positive number.\");\n }\n return Math.max(1, Math.ceil(jobs / size));\n}\n\nexport function createWorkerLoop(options = {}) {\n const {\n device,\n worker,\n jobs = [],\n workgroupSize = 64,\n maxJobsPerDispatch,\n rateHz,\n label,\n onTick,\n onError,\n frameId,\n telemetry,\n } = options ?? {};\n\n if (!device) {\n throw new Error(\"createWorkerLoop requires a GPUDevice.\");\n }\n if (!worker || !worker.pipeline) {\n throw new Error(\"createWorkerLoop requires a worker pipeline.\");\n }\n\n let running = false;\n let handle = null;\n let usingRaf = false;\n const intervalMs =\n Number.isFinite(rateHz) && rateHz > 0 ? 1000 / rateHz : null;\n\n const tick = () => {\n try {\n const tickStartMs = getNow();\n const currentFrameId = resolveFrameId(frameId);\n const telemetryDispatches = [];\n const encoder = device.createCommandEncoder();\n const pass = encoder.beginComputePass(\n label ? { label } : undefined\n );\n\n pass.setPipeline(worker.pipeline);\n setBindGroups(pass, worker.bindGroups);\n\n const explicitWorkerGroups =\n resolveWorkgroups(worker.workgroups, \"worker\") ??\n resolveWorkgroups(worker.workgroupCount, \"worker\") ??\n resolveWorkgroups(worker.dispatch, \"worker\");\n\n const workerGroups = explicitWorkerGroups\n ? explicitWorkerGroups\n : [computeWorkerWorkgroups(maxJobsPerDispatch, workgroupSize), 1, 1];\n\n if (workerGroups[0] > 0) {\n pass.dispatchWorkgroups(...workerGroups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"worker\",\n descriptor: worker,\n index: 0,\n frameId: currentFrameId,\n workgroups: workerGroups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n worker,\n workgroupSize,\n \"worker workgroupSize\"\n ),\n })\n );\n }\n\n jobs.forEach((job, index) => {\n if (!job || !job.pipeline) {\n throw new Error(`Job pipeline missing at index ${index}.`);\n }\n pass.setPipeline(job.pipeline);\n setBindGroups(pass, job.bindGroups);\n const groups = resolveWorkgroups(\n job.workgroups ?? job.workgroupCount ?? job.dispatch,\n `job ${index}`\n );\n if (!groups) {\n throw new Error(`Job ${index} requires a workgroup count.`);\n }\n if (groups[0] > 0) {\n pass.dispatchWorkgroups(...groups);\n telemetryDispatches.push(\n buildDispatchTelemetrySample({\n kind: \"job\",\n descriptor: job,\n index,\n frameId: currentFrameId,\n workgroups: groups,\n workgroupSize: resolveTelemetryWorkgroupSize(\n job,\n undefined,\n `job ${index} workgroupSize`\n ),\n })\n );\n }\n });\n\n pass.end();\n device.queue.submit([encoder.finish()]);\n\n telemetryDispatches.forEach((sample) => {\n emitOptionalHook(telemetry?.onDispatch, sample, onError);\n });\n emitOptionalHook(\n telemetry?.onTick,\n {\n frameId: currentFrameId,\n tickDurationMs: getNow() - tickStartMs,\n dispatchCount: telemetryDispatches.length,\n workerDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"worker\"\n ).length,\n jobDispatchCount: telemetryDispatches.filter(\n (sample) => sample.kind === \"job\"\n ).length,\n dispatches: telemetryDispatches,\n },\n onError\n );\n\n if (onTick) {\n onTick();\n }\n } catch (err) {\n if (onError) {\n onError(err);\n return;\n }\n throw err;\n }\n };\n\n const scheduleNext = () => {\n if (!running) {\n return;\n }\n if (intervalMs != null) {\n tick();\n usingRaf = false;\n handle = setTimeout(scheduleNext, intervalMs);\n return;\n }\n tick();\n if (typeof requestAnimationFrame === \"function\") {\n usingRaf = true;\n handle = requestAnimationFrame(scheduleNext);\n } else {\n usingRaf = false;\n handle = setTimeout(scheduleNext, 0);\n }\n };\n\n const start = () => {\n if (running) {\n return;\n }\n running = true;\n scheduleNext();\n };\n\n const stop = () => {\n running = false;\n if (handle == null) {\n return;\n }\n if (usingRaf && typeof cancelAnimationFrame === \"function\") {\n cancelAnimationFrame(handle);\n } else {\n clearTimeout(handle);\n }\n handle = null;\n };\n\n return {\n start,\n stop,\n tick,\n get running() {\n return running;\n },\n };\n}\n\nexport const scenePreparationRepresentationBands = Object.freeze([\n \"near\",\n \"mid\",\n \"far\",\n \"horizon\",\n]);\n\nexport const scenePreparationStageFamilies = Object.freeze([\n \"snapshotSelection\",\n \"transformPropagation\",\n \"animationPose\",\n \"proceduralAnimation\",\n \"skinningOrDeformation\",\n \"boundsUpdate\",\n \"lodSelection\",\n \"rtRepresentationSelection\",\n \"visibility\",\n \"lightAssignment\",\n \"renderProxyBuild\",\n \"rtInstancePreparation\",\n]);\n\nconst scenePreparationDefaultStageDependencies = Object.freeze({\n snapshotSelection: Object.freeze([]),\n transformPropagation: Object.freeze([\"snapshotSelection\"]),\n animationPose: Object.freeze([\"transformPropagation\"]),\n proceduralAnimation: Object.freeze([\"animationPose\"]),\n skinningOrDeformation: Object.freeze([\n \"animationPose\",\n \"proceduralAnimation\",\n ]),\n boundsUpdate: Object.freeze([\"skinningOrDeformation\"]),\n lodSelection: Object.freeze([\"boundsUpdate\"]),\n rtRepresentationSelection: Object.freeze([\"lodSelection\"]),\n visibility: Object.freeze([\"boundsUpdate\", \"lodSelection\"]),\n lightAssignment: Object.freeze([\"visibility\"]),\n renderProxyBuild: Object.freeze([\"visibility\", \"lodSelection\"]),\n rtInstancePreparation: Object.freeze([\n \"visibility\",\n \"rtRepresentationSelection\",\n ]),\n});\n\nconst scenePreparationBandPriorityWeights = Object.freeze({\n near: 400,\n mid: 300,\n far: 200,\n horizon: 100,\n});\n\nconst scenePreparationImportanceWeights = Object.freeze({\n low: 0,\n medium: 15,\n high: 30,\n critical: 60,\n});\n\nconst scenePreparationStagePriorityWeights = Object.freeze({\n snapshotSelection: 60,\n transformPropagation: 54,\n animationPose: 50,\n proceduralAnimation: 46,\n skinningOrDeformation: 42,\n boundsUpdate: 38,\n lodSelection: 32,\n rtRepresentationSelection: 28,\n visibility: 34,\n lightAssignment: 24,\n renderProxyBuild: 22,\n rtInstancePreparation: 26,\n});\n\nfunction assertScenePreparationIdentifier(name, value) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new Error(`${name} must be a non-empty string.`);\n }\n return value.trim();\n}\n\nfunction assertScenePreparationEnum(name, value, allowed) {\n const normalized = assertScenePreparationIdentifier(name, value);\n if (!allowed.includes(normalized)) {\n throw new Error(`${name} must be one of: ${allowed.join(\", \")}.`);\n }\n return normalized;\n}\n\nfunction normalizeScenePreparationStages(stages, chunkLabel) {\n const requested =\n stages === undefined ? scenePreparationStageFamilies : stages;\n if (!Array.isArray(requested) || requested.length === 0) {\n throw new Error(`${chunkLabel}.stages must be a non-empty array when provided.`);\n }\n\n const normalized = [...new Set(\n requested.map((stage, index) =>\n assertScenePreparationEnum(\n `${chunkLabel}.stages[${index}]`,\n stage,\n scenePreparationStageFamilies\n )\n )\n )];\n\n return normalized.sort(\n (left, right) =>\n scenePreparationStageFamilies.indexOf(left) -\n scenePreparationStageFamilies.indexOf(right)\n );\n}\n\nfunction collectScenePreparationDependencies(\n stageFamily,\n includedStages,\n seen = new Set()\n) {\n const dependencies =\n scenePreparationDefaultStageDependencies[stageFamily] ?? [];\n for (const dependency of dependencies) {\n if (includedStages.has(dependency)) {\n seen.add(dependency);\n continue;\n }\n collectScenePreparationDependencies(dependency, includedStages, seen);\n }\n return [...seen].sort(\n (left, right) =>\n scenePreparationStageFamilies.indexOf(left) -\n scenePreparationStageFamilies.indexOf(right)\n );\n}\n\nfunction buildScenePreparationPriority(chunk, stageFamily) {\n const bandWeight =\n scenePreparationBandPriorityWeights[chunk.representationBand] ?? 0;\n const importanceWeight =\n scenePreparationImportanceWeights[chunk.gameplayImportance] ?? 0;\n const stageWeight =\n scenePreparationStagePriorityWeights[stageFamily] ?? 0;\n\n return (\n bandWeight +\n importanceWeight +\n stageWeight +\n (chunk.visible ? 20 : 0) +\n (chunk.playerRelevant ? 20 : 0) +\n (chunk.imageCritical ? 15 : 0)\n );\n}\n\nfunction buildScenePreparationPriorityLanes(jobs) {\n const lanes = new Map();\n for (const job of jobs) {\n const lane = lanes.get(job.priority) ?? {\n priority: job.priority,\n jobIds: [],\n chunkIds: [],\n };\n lane.jobIds.push(job.id);\n if (!lane.chunkIds.includes(job.chunkId)) {\n lane.chunkIds.push(job.chunkId);\n }\n lanes.set(job.priority, lane);\n }\n\n return Object.freeze(\n [...lanes.values()]\n .sort((left, right) => right.priority - left.priority)\n .map((lane) =>\n Object.freeze({\n priority: lane.priority,\n jobIds: Object.freeze([...lane.jobIds]),\n chunkIds: Object.freeze([...lane.chunkIds]),\n jobCount: lane.jobIds.length,\n })\n )\n );\n}\n\nfunction buildScenePreparationTopologicalOrder(jobs) {\n const indegree = new Map(jobs.map((job) => [job.id, job.dependencies.length]));\n const dependentsById = new Map(jobs.map((job) => [job.id, []]));\n\n for (const job of jobs) {\n for (const dependency of job.dependencies) {\n dependentsById.get(dependency)?.push(job.id);\n }\n }\n\n const queue = jobs\n .filter((job) => job.dependencies.length === 0)\n .sort((left, right) => right.priority - left.priority)\n .map((job) => job.id);\n const jobById = new Map(jobs.map((job) => [job.id, job]));\n const order = [];\n\n while (queue.length > 0) {\n const currentId = queue.shift();\n if (!currentId) {\n continue;\n }\n order.push(currentId);\n const unlocked = [];\n for (const dependentId of dependentsById.get(currentId) ?? []) {\n const next = (indegree.get(dependentId) ?? 0) - 1;\n indegree.set(dependentId, next);\n if (next === 0) {\n unlocked.push(dependentId);\n }\n }\n unlocked\n .sort(\n (left, right) =>\n (jobById.get(right)?.priority ?? 0) -\n (jobById.get(left)?.priority ?? 0)\n )\n .forEach((jobId) => {\n queue.push(jobId);\n });\n }\n\n if (order.length !== jobs.length) {\n throw new Error(\"Scene-preparation manifest contains a cycle.\");\n }\n\n return Object.freeze(order);\n}\n\nexport function createScenePreparationManifest(options = {}) {\n const snapshotId = assertScenePreparationIdentifier(\n \"snapshotId\",\n options.snapshotId\n );\n const chunkEntries = Array.isArray(options.chunks) ? options.chunks : [];\n if (chunkEntries.length === 0) {\n throw new Error(\"createScenePreparationManifest requires at least one chunk.\");\n }\n\n const normalizedChunks = chunkEntries.map((chunk, index) => {\n if (!chunk || typeof chunk !== \"object\" || Array.isArray(chunk)) {\n throw new Error(`chunks[${index}] must be an object.`);\n }\n const chunkLabel = `chunks[${index}]`;\n if (chunk.mutatesSimulation === true) {\n throw new Error(\n `${chunkLabel}.mutatesSimulation cannot be true for render preparation.`\n );\n }\n\n return Object.freeze({\n chunkId: assertScenePreparationIdentifier(`${chunkLabel}.chunkId`, chunk.chunkId),\n representationBand: assertScenePreparationEnum(\n `${chunkLabel}.representationBand`,\n chunk.representationBand ?? \"mid\",\n scenePreparationRepresentationBands\n ),\n gameplayImportance: assertScenePreparationEnum(\n `${chunkLabel}.gameplayImportance`,\n chunk.gameplayImportance ?? \"medium\",\n Object.keys(scenePreparationImportanceWeights)\n ),\n visible: chunk.visible !== false,\n playerRelevant: chunk.playerRelevant === true,\n imageCritical: chunk.imageCritical === true,\n stages: normalizeScenePreparationStages(chunk.stages, chunkLabel),\n });\n });\n\n const chunkIds = new Set();\n for (const chunk of normalizedChunks) {\n if (chunkIds.has(chunk.chunkId)) {\n throw new Error(`Duplicate scene-preparation chunk id detected: ${chunk.chunkId}`);\n }\n chunkIds.add(chunk.chunkId);\n }\n\n const jobs = [];\n for (const chunk of normalizedChunks) {\n const includedStages = new Set(chunk.stages);\n for (const stageFamily of chunk.stages) {\n const dependencies = collectScenePreparationDependencies(\n stageFamily,\n includedStages\n ).map(\n (dependency) =>\n `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${dependency}`\n );\n\n jobs.push(\n Object.freeze({\n id: `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${stageFamily}`,\n snapshotId,\n chunkId: chunk.chunkId,\n representationBand: chunk.representationBand,\n stageFamily,\n priority: buildScenePreparationPriority(chunk, stageFamily),\n dependencies: Object.freeze(dependencies),\n dependencyCount: dependencies.length,\n root: dependencies.length === 0,\n authority: \"visual\",\n mutatesSimulation: false,\n gameplayImportance: chunk.gameplayImportance,\n visible: chunk.visible,\n playerRelevant: chunk.playerRelevant,\n imageCritical: chunk.imageCritical,\n })\n );\n }\n }\n\n const jobById = new Map(jobs.map((job) => [job.id, job]));\n let crossChunkDependencyCount = 0;\n let localJoinCount = 0;\n\n const finalizedJobs = Object.freeze(\n jobs.map((job) => {\n const dependents = jobs\n .filter((candidate) => candidate.dependencies.includes(job.id))\n .map((candidate) => candidate.id);\n const crossChunkDependencies = job.dependencies.filter((dependency) => {\n const parent = jobById.get(dependency);\n return parent && parent.chunkId !== job.chunkId;\n });\n crossChunkDependencyCount += crossChunkDependencies.length;\n if (\n job.dependencies.length > 1 &&\n crossChunkDependencies.length === 0\n ) {\n localJoinCount += 1;\n }\n\n return Object.freeze({\n ...job,\n dependents: Object.freeze(dependents),\n dependentCount: dependents.length,\n unresolvedDependencyCount: job.dependencies.length,\n localJoin:\n job.dependencies.length > 1 && crossChunkDependencies.length === 0,\n });\n })\n );\n\n const graph = Object.freeze({\n schedulerMode: \"dag\",\n jobCount: finalizedJobs.length,\n chunkCount: normalizedChunks.length,\n chunkIds: Object.freeze(normalizedChunks.map((chunk) => chunk.chunkId)),\n representationBands: Object.freeze(\n [...new Set(normalizedChunks.map((chunk) => chunk.representationBand))]\n ),\n roots: Object.freeze(\n finalizedJobs.filter((job) => job.root).map((job) => job.id)\n ),\n chunkRoots: Object.freeze(\n Object.fromEntries(\n normalizedChunks.map((chunk) => [\n chunk.chunkId,\n finalizedJobs\n .filter((job) => job.chunkId === chunk.chunkId && job.root)\n .map((job) => job.id),\n ])\n )\n ),\n topologicalOrder: buildScenePreparationTopologicalOrder(finalizedJobs),\n priorityLanes: buildScenePreparationPriorityLanes(finalizedJobs),\n localJoinCount,\n crossChunkDependencyCount,\n });\n\n return Object.freeze({\n schemaVersion: 1,\n owner: \"scene-preparation\",\n schedulerMode: \"dag\",\n snapshotId,\n jobs: finalizedJobs,\n graph,\n });\n}\n"],"mappings":"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","names":["source"]}
{
"name": "@plasius/gpu-worker",
"version": "0.1.10",
"version": "0.1.11",
"description": "WebGPU worker runtime with a lock-free job queue for WGSL workloads.",

@@ -5,0 +5,0 @@ "type": "module",

@@ -161,2 +161,35 @@ # @plasius/gpu-worker

`@plasius/gpu-worker` also now exposes a scene-preparation manifest helper for
snapshot-driven chunk DAG planning:
```js
import { createScenePreparationManifest } from "@plasius/gpu-worker";
const manifest = createScenePreparationManifest({
snapshotId: "visual-snapshot-42",
chunks: [
{
chunkId: "chunk-near-0",
representationBand: "near",
gameplayImportance: "critical",
visible: true,
playerRelevant: true,
},
{
chunkId: "chunk-far-3",
representationBand: "far",
gameplayImportance: "medium",
visible: false,
},
],
});
console.log(manifest.graph.chunkRoots);
console.log(manifest.graph.priorityLanes[0]);
```
The helper publishes one chunk-local DAG per stable snapshot, keeps joins local
to chunk stage boundaries, and rejects render-preparation manifests that try to
mutate authoritative simulation state.
## What this is

@@ -163,0 +196,0 @@ - A minimal GPU worker layer that combines a lock-free queue with user WGSL jobs.

@@ -730,1 +730,380 @@ import {

}
export const scenePreparationRepresentationBands = Object.freeze([
"near",
"mid",
"far",
"horizon",
]);
export const scenePreparationStageFamilies = Object.freeze([
"snapshotSelection",
"transformPropagation",
"animationPose",
"proceduralAnimation",
"skinningOrDeformation",
"boundsUpdate",
"lodSelection",
"rtRepresentationSelection",
"visibility",
"lightAssignment",
"renderProxyBuild",
"rtInstancePreparation",
]);
const scenePreparationDefaultStageDependencies = Object.freeze({
snapshotSelection: Object.freeze([]),
transformPropagation: Object.freeze(["snapshotSelection"]),
animationPose: Object.freeze(["transformPropagation"]),
proceduralAnimation: Object.freeze(["animationPose"]),
skinningOrDeformation: Object.freeze([
"animationPose",
"proceduralAnimation",
]),
boundsUpdate: Object.freeze(["skinningOrDeformation"]),
lodSelection: Object.freeze(["boundsUpdate"]),
rtRepresentationSelection: Object.freeze(["lodSelection"]),
visibility: Object.freeze(["boundsUpdate", "lodSelection"]),
lightAssignment: Object.freeze(["visibility"]),
renderProxyBuild: Object.freeze(["visibility", "lodSelection"]),
rtInstancePreparation: Object.freeze([
"visibility",
"rtRepresentationSelection",
]),
});
const scenePreparationBandPriorityWeights = Object.freeze({
near: 400,
mid: 300,
far: 200,
horizon: 100,
});
const scenePreparationImportanceWeights = Object.freeze({
low: 0,
medium: 15,
high: 30,
critical: 60,
});
const scenePreparationStagePriorityWeights = Object.freeze({
snapshotSelection: 60,
transformPropagation: 54,
animationPose: 50,
proceduralAnimation: 46,
skinningOrDeformation: 42,
boundsUpdate: 38,
lodSelection: 32,
rtRepresentationSelection: 28,
visibility: 34,
lightAssignment: 24,
renderProxyBuild: 22,
rtInstancePreparation: 26,
});
function assertScenePreparationIdentifier(name, value) {
if (typeof value !== "string" || value.trim().length === 0) {
throw new Error(`${name} must be a non-empty string.`);
}
return value.trim();
}
function assertScenePreparationEnum(name, value, allowed) {
const normalized = assertScenePreparationIdentifier(name, value);
if (!allowed.includes(normalized)) {
throw new Error(`${name} must be one of: ${allowed.join(", ")}.`);
}
return normalized;
}
function normalizeScenePreparationStages(stages, chunkLabel) {
const requested =
stages === undefined ? scenePreparationStageFamilies : stages;
if (!Array.isArray(requested) || requested.length === 0) {
throw new Error(`${chunkLabel}.stages must be a non-empty array when provided.`);
}
const normalized = [...new Set(
requested.map((stage, index) =>
assertScenePreparationEnum(
`${chunkLabel}.stages[${index}]`,
stage,
scenePreparationStageFamilies
)
)
)];
return normalized.sort(
(left, right) =>
scenePreparationStageFamilies.indexOf(left) -
scenePreparationStageFamilies.indexOf(right)
);
}
function collectScenePreparationDependencies(
stageFamily,
includedStages,
seen = new Set()
) {
const dependencies =
scenePreparationDefaultStageDependencies[stageFamily] ?? [];
for (const dependency of dependencies) {
if (includedStages.has(dependency)) {
seen.add(dependency);
continue;
}
collectScenePreparationDependencies(dependency, includedStages, seen);
}
return [...seen].sort(
(left, right) =>
scenePreparationStageFamilies.indexOf(left) -
scenePreparationStageFamilies.indexOf(right)
);
}
function buildScenePreparationPriority(chunk, stageFamily) {
const bandWeight =
scenePreparationBandPriorityWeights[chunk.representationBand] ?? 0;
const importanceWeight =
scenePreparationImportanceWeights[chunk.gameplayImportance] ?? 0;
const stageWeight =
scenePreparationStagePriorityWeights[stageFamily] ?? 0;
return (
bandWeight +
importanceWeight +
stageWeight +
(chunk.visible ? 20 : 0) +
(chunk.playerRelevant ? 20 : 0) +
(chunk.imageCritical ? 15 : 0)
);
}
function buildScenePreparationPriorityLanes(jobs) {
const lanes = new Map();
for (const job of jobs) {
const lane = lanes.get(job.priority) ?? {
priority: job.priority,
jobIds: [],
chunkIds: [],
};
lane.jobIds.push(job.id);
if (!lane.chunkIds.includes(job.chunkId)) {
lane.chunkIds.push(job.chunkId);
}
lanes.set(job.priority, lane);
}
return Object.freeze(
[...lanes.values()]
.sort((left, right) => right.priority - left.priority)
.map((lane) =>
Object.freeze({
priority: lane.priority,
jobIds: Object.freeze([...lane.jobIds]),
chunkIds: Object.freeze([...lane.chunkIds]),
jobCount: lane.jobIds.length,
})
)
);
}
function buildScenePreparationTopologicalOrder(jobs) {
const indegree = new Map(jobs.map((job) => [job.id, job.dependencies.length]));
const dependentsById = new Map(jobs.map((job) => [job.id, []]));
for (const job of jobs) {
for (const dependency of job.dependencies) {
dependentsById.get(dependency)?.push(job.id);
}
}
const queue = jobs
.filter((job) => job.dependencies.length === 0)
.sort((left, right) => right.priority - left.priority)
.map((job) => job.id);
const jobById = new Map(jobs.map((job) => [job.id, job]));
const order = [];
while (queue.length > 0) {
const currentId = queue.shift();
if (!currentId) {
continue;
}
order.push(currentId);
const unlocked = [];
for (const dependentId of dependentsById.get(currentId) ?? []) {
const next = (indegree.get(dependentId) ?? 0) - 1;
indegree.set(dependentId, next);
if (next === 0) {
unlocked.push(dependentId);
}
}
unlocked
.sort(
(left, right) =>
(jobById.get(right)?.priority ?? 0) -
(jobById.get(left)?.priority ?? 0)
)
.forEach((jobId) => {
queue.push(jobId);
});
}
if (order.length !== jobs.length) {
throw new Error("Scene-preparation manifest contains a cycle.");
}
return Object.freeze(order);
}
export function createScenePreparationManifest(options = {}) {
const snapshotId = assertScenePreparationIdentifier(
"snapshotId",
options.snapshotId
);
const chunkEntries = Array.isArray(options.chunks) ? options.chunks : [];
if (chunkEntries.length === 0) {
throw new Error("createScenePreparationManifest requires at least one chunk.");
}
const normalizedChunks = chunkEntries.map((chunk, index) => {
if (!chunk || typeof chunk !== "object" || Array.isArray(chunk)) {
throw new Error(`chunks[${index}] must be an object.`);
}
const chunkLabel = `chunks[${index}]`;
if (chunk.mutatesSimulation === true) {
throw new Error(
`${chunkLabel}.mutatesSimulation cannot be true for render preparation.`
);
}
return Object.freeze({
chunkId: assertScenePreparationIdentifier(`${chunkLabel}.chunkId`, chunk.chunkId),
representationBand: assertScenePreparationEnum(
`${chunkLabel}.representationBand`,
chunk.representationBand ?? "mid",
scenePreparationRepresentationBands
),
gameplayImportance: assertScenePreparationEnum(
`${chunkLabel}.gameplayImportance`,
chunk.gameplayImportance ?? "medium",
Object.keys(scenePreparationImportanceWeights)
),
visible: chunk.visible !== false,
playerRelevant: chunk.playerRelevant === true,
imageCritical: chunk.imageCritical === true,
stages: normalizeScenePreparationStages(chunk.stages, chunkLabel),
});
});
const chunkIds = new Set();
for (const chunk of normalizedChunks) {
if (chunkIds.has(chunk.chunkId)) {
throw new Error(`Duplicate scene-preparation chunk id detected: ${chunk.chunkId}`);
}
chunkIds.add(chunk.chunkId);
}
const jobs = [];
for (const chunk of normalizedChunks) {
const includedStages = new Set(chunk.stages);
for (const stageFamily of chunk.stages) {
const dependencies = collectScenePreparationDependencies(
stageFamily,
includedStages
).map(
(dependency) =>
`${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${dependency}`
);
jobs.push(
Object.freeze({
id: `${snapshotId}:${chunk.chunkId}:${chunk.representationBand}:${stageFamily}`,
snapshotId,
chunkId: chunk.chunkId,
representationBand: chunk.representationBand,
stageFamily,
priority: buildScenePreparationPriority(chunk, stageFamily),
dependencies: Object.freeze(dependencies),
dependencyCount: dependencies.length,
root: dependencies.length === 0,
authority: "visual",
mutatesSimulation: false,
gameplayImportance: chunk.gameplayImportance,
visible: chunk.visible,
playerRelevant: chunk.playerRelevant,
imageCritical: chunk.imageCritical,
})
);
}
}
const jobById = new Map(jobs.map((job) => [job.id, job]));
let crossChunkDependencyCount = 0;
let localJoinCount = 0;
const finalizedJobs = Object.freeze(
jobs.map((job) => {
const dependents = jobs
.filter((candidate) => candidate.dependencies.includes(job.id))
.map((candidate) => candidate.id);
const crossChunkDependencies = job.dependencies.filter((dependency) => {
const parent = jobById.get(dependency);
return parent && parent.chunkId !== job.chunkId;
});
crossChunkDependencyCount += crossChunkDependencies.length;
if (
job.dependencies.length > 1 &&
crossChunkDependencies.length === 0
) {
localJoinCount += 1;
}
return Object.freeze({
...job,
dependents: Object.freeze(dependents),
dependentCount: dependents.length,
unresolvedDependencyCount: job.dependencies.length,
localJoin:
job.dependencies.length > 1 && crossChunkDependencies.length === 0,
});
})
);
const graph = Object.freeze({
schedulerMode: "dag",
jobCount: finalizedJobs.length,
chunkCount: normalizedChunks.length,
chunkIds: Object.freeze(normalizedChunks.map((chunk) => chunk.chunkId)),
representationBands: Object.freeze(
[...new Set(normalizedChunks.map((chunk) => chunk.representationBand))]
),
roots: Object.freeze(
finalizedJobs.filter((job) => job.root).map((job) => job.id)
),
chunkRoots: Object.freeze(
Object.fromEntries(
normalizedChunks.map((chunk) => [
chunk.chunkId,
finalizedJobs
.filter((job) => job.chunkId === chunk.chunkId && job.root)
.map((job) => job.id),
])
)
),
topologicalOrder: buildScenePreparationTopologicalOrder(finalizedJobs),
priorityLanes: buildScenePreparationPriorityLanes(finalizedJobs),
localJoinCount,
crossChunkDependencyCount,
});
return Object.freeze({
schemaVersion: 1,
owner: "scene-preparation",
schedulerMode: "dag",
snapshotId,
jobs: finalizedJobs,
graph,
});
}