@motion-core/motion-gpu 0.4.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +99 -0
  2. package/dist/advanced.js +3 -1
  3. package/dist/core/advanced.js +3 -1
  4. package/dist/core/compute-shader.d.ts +87 -0
  5. package/dist/core/compute-shader.d.ts.map +1 -0
  6. package/dist/core/compute-shader.js +205 -0
  7. package/dist/core/compute-shader.js.map +1 -0
  8. package/dist/core/error-report.d.ts +1 -1
  9. package/dist/core/error-report.d.ts.map +1 -1
  10. package/dist/core/error-report.js +63 -0
  11. package/dist/core/error-report.js.map +1 -1
  12. package/dist/core/frame-registry.d.ts.map +1 -1
  13. package/dist/core/frame-registry.js +1 -1
  14. package/dist/core/frame-registry.js.map +1 -1
  15. package/dist/core/index.d.ts +5 -2
  16. package/dist/core/index.d.ts.map +1 -1
  17. package/dist/core/index.js +3 -1
  18. package/dist/core/material-preprocess.d.ts.map +1 -1
  19. package/dist/core/material-preprocess.js +5 -3
  20. package/dist/core/material-preprocess.js.map +1 -1
  21. package/dist/core/material.d.ts +22 -6
  22. package/dist/core/material.d.ts.map +1 -1
  23. package/dist/core/material.js +30 -3
  24. package/dist/core/material.js.map +1 -1
  25. package/dist/core/render-graph.d.ts +7 -3
  26. package/dist/core/render-graph.d.ts.map +1 -1
  27. package/dist/core/render-graph.js +22 -6
  28. package/dist/core/render-graph.js.map +1 -1
  29. package/dist/core/renderer.d.ts.map +1 -1
  30. package/dist/core/renderer.js +418 -23
  31. package/dist/core/renderer.js.map +1 -1
  32. package/dist/core/runtime-loop.d.ts +2 -2
  33. package/dist/core/runtime-loop.d.ts.map +1 -1
  34. package/dist/core/runtime-loop.js +49 -1
  35. package/dist/core/runtime-loop.js.map +1 -1
  36. package/dist/core/shader.d.ts +9 -1
  37. package/dist/core/shader.d.ts.map +1 -1
  38. package/dist/core/shader.js +21 -2
  39. package/dist/core/shader.js.map +1 -1
  40. package/dist/core/storage-buffers.d.ts +37 -0
  41. package/dist/core/storage-buffers.d.ts.map +1 -0
  42. package/dist/core/storage-buffers.js +95 -0
  43. package/dist/core/storage-buffers.js.map +1 -0
  44. package/dist/core/texture-loader.d.ts.map +1 -1
  45. package/dist/core/texture-loader.js +4 -0
  46. package/dist/core/texture-loader.js.map +1 -1
  47. package/dist/core/textures.d.ts +12 -0
  48. package/dist/core/textures.d.ts.map +1 -1
  49. package/dist/core/textures.js +7 -2
  50. package/dist/core/textures.js.map +1 -1
  51. package/dist/core/types.d.ts +146 -4
  52. package/dist/core/types.d.ts.map +1 -1
  53. package/dist/index.js +3 -1
  54. package/dist/passes/ComputePass.d.ts +83 -0
  55. package/dist/passes/ComputePass.d.ts.map +1 -0
  56. package/dist/passes/ComputePass.js +92 -0
  57. package/dist/passes/ComputePass.js.map +1 -0
  58. package/dist/passes/PingPongComputePass.d.ts +104 -0
  59. package/dist/passes/PingPongComputePass.d.ts.map +1 -0
  60. package/dist/passes/PingPongComputePass.js +132 -0
  61. package/dist/passes/PingPongComputePass.js.map +1 -0
  62. package/dist/passes/ShaderPass.d.ts.map +1 -1
  63. package/dist/passes/ShaderPass.js +2 -1
  64. package/dist/passes/ShaderPass.js.map +1 -1
  65. package/dist/passes/index.d.ts +2 -0
  66. package/dist/passes/index.d.ts.map +1 -1
  67. package/dist/passes/index.js +3 -1
  68. package/dist/react/FragCanvas.d.ts +2 -2
  69. package/dist/react/FragCanvas.d.ts.map +1 -1
  70. package/dist/react/FragCanvas.js.map +1 -1
  71. package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -1
  72. package/dist/react/MotionGPUErrorOverlay.js +123 -20
  73. package/dist/react/MotionGPUErrorOverlay.js.map +1 -1
  74. package/dist/react/advanced.js +3 -1
  75. package/dist/react/index.d.ts +5 -2
  76. package/dist/react/index.d.ts.map +1 -1
  77. package/dist/react/index.js +3 -1
  78. package/dist/svelte/FragCanvas.svelte +2 -2
  79. package/dist/svelte/FragCanvas.svelte.d.ts +2 -2
  80. package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -1
  81. package/dist/svelte/MotionGPUErrorOverlay.svelte +137 -7
  82. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -1
  83. package/dist/svelte/advanced.js +3 -1
  84. package/dist/svelte/index.d.ts +5 -2
  85. package/dist/svelte/index.d.ts.map +1 -1
  86. package/dist/svelte/index.js +3 -1
  87. package/package.json +1 -1
  88. package/src/lib/core/compute-shader.ts +326 -0
  89. package/src/lib/core/error-report.ts +129 -0
  90. package/src/lib/core/frame-registry.ts +2 -1
  91. package/src/lib/core/index.ts +18 -1
  92. package/src/lib/core/material-preprocess.ts +17 -6
  93. package/src/lib/core/material.ts +101 -20
  94. package/src/lib/core/render-graph.ts +39 -9
  95. package/src/lib/core/renderer.ts +655 -41
  96. package/src/lib/core/runtime-loop.ts +82 -3
  97. package/src/lib/core/shader.ts +45 -2
  98. package/src/lib/core/storage-buffers.ts +142 -0
  99. package/src/lib/core/texture-loader.ts +6 -0
  100. package/src/lib/core/textures.ts +24 -2
  101. package/src/lib/core/types.ts +165 -4
  102. package/src/lib/passes/ComputePass.ts +136 -0
  103. package/src/lib/passes/PingPongComputePass.ts +180 -0
  104. package/src/lib/passes/ShaderPass.ts +2 -1
  105. package/src/lib/passes/index.ts +6 -0
  106. package/src/lib/react/FragCanvas.tsx +3 -3
  107. package/src/lib/react/MotionGPUErrorOverlay.tsx +137 -5
  108. package/src/lib/react/index.ts +18 -1
  109. package/src/lib/svelte/FragCanvas.svelte +2 -2
  110. package/src/lib/svelte/MotionGPUErrorOverlay.svelte +137 -7
  111. package/src/lib/svelte/index.ts +18 -1
@@ -1 +1 @@
1
- {"version":3,"file":"error-report.js","names":[],"sources":["../../src/lib/core/error-report.ts"],"sourcesContent":["import {\n\tgetShaderCompilationDiagnostics,\n\ttype ShaderCompilationDiagnostic\n} from './error-diagnostics.js';\nimport { formatShaderSourceLocation } from './shader.js';\n\n/**\n * Runtime phase in which an error occurred.\n */\nexport type MotionGPUErrorPhase = 'initialization' | 'render';\n\n/**\n * Stable machine-readable error category code.\n */\nexport type MotionGPUErrorCode =\n\t| 'WEBGPU_UNAVAILABLE'\n\t| 'WEBGPU_ADAPTER_UNAVAILABLE'\n\t| 'WEBGPU_CONTEXT_UNAVAILABLE'\n\t| 'WGSL_COMPILATION_FAILED'\n\t| 'WEBGPU_DEVICE_LOST'\n\t| 'WEBGPU_UNCAPTURED_ERROR'\n\t| 'BIND_GROUP_MISMATCH'\n\t| 'TEXTURE_USAGE_INVALID'\n\t| 'TEXTURE_REQUEST_FAILED'\n\t| 'TEXTURE_DECODE_UNAVAILABLE'\n\t| 'TEXTURE_REQUEST_ABORTED'\n\t| 'MOTIONGPU_RUNTIME_ERROR';\n\n/**\n * Severity level for user-facing diagnostics.\n */\nexport type MotionGPUErrorSeverity = 'error' | 'fatal';\n\n/**\n * One source-code line displayed in diagnostics snippet.\n */\nexport interface MotionGPUErrorSourceLine {\n\tnumber: number;\n\tcode: string;\n\thighlight: boolean;\n}\n\n/**\n * Structured source context displayed for shader compilation errors.\n */\nexport interface MotionGPUErrorSource {\n\tcomponent: string;\n\tlocation: string;\n\tline: number;\n\tcolumn?: number;\n\tsnippet: MotionGPUErrorSourceLine[];\n}\n\n/**\n * Optional runtime context captured with diagnostics payload.\n */\nexport interface MotionGPUErrorContext {\n\tmaterialSignature?: string;\n\tpassGraph?: {\n\t\tpassCount: number;\n\t\tenabledPassCount: number;\n\t\tinputs: string[];\n\t\toutputs: string[];\n\t};\n\tactiveRenderTargets: string[];\n}\n\n/**\n * Structured error payload used by UI diagnostics.\n */\nexport interface MotionGPUErrorReport {\n\t/**\n\t * Stable machine-readable category code.\n\t */\n\tcode: MotionGPUErrorCode;\n\t/**\n\t * Severity level used by diagnostics UIs and telemetry.\n\t */\n\tseverity: MotionGPUErrorSeverity;\n\t/**\n\t * Whether runtime may recover without full renderer re-creation.\n\t */\n\trecoverable: boolean;\n\t/**\n\t * Short category title.\n\t */\n\ttitle: string;\n\t/**\n\t * Primary human-readable message.\n\t */\n\tmessage: string;\n\t/**\n\t * Suggested remediation hint.\n\t */\n\thint: string;\n\t/**\n\t * Additional parsed details (for example WGSL line errors).\n\t */\n\tdetails: string[];\n\t/**\n\t * Stack trace lines when available.\n\t */\n\tstack: string[];\n\t/**\n\t * Original unmodified message.\n\t */\n\trawMessage: string;\n\t/**\n\t * Runtime phase where the error occurred.\n\t */\n\tphase: MotionGPUErrorPhase;\n\t/**\n\t * Optional source context for shader-related diagnostics.\n\t */\n\tsource: MotionGPUErrorSource | null;\n\t/**\n\t * Optional runtime context snapshot (material/pass graph/render targets).\n\t */\n\tcontext: MotionGPUErrorContext | null;\n}\n\n/**\n * Splits multi-line values into trimmed non-empty lines.\n */\nfunction splitLines(value: string): string[] {\n\treturn value\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n}\n\nfunction toDisplayName(path: string): string {\n\tconst normalized = path.split(/[?#]/)[0] ?? path;\n\tconst chunks = normalized.split(/[\\\\/]/);\n\tconst last = chunks[chunks.length - 1];\n\treturn last && last.length > 0 ? last : path;\n}\n\nfunction toSnippet(source: string, line: number, radius = 3): MotionGPUErrorSourceLine[] {\n\tconst lines = source.replace(/\\r\\n?/g, '\\n').split('\\n');\n\tif (lines.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst targetLine = Math.min(Math.max(1, line), lines.length);\n\tconst start = Math.max(1, targetLine - radius);\n\tconst end = Math.min(lines.length, targetLine + radius);\n\tconst snippet: MotionGPUErrorSourceLine[] = [];\n\n\tfor (let index = start; index <= end; index += 1) {\n\t\tsnippet.push({\n\t\t\tnumber: index,\n\t\t\tcode: lines[index - 1] ?? '',\n\t\t\thighlight: index === targetLine\n\t\t});\n\t}\n\n\treturn snippet;\n}\n\nfunction buildSourceFromDiagnostics(error: unknown): MotionGPUErrorSource | null {\n\tconst diagnostics = getShaderCompilationDiagnostics(error);\n\tif (!diagnostics || diagnostics.diagnostics.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst primary = diagnostics.diagnostics.find((entry) => entry.sourceLocation !== null);\n\tif (!primary?.sourceLocation) {\n\t\treturn null;\n\t}\n\n\tconst location = primary.sourceLocation;\n\tconst column = primary.linePos && primary.linePos > 0 ? primary.linePos : undefined;\n\n\tif (location.kind === 'fragment') {\n\t\tconst component =\n\t\t\tdiagnostics.materialSource?.component ??\n\t\t\t(diagnostics.materialSource?.file\n\t\t\t\t? toDisplayName(diagnostics.materialSource.file)\n\t\t\t\t: 'User shader fragment');\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `fragment line ${location.line}`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(diagnostics.fragmentSource, location.line)\n\t\t};\n\t}\n\n\tif (location.kind === 'include') {\n\t\tconst includeName = location.include ?? 'unknown';\n\t\tconst includeSource = diagnostics.includeSources[includeName] ?? '';\n\t\tconst component = `#include <${includeName}>`;\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `include <${includeName}>`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(includeSource, location.line)\n\t\t};\n\t}\n\n\tconst defineName = location.define ?? 'unknown';\n\tconst defineLine = Math.max(1, location.line);\n\tconst component = `#define ${defineName}`;\n\tconst locationLabel =\n\t\tformatShaderSourceLocation(location) ?? `define \"${defineName}\" line ${defineLine}`;\n\treturn {\n\t\tcomponent,\n\t\tlocation: `${component} (${locationLabel})`,\n\t\tline: defineLine,\n\t\t...(column !== undefined ? { column } : {}),\n\t\tsnippet: toSnippet(diagnostics.defineBlockSource ?? '', defineLine, 2)\n\t};\n}\n\nfunction formatDiagnosticMessage(entry: ShaderCompilationDiagnostic): string {\n\tconst sourceLabel = formatShaderSourceLocation(entry.sourceLocation);\n\tconst generatedLineLabel =\n\t\tentry.generatedLine > 0 ? `generated WGSL line ${entry.generatedLine}` : null;\n\tconst labels = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\tif (labels.length === 0) {\n\t\treturn entry.message;\n\t}\n\n\treturn `[${labels.join(' | ')}] ${entry.message}`;\n}\n\n/**\n * Maps known WebGPU/WGSL error patterns to a user-facing title and hint.\n */\nfunction classifyErrorMessage(\n\tmessage: string\n): Pick<MotionGPUErrorReport, 'code' | 'severity' | 'recoverable' | 'title' | 'hint'> {\n\tif (message.includes('WebGPU is not available in this browser')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU unavailable',\n\t\t\thint: 'Use a browser with WebGPU enabled (latest Chrome/Edge/Safari TP) and secure context.'\n\t\t};\n\t}\n\n\tif (message.includes('Unable to acquire WebGPU adapter')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_ADAPTER_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU adapter unavailable',\n\t\t\thint: 'GPU adapter request failed. Check browser permissions, flags and device support.'\n\t\t};\n\t}\n\n\tif (message.includes('Canvas does not support webgpu context')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_CONTEXT_UNAVAILABLE',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Canvas cannot create WebGPU context',\n\t\t\thint: 'Make sure this canvas is attached to DOM and not using an unsupported context option.'\n\t\t};\n\t}\n\n\tif (message.includes('WGSL compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'WGSL_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WGSL compilation failed',\n\t\t\thint: 'Check WGSL line numbers below and verify struct/binding/function signatures.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU device lost') || message.includes('Device Lost')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_DEVICE_LOST',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU device lost',\n\t\t\thint: 'GPU device/context was lost. Recreate the renderer and check OS/GPU stability.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU uncaptured error')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNCAPTURED_ERROR',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WebGPU uncaptured error',\n\t\t\thint: 'A GPU command failed asynchronously. Review details and validate resource/state usage.'\n\t\t};\n\t}\n\n\tif (message.includes('CreateBindGroup') || message.includes('bind group layout')) {\n\t\treturn {\n\t\t\tcode: 'BIND_GROUP_MISMATCH',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Bind group mismatch',\n\t\t\thint: 'Bindings in shader and runtime resources are out of sync. Verify uniforms/textures layout.'\n\t\t};\n\t}\n\n\tif (message.includes('Destination texture needs to have CopyDst')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_USAGE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Invalid texture usage flags',\n\t\t\thint: 'Texture used as upload destination must include CopyDst (and often RenderAttachment).'\n\t\t};\n\t}\n\n\tif (message.includes('Texture request failed')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request failed',\n\t\t\thint: 'Verify texture URL, CORS policy and response status before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('createImageBitmap is not available in this runtime')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_DECODE_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'Texture decode unavailable',\n\t\t\thint: 'Runtime lacks createImageBitmap support. Use a browser/runtime with image bitmap decoding.'\n\t\t};\n\t}\n\n\tif (message.toLowerCase().includes('texture request was aborted')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_ABORTED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request aborted',\n\t\t\thint: 'Texture load was cancelled. Retry the request when source inputs stabilize.'\n\t\t};\n\t}\n\n\treturn {\n\t\tcode: 'MOTIONGPU_RUNTIME_ERROR',\n\t\tseverity: 'error',\n\t\trecoverable: true,\n\t\ttitle: 'MotionGPU render error',\n\t\thint: 'Review technical details below. If issue persists, isolate shader/uniform/texture changes.'\n\t};\n}\n\n/**\n * Converts unknown errors to a consistent, display-ready error report.\n *\n * @param error - Unknown thrown value.\n * @param phase - Phase during which error occurred.\n * @returns Normalized error report.\n */\nexport function toMotionGPUErrorReport(\n\terror: unknown,\n\tphase: MotionGPUErrorPhase\n): MotionGPUErrorReport {\n\tconst shaderDiagnostics = getShaderCompilationDiagnostics(error);\n\tconst rawMessage =\n\t\terror instanceof Error\n\t\t\t? error.message\n\t\t\t: typeof error === 'string'\n\t\t\t\t? error\n\t\t\t\t: 'Unknown FragCanvas error';\n\tconst rawLines = splitLines(rawMessage);\n\tconst defaultMessage = rawLines[0] ?? rawMessage;\n\tconst defaultDetails = rawLines.slice(1);\n\tconst source = buildSourceFromDiagnostics(error);\n\tconst context = shaderDiagnostics?.runtimeContext ?? null;\n\tconst message =\n\t\tshaderDiagnostics && shaderDiagnostics.diagnostics[0]\n\t\t\t? formatDiagnosticMessage(shaderDiagnostics.diagnostics[0])\n\t\t\t: defaultMessage;\n\tconst details = shaderDiagnostics\n\t\t? shaderDiagnostics.diagnostics.slice(1).map((entry) => formatDiagnosticMessage(entry))\n\t\t: defaultDetails;\n\tconst stack =\n\t\terror instanceof Error && error.stack\n\t\t\t? splitLines(error.stack).filter((line) => line !== message)\n\t\t\t: [];\n\tconst classification = classifyErrorMessage(rawMessage);\n\n\treturn {\n\t\tcode: classification.code,\n\t\tseverity: classification.severity,\n\t\trecoverable: classification.recoverable,\n\t\ttitle: classification.title,\n\t\tmessage,\n\t\thint: classification.hint,\n\t\tdetails,\n\t\tstack,\n\t\trawMessage,\n\t\tphase,\n\t\tsource,\n\t\tcontext\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"error-report.js","names":[],"sources":["../../src/lib/core/error-report.ts"],"sourcesContent":["import {\n\tgetShaderCompilationDiagnostics,\n\ttype ShaderCompilationDiagnostic\n} from './error-diagnostics.js';\nimport { formatShaderSourceLocation } from './shader.js';\n\n/**\n * Runtime phase in which an error occurred.\n */\nexport type MotionGPUErrorPhase = 'initialization' | 'render';\n\n/**\n * Stable machine-readable error category code.\n */\nexport type MotionGPUErrorCode =\n\t| 'WEBGPU_UNAVAILABLE'\n\t| 'WEBGPU_ADAPTER_UNAVAILABLE'\n\t| 'WEBGPU_CONTEXT_UNAVAILABLE'\n\t| 'WGSL_COMPILATION_FAILED'\n\t| 'MATERIAL_PREPROCESS_FAILED'\n\t| 'WEBGPU_DEVICE_LOST'\n\t| 'WEBGPU_UNCAPTURED_ERROR'\n\t| 'BIND_GROUP_MISMATCH'\n\t| 'RUNTIME_RESOURCE_MISSING'\n\t| 'UNIFORM_VALUE_INVALID'\n\t| 'STORAGE_BUFFER_OUT_OF_BOUNDS'\n\t| 'STORAGE_BUFFER_READ_FAILED'\n\t| 'RENDER_GRAPH_INVALID'\n\t| 'PINGPONG_CONFIGURATION_INVALID'\n\t| 'TEXTURE_USAGE_INVALID'\n\t| 'TEXTURE_REQUEST_FAILED'\n\t| 'TEXTURE_DECODE_UNAVAILABLE'\n\t| 'TEXTURE_REQUEST_ABORTED'\n\t| 'COMPUTE_COMPILATION_FAILED'\n\t| 'COMPUTE_CONTRACT_INVALID'\n\t| 'MOTIONGPU_RUNTIME_ERROR';\n\n/**\n * Severity level for user-facing diagnostics.\n */\nexport type MotionGPUErrorSeverity = 'error' | 'fatal';\n\n/**\n * One source-code line displayed in diagnostics snippet.\n */\nexport interface MotionGPUErrorSourceLine {\n\tnumber: number;\n\tcode: string;\n\thighlight: boolean;\n}\n\n/**\n * Structured source context displayed for shader compilation errors.\n */\nexport interface MotionGPUErrorSource {\n\tcomponent: string;\n\tlocation: string;\n\tline: number;\n\tcolumn?: number;\n\tsnippet: MotionGPUErrorSourceLine[];\n}\n\n/**\n * Optional runtime context captured with diagnostics payload.\n */\nexport interface MotionGPUErrorContext {\n\tmaterialSignature?: string;\n\tpassGraph?: {\n\t\tpassCount: number;\n\t\tenabledPassCount: number;\n\t\tinputs: string[];\n\t\toutputs: string[];\n\t};\n\tactiveRenderTargets: string[];\n}\n\n/**\n * Structured error payload used by UI diagnostics.\n */\nexport interface MotionGPUErrorReport {\n\t/**\n\t * Stable machine-readable category code.\n\t */\n\tcode: MotionGPUErrorCode;\n\t/**\n\t * Severity level used by diagnostics UIs and telemetry.\n\t */\n\tseverity: MotionGPUErrorSeverity;\n\t/**\n\t * Whether runtime may recover without full renderer re-creation.\n\t */\n\trecoverable: boolean;\n\t/**\n\t * Short category title.\n\t */\n\ttitle: string;\n\t/**\n\t * Primary human-readable message.\n\t */\n\tmessage: string;\n\t/**\n\t * Suggested remediation hint.\n\t */\n\thint: string;\n\t/**\n\t * Additional parsed details (for example WGSL line errors).\n\t */\n\tdetails: string[];\n\t/**\n\t * Stack trace lines when available.\n\t */\n\tstack: string[];\n\t/**\n\t * Original unmodified message.\n\t */\n\trawMessage: string;\n\t/**\n\t * Runtime phase where the error occurred.\n\t */\n\tphase: MotionGPUErrorPhase;\n\t/**\n\t * Optional source context for shader-related diagnostics.\n\t */\n\tsource: MotionGPUErrorSource | null;\n\t/**\n\t * Optional runtime context snapshot (material/pass graph/render targets).\n\t */\n\tcontext: MotionGPUErrorContext | null;\n}\n\n/**\n * Splits multi-line values into trimmed non-empty lines.\n */\nfunction splitLines(value: string): string[] {\n\treturn value\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0);\n}\n\nfunction toDisplayName(path: string): string {\n\tconst normalized = path.split(/[?#]/)[0] ?? path;\n\tconst chunks = normalized.split(/[\\\\/]/);\n\tconst last = chunks[chunks.length - 1];\n\treturn last && last.length > 0 ? last : path;\n}\n\nfunction toSnippet(source: string, line: number, radius = 3): MotionGPUErrorSourceLine[] {\n\tconst lines = source.replace(/\\r\\n?/g, '\\n').split('\\n');\n\tif (lines.length === 0) {\n\t\treturn [];\n\t}\n\n\tconst targetLine = Math.min(Math.max(1, line), lines.length);\n\tconst start = Math.max(1, targetLine - radius);\n\tconst end = Math.min(lines.length, targetLine + radius);\n\tconst snippet: MotionGPUErrorSourceLine[] = [];\n\n\tfor (let index = start; index <= end; index += 1) {\n\t\tsnippet.push({\n\t\t\tnumber: index,\n\t\t\tcode: lines[index - 1] ?? '',\n\t\t\thighlight: index === targetLine\n\t\t});\n\t}\n\n\treturn snippet;\n}\n\nfunction buildSourceFromDiagnostics(error: unknown): MotionGPUErrorSource | null {\n\tconst diagnostics = getShaderCompilationDiagnostics(error);\n\tif (!diagnostics || diagnostics.diagnostics.length === 0) {\n\t\treturn null;\n\t}\n\n\tconst primary = diagnostics.diagnostics.find((entry) => entry.sourceLocation !== null);\n\tif (!primary?.sourceLocation) {\n\t\treturn null;\n\t}\n\n\tconst location = primary.sourceLocation;\n\tconst column = primary.linePos && primary.linePos > 0 ? primary.linePos : undefined;\n\n\tif (location.kind === 'fragment') {\n\t\tconst component =\n\t\t\tdiagnostics.materialSource?.component ??\n\t\t\t(diagnostics.materialSource?.file\n\t\t\t\t? toDisplayName(diagnostics.materialSource.file)\n\t\t\t\t: 'User shader fragment');\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `fragment line ${location.line}`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(diagnostics.fragmentSource, location.line)\n\t\t};\n\t}\n\n\tif (location.kind === 'include') {\n\t\tconst includeName = location.include ?? 'unknown';\n\t\tconst includeSource = diagnostics.includeSources[includeName] ?? '';\n\t\tconst component = `#include <${includeName}>`;\n\t\tconst locationLabel = formatShaderSourceLocation(location) ?? `include <${includeName}>`;\n\t\treturn {\n\t\t\tcomponent,\n\t\t\tlocation: `${component} (${locationLabel})`,\n\t\t\tline: location.line,\n\t\t\t...(column !== undefined ? { column } : {}),\n\t\t\tsnippet: toSnippet(includeSource, location.line)\n\t\t};\n\t}\n\n\tconst defineName = location.define ?? 'unknown';\n\tconst defineLine = Math.max(1, location.line);\n\tconst component = `#define ${defineName}`;\n\tconst locationLabel =\n\t\tformatShaderSourceLocation(location) ?? `define \"${defineName}\" line ${defineLine}`;\n\treturn {\n\t\tcomponent,\n\t\tlocation: `${component} (${locationLabel})`,\n\t\tline: defineLine,\n\t\t...(column !== undefined ? { column } : {}),\n\t\tsnippet: toSnippet(diagnostics.defineBlockSource ?? '', defineLine, 2)\n\t};\n}\n\nfunction formatDiagnosticMessage(entry: ShaderCompilationDiagnostic): string {\n\tconst sourceLabel = formatShaderSourceLocation(entry.sourceLocation);\n\tconst generatedLineLabel =\n\t\tentry.generatedLine > 0 ? `generated WGSL line ${entry.generatedLine}` : null;\n\tconst labels = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\tif (labels.length === 0) {\n\t\treturn entry.message;\n\t}\n\n\treturn `[${labels.join(' | ')}] ${entry.message}`;\n}\n\n/**\n * Maps known WebGPU/WGSL error patterns to a user-facing title and hint.\n */\nfunction classifyErrorMessage(\n\tmessage: string\n): Pick<MotionGPUErrorReport, 'code' | 'severity' | 'recoverable' | 'title' | 'hint'> {\n\tif (message.includes('WebGPU is not available in this browser')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU unavailable',\n\t\t\thint: 'Use a browser with WebGPU enabled (latest Chrome/Edge/Safari TP) and secure context.'\n\t\t};\n\t}\n\n\tif (message.includes('Unable to acquire WebGPU adapter')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_ADAPTER_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU adapter unavailable',\n\t\t\thint: 'GPU adapter request failed. Check browser permissions, flags and device support.'\n\t\t};\n\t}\n\n\tif (message.includes('Canvas does not support webgpu context')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_CONTEXT_UNAVAILABLE',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Canvas cannot create WebGPU context',\n\t\t\thint: 'Make sure this canvas is attached to DOM and not using an unsupported context option.'\n\t\t};\n\t}\n\n\tif (message.includes('WGSL compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'WGSL_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WGSL compilation failed',\n\t\t\thint: 'Check WGSL line numbers below and verify struct/binding/function signatures.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Invalid include directive in fragment shader.') ||\n\t\tmessage.includes('Unknown include \"') ||\n\t\tmessage.includes('Circular include detected for \"') ||\n\t\tmessage.includes('Invalid define value for \"') ||\n\t\tmessage.includes('Invalid include \"')\n\t) {\n\t\treturn {\n\t\t\tcode: 'MATERIAL_PREPROCESS_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Material preprocess failed',\n\t\t\thint: 'Validate #include keys, define values and include expansion order before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('Compute shader compilation failed')) {\n\t\treturn {\n\t\t\tcode: 'COMPUTE_COMPILATION_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute shader compilation failed',\n\t\t\thint: 'Check WGSL compute shader sources below and verify storage bindings.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes(\n\t\t\t'Compute shader must declare `@compute @workgroup_size(...) fn compute(...)`.'\n\t\t) ||\n\t\tmessage.includes('Compute shader must include a `@builtin(global_invocation_id)` parameter.') ||\n\t\tmessage.includes('Could not extract @workgroup_size from compute shader source.') ||\n\t\tmessage.includes('@workgroup_size dimensions must be integers in range') ||\n\t\tmessage.includes('Unsupported storage buffer access mode \"')\n\t) {\n\t\treturn {\n\t\t\tcode: 'COMPUTE_CONTRACT_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Compute contract is invalid',\n\t\t\thint: 'Ensure compute shader contract (@compute, @workgroup_size, global_invocation_id, storage access) is valid.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU device lost') || message.includes('Device Lost')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_DEVICE_LOST',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'WebGPU device lost',\n\t\t\thint: 'GPU device/context was lost. Recreate the renderer and check OS/GPU stability.'\n\t\t};\n\t}\n\n\tif (message.includes('WebGPU uncaptured error')) {\n\t\treturn {\n\t\t\tcode: 'WEBGPU_UNCAPTURED_ERROR',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'WebGPU uncaptured error',\n\t\t\thint: 'A GPU command failed asynchronously. Review details and validate resource/state usage.'\n\t\t};\n\t}\n\n\tif (message.includes('CreateBindGroup') || message.includes('bind group layout')) {\n\t\treturn {\n\t\t\tcode: 'BIND_GROUP_MISMATCH',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Bind group mismatch',\n\t\t\thint: 'Bindings in shader and runtime resources are out of sync. Verify uniforms/textures layout.'\n\t\t};\n\t}\n\n\tif (message.includes('Storage buffer \"') && message.includes('write out of bounds:')) {\n\t\treturn {\n\t\t\tcode: 'STORAGE_BUFFER_OUT_OF_BOUNDS',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Storage buffer write out of bounds',\n\t\t\thint: 'Ensure offset + write byte length does not exceed declared storage buffer size.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Cannot read storage buffer \"') ||\n\t\tmessage.includes('Cannot read storage buffer: GPU device unavailable.') ||\n\t\tmessage.includes('not allocated on GPU.')\n\t) {\n\t\treturn {\n\t\t\tcode: 'STORAGE_BUFFER_READ_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Storage buffer read failed',\n\t\t\thint: 'Readbacks require an initialized renderer, allocated GPU buffer and active device.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Unknown uniform \"') ||\n\t\tmessage.includes('Unknown uniform type for \"') ||\n\t\tmessage.includes('Unknown texture \"') ||\n\t\tmessage.includes('Unknown storage buffer \"') ||\n\t\tmessage.includes('Missing definition for storage buffer \"') ||\n\t\tmessage.includes('Missing texture definition for \"') ||\n\t\t(message.includes('Storage buffer \"') && message.includes('\" not allocated.')) ||\n\t\t(message.includes('Storage texture \"') && message.includes('\" not allocated.'))\n\t) {\n\t\treturn {\n\t\t\tcode: 'RUNTIME_RESOURCE_MISSING',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Runtime resource binding failed',\n\t\t\thint: 'Check material declarations and runtime keys for uniforms, textures and storage resources.'\n\t\t};\n\t}\n\n\tif (message.includes('Uniform ') && message.includes(' value must')) {\n\t\treturn {\n\t\t\tcode: 'UNIFORM_VALUE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Uniform value is invalid',\n\t\t\thint: 'Provide finite values with tuple/matrix sizes matching the uniform type.'\n\t\t};\n\t}\n\n\tif (\n\t\tmessage.includes('Render pass #') ||\n\t\tmessage.includes('Render graph references unknown runtime target')\n\t) {\n\t\treturn {\n\t\t\tcode: 'RENDER_GRAPH_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Render graph configuration is invalid',\n\t\t\thint: 'Verify pass inputs/outputs, declared render targets and execution order.'\n\t\t};\n\t}\n\n\tif (message.includes('PingPongComputePass must provide a target texture key.')) {\n\t\treturn {\n\t\t\tcode: 'PINGPONG_CONFIGURATION_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Ping-pong compute pass is misconfigured',\n\t\t\thint: 'Configure a valid target texture key for PingPongComputePass.'\n\t\t};\n\t}\n\n\tif (message.includes('Destination texture needs to have CopyDst')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_USAGE_INVALID',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Invalid texture usage flags',\n\t\t\thint: 'Texture used as upload destination must include CopyDst (and often RenderAttachment).'\n\t\t};\n\t}\n\n\tif (message.includes('Texture request failed')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_FAILED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request failed',\n\t\t\thint: 'Verify texture URL, CORS policy and response status before retrying.'\n\t\t};\n\t}\n\n\tif (message.includes('createImageBitmap is not available in this runtime')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_DECODE_UNAVAILABLE',\n\t\t\tseverity: 'fatal',\n\t\t\trecoverable: false,\n\t\t\ttitle: 'Texture decode unavailable',\n\t\t\thint: 'Runtime lacks createImageBitmap support. Use a browser/runtime with image bitmap decoding.'\n\t\t};\n\t}\n\n\tif (message.toLowerCase().includes('texture request was aborted')) {\n\t\treturn {\n\t\t\tcode: 'TEXTURE_REQUEST_ABORTED',\n\t\t\tseverity: 'error',\n\t\t\trecoverable: true,\n\t\t\ttitle: 'Texture request aborted',\n\t\t\thint: 'Texture load was cancelled. Retry the request when source inputs stabilize.'\n\t\t};\n\t}\n\n\treturn {\n\t\tcode: 'MOTIONGPU_RUNTIME_ERROR',\n\t\tseverity: 'error',\n\t\trecoverable: true,\n\t\ttitle: 'MotionGPU render error',\n\t\thint: 'Review technical details below. If issue persists, isolate shader/uniform/texture changes.'\n\t};\n}\n\n/**\n * Converts unknown errors to a consistent, display-ready error report.\n *\n * @param error - Unknown thrown value.\n * @param phase - Phase during which error occurred.\n * @returns Normalized error report.\n */\nexport function toMotionGPUErrorReport(\n\terror: unknown,\n\tphase: MotionGPUErrorPhase\n): MotionGPUErrorReport {\n\tconst shaderDiagnostics = getShaderCompilationDiagnostics(error);\n\tconst rawMessage =\n\t\terror instanceof Error\n\t\t\t? error.message\n\t\t\t: typeof error === 'string'\n\t\t\t\t? error\n\t\t\t\t: 'Unknown FragCanvas error';\n\tconst rawLines = splitLines(rawMessage);\n\tconst defaultMessage = rawLines[0] ?? rawMessage;\n\tconst defaultDetails = rawLines.slice(1);\n\tconst source = buildSourceFromDiagnostics(error);\n\tconst context = shaderDiagnostics?.runtimeContext ?? null;\n\tconst message =\n\t\tshaderDiagnostics && shaderDiagnostics.diagnostics[0]\n\t\t\t? formatDiagnosticMessage(shaderDiagnostics.diagnostics[0])\n\t\t\t: defaultMessage;\n\tconst details = shaderDiagnostics\n\t\t? shaderDiagnostics.diagnostics.slice(1).map((entry) => formatDiagnosticMessage(entry))\n\t\t: defaultDetails;\n\tconst stack =\n\t\terror instanceof Error && error.stack\n\t\t\t? splitLines(error.stack).filter((line) => line !== message)\n\t\t\t: [];\n\tconst classification = classifyErrorMessage(rawMessage);\n\n\treturn {\n\t\tcode: classification.code,\n\t\tseverity: classification.severity,\n\t\trecoverable: classification.recoverable,\n\t\ttitle: classification.title,\n\t\tmessage,\n\t\thint: classification.hint,\n\t\tdetails,\n\t\tstack,\n\t\trawMessage,\n\t\tphase,\n\t\tsource,\n\t\tcontext\n\t};\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"frame-registry.d.ts","sourceRoot":"","sources":["../../src/lib/core/frame-registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"frame-registry.d.ts","sourceRoot":"","sources":["../../src/lib/core/frame-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+C,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EAAE,sBAAsB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAExD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;AAEvC;;GAEG;AACH,MAAM,WAAW,SAAS;IACzB,GAAG,EAAE,QAAQ,CAAC;IACd,KAAK,EAAE,QAAQ,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,GAAG,EAAE,QAAQ,CAAC;CACd;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;AAEnF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;OAEG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC;;;;OAIG;IACH,KAAK,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAC9B;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC;IAC3D;;OAEG;IACH,KAAK,CAAC,EAAE,CAAC,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC;IAC1D;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,MAAM,0BAA0B,GACnC,sBAAsB,GACtB,CAAC,MAAM,sBAAsB,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AAErD;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAC9B,OAAO,GACP,QAAQ,GACR;IACA,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,EAAE,0BAA0B,CAAC;CAClC,GACD;IACA,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,0BAA0B,CAAC;CACjC,CAAC;AAEL;;GAEG;AACH,MAAM,WAAW,cAAc;IAC9B;;OAEG;IACH,IAAI,EAAE,SAAS,CAAC;IAChB;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB;;OAEG;IACH,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,MAAM,EAAE,KAAK,CAAC;QACb,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CACb,MAAM,EACN;QACC,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KAC9B,CACD,CAAC;CACF;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,eAAe,GAAG,IAAI,CAAC;IAClC,KAAK,EAAE,gBAAgB,CAAC;IACxB,MAAM,EAAE,MAAM,CACb,MAAM,EACN;QACC,OAAO,EAAE,gBAAgB,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;KACxC,CACD,CAAC;CACF;AAED;;GAEG;AACH,UAAU,mBAAoB,SAAQ,cAAc;IACnD,WAAW,EAAE,MAAM,IAAI,CAAC;CACxB;AAwXD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC7B;;OAEG;IACH,QAAQ,EAAE,CACT,aAAa,EAAE,QAAQ,GAAG,aAAa,EACvC,iBAAiB,CAAC,EAAE,aAAa,GAAG,eAAe,EACnD,YAAY,CAAC,EAAE,eAAe,KAC1B,mBAAmB,CAAC;IACzB;;OAEG;IACH,GAAG,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACjC;;OAEG;IACH,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACrD;;OAEG;IACH,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB;;OAEG;IACH,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,aAAa,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C;;OAEG;IACH,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C;;OAEG;IACH,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC;;OAEG;IACH,mBAAmB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD;;OAEG;IACH,kBAAkB,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C;;OAEG;IACH,cAAc,EAAE,MAAM,IAAI,CAAC;IAC3B;;OAEG;IACH,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD;;OAEG;IACH,aAAa,EAAE,MAAM,UAAU,CAAC;IAChC;;OAEG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC;IAC7B;;OAEG;IACH,WAAW,EAAE,MAAM,MAAM,CAAC;IAC1B;;OAEG;IACH,mBAAmB,EAAE,MAAM,OAAO,CAAC;IACnC;;OAEG;IACH,kBAAkB,EAAE,MAAM,MAAM,CAAC;IACjC;;OAEG;IACH,oBAAoB,EAAE,MAAM,sBAAsB,GAAG,IAAI,CAAC;IAC1D;;OAEG;IACH,qBAAqB,EAAE,MAAM,OAAO,CAAC;IACrC;;OAEG;IACH,iBAAiB,EAAE,MAAM,eAAe,GAAG,IAAI,CAAC;IAChD;;OAEG;IACH,WAAW,EAAE,MAAM,qBAAqB,CAAC;IACzC;;OAEG;IACH,WAAW,EAAE,CACZ,GAAG,EAAE,QAAQ,EACb,OAAO,CAAC,EAAE;QACT,MAAM,CAAC,EAAE,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAC;QAC7D,KAAK,CAAC,EAAE,CAAC,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,GAAG,UAAU,CAAC,EAAE,CAAC;QAC5D,QAAQ,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;KACrC,KACG,UAAU,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,UAAU,GAAG,SAAS,CAAC;IACpD;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC7C,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC7B,GAAG,aAAa,CA6fhB"}
@@ -442,7 +442,7 @@ function createFrameRegistry(options) {
442
442
  stop,
443
443
  started: internalTask.startedStore,
444
444
  unsubscribe: () => {
445
- if (stage.tasks.delete(key)) markScheduleDirty();
445
+ if (stage.tasks.get(key) === internalTask && stage.tasks.delete(key)) markScheduleDirty();
446
446
  }
447
447
  };
448
448
  },
@@ -1 +1 @@
1
- {"version":3,"file":"frame-registry.js","names":[],"sources":["../../src/lib/core/frame-registry.ts"],"sourcesContent":["import { createCurrentWritable, type CurrentWritable, type Subscribable } from './current-value.js';\nimport type { FrameInvalidationToken, FrameState, RenderMode } from './types.js';\n\n/**\n * Per-frame callback executed by the frame scheduler.\n */\nexport type FrameCallback = (state: FrameState) => void;\n\n/**\n * Stable key type used to identify frame tasks and stages.\n */\nexport type FrameKey = string | symbol;\n\n/**\n * Public metadata describing a registered frame task.\n */\nexport interface FrameTask {\n\tkey: FrameKey;\n\tstage: FrameKey;\n}\n\n/**\n * Public metadata describing a frame stage.\n */\nexport interface FrameStage {\n\tkey: FrameKey;\n}\n\n/**\n * Stage callback allowing custom orchestration around task execution.\n */\nexport type FrameStageCallback = (state: FrameState, runTasks: () => void) => void;\n\n/**\n * Options controlling task registration and scheduling behavior.\n */\nexport interface UseFrameOptions {\n\t/**\n\t * Whether task starts in active state.\n\t *\n\t * @default true\n\t */\n\tautoStart?: boolean;\n\t/**\n\t * Whether task execution invalidates frame automatically.\n\t *\n\t * @default true\n\t */\n\tautoInvalidate?: boolean;\n\t/**\n\t * Explicit task invalidation policy.\n\t */\n\tinvalidation?: FrameTaskInvalidation;\n\t/**\n\t * Stage to register task in.\n\t *\n\t * If omitted, main stage is used unless inferred from task dependencies.\n\t */\n\tstage?: FrameKey | FrameStage;\n\t/**\n\t * Task dependencies that should run after this task.\n\t */\n\tbefore?: (FrameKey | FrameTask) | (FrameKey | FrameTask)[];\n\t/**\n\t * Task dependencies that should run before this task.\n\t */\n\tafter?: (FrameKey | FrameTask) | (FrameKey | FrameTask)[];\n\t/**\n\t * Dynamic predicate controlling whether the task is currently active.\n\t */\n\trunning?: () => boolean;\n}\n\n/**\n * Invalidation token value or resolver.\n */\nexport type FrameTaskInvalidationToken =\n\t| FrameInvalidationToken\n\t| (() => FrameInvalidationToken | null | undefined);\n\n/**\n * Explicit task invalidation policy.\n */\nexport type FrameTaskInvalidation =\n\t| 'never'\n\t| 'always'\n\t| {\n\t\t\tmode?: 'never' | 'always';\n\t\t\ttoken?: FrameTaskInvalidationToken;\n\t }\n\t| {\n\t\t\tmode: 'on-change';\n\t\t\ttoken: FrameTaskInvalidationToken;\n\t };\n\n/**\n * Handle returned by `useFrame` registration.\n */\nexport interface UseFrameResult {\n\t/**\n\t * Registered task metadata.\n\t */\n\ttask: FrameTask;\n\t/**\n\t * Starts task execution.\n\t */\n\tstart: () => void;\n\t/**\n\t * Stops task execution.\n\t */\n\tstop: () => void;\n\t/**\n\t * Readable flag representing effective running state.\n\t */\n\tstarted: Subscribable<boolean>;\n}\n\n/**\n * Snapshot of the resolved stage/task execution order.\n */\nexport interface FrameScheduleSnapshot {\n\tstages: Array<{\n\t\tkey: string;\n\t\ttasks: string[];\n\t}>;\n}\n\n/**\n * Optional scheduler diagnostics payload captured for the last run.\n */\nexport interface FrameRunTimings {\n\ttotal: number;\n\tstages: Record<\n\t\tstring,\n\t\t{\n\t\t\tduration: number;\n\t\t\ttasks: Record<string, number>;\n\t\t}\n\t>;\n}\n\n/**\n * Aggregated timing statistics for stage/task profiling.\n */\nexport interface FrameTimingStats {\n\tlast: number;\n\tavg: number;\n\tmin: number;\n\tmax: number;\n\tcount: number;\n}\n\n/**\n * Profiling snapshot aggregated from the configured history window.\n */\nexport interface FrameProfilingSnapshot {\n\twindow: number;\n\tframeCount: number;\n\tlastFrame: FrameRunTimings | null;\n\ttotal: FrameTimingStats;\n\tstages: Record<\n\t\tstring,\n\t\t{\n\t\t\ttimings: FrameTimingStats;\n\t\t\ttasks: Record<string, FrameTimingStats>;\n\t\t}\n\t>;\n}\n\n/**\n * Internal registration payload including unsubscribe callback.\n */\ninterface RegisteredFrameTask extends UseFrameResult {\n\tunsubscribe: () => void;\n}\n\n/**\n * Internal mutable task descriptor used by scheduler runtime.\n */\ninterface InternalTask {\n\ttask: FrameTask;\n\tcallback: FrameCallback;\n\torder: number;\n\tstarted: boolean;\n\tlastRunning: boolean;\n\tstartedStoreSet: (value: boolean) => void;\n\tstartedStore: Subscribable<boolean>;\n\tbefore: Set<FrameKey>;\n\tafter: Set<FrameKey>;\n\tinvalidation: {\n\t\tmode: 'never' | 'always' | 'on-change';\n\t\ttoken?: FrameTaskInvalidationToken;\n\t\tlastToken: FrameInvalidationToken | null;\n\t\thasToken: boolean;\n\t};\n\trunning?: () => boolean;\n}\n\n/**\n * Internal mutable stage descriptor used by scheduler runtime.\n */\ninterface InternalStage {\n\tkey: FrameKey;\n\torder: number;\n\tstarted: boolean;\n\tbefore: Set<FrameKey>;\n\tafter: Set<FrameKey>;\n\tcallback: FrameStageCallback;\n\ttasks: Map<FrameKey, InternalTask>;\n}\n\n/**\n * Default stage key used when task stage is not explicitly specified.\n */\nconst MAIN_STAGE_KEY = Symbol('motiongpu-main-stage');\nconst RENDER_MODE_INVALIDATION_TOKEN = Symbol('motiongpu-render-mode-change');\n\n/**\n * Default stage callback that runs tasks immediately.\n */\nconst DEFAULT_STAGE_CALLBACK: FrameStageCallback = (_state, runTasks) => runTasks();\n\n/**\n * Normalizes scalar-or-array options to array form.\n */\nfunction asArray<T>(value: T | T[] | undefined): T[] {\n\tif (!value) {\n\t\treturn [];\n\t}\n\n\treturn Array.isArray(value) ? value : [value];\n}\n\n/**\n * Normalizes frame keys to readable string labels.\n */\nfunction frameKeyToString(key: FrameKey): string {\n\treturn typeof key === 'symbol' ? key.toString() : key;\n}\n\n/**\n * Extracts task key from either direct key or task reference.\n */\nfunction toTaskKey(reference: FrameKey | FrameTask): FrameKey {\n\tif (typeof reference === 'string' || typeof reference === 'symbol') {\n\t\treturn reference;\n\t}\n\n\treturn reference.key;\n}\n\n/**\n * Extracts stage key from either direct key or stage reference.\n */\nfunction toStageKey(reference: FrameKey | FrameStage): FrameKey {\n\tif (typeof reference === 'string' || typeof reference === 'symbol') {\n\t\treturn reference;\n\t}\n\n\treturn reference.key;\n}\n\n/**\n * Resolves invalidation token from static value or resolver callback.\n */\nfunction resolveInvalidationToken(\n\ttoken: FrameTaskInvalidationToken | undefined\n): FrameInvalidationToken | null {\n\tif (token === undefined) {\n\t\treturn null;\n\t}\n\n\tconst resolved = typeof token === 'function' ? token() : token;\n\tif (resolved === null || resolved === undefined) {\n\t\treturn null;\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Normalizes task invalidation options to runtime representation.\n */\nfunction normalizeTaskInvalidation(\n\tkey: FrameKey,\n\toptions: UseFrameOptions\n): InternalTask['invalidation'] {\n\tconst explicit = options.invalidation;\n\tif (explicit === undefined) {\n\t\tif (options.autoInvalidate === false) {\n\t\t\treturn {\n\t\t\t\tmode: 'never',\n\t\t\t\tlastToken: null,\n\t\t\t\thasToken: false\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmode: 'always',\n\t\t\ttoken: key,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\tif (explicit === 'never' || explicit === 'always') {\n\t\tif (explicit === 'never') {\n\t\t\treturn {\n\t\t\t\tmode: explicit,\n\t\t\t\tlastToken: null,\n\t\t\t\thasToken: false\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmode: explicit,\n\t\t\ttoken: key,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\tconst mode = explicit.mode ?? 'always';\n\tconst token = explicit.token;\n\tif (mode === 'on-change' && token === undefined) {\n\t\tthrow new Error('Task invalidation mode \"on-change\" requires a token');\n\t}\n\n\tif (mode === 'never') {\n\t\treturn {\n\t\t\tmode,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\tif (mode === 'on-change') {\n\t\treturn {\n\t\t\tmode,\n\t\t\ttoken: token as FrameTaskInvalidationToken,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\treturn {\n\t\tmode,\n\t\ttoken: token ?? key,\n\t\tlastToken: null,\n\t\thasToken: false\n\t};\n}\n\n/**\n * Computes aggregate timing stats from sampled durations.\n */\nfunction buildTimingStats(samples: number[], last: number): FrameTimingStats {\n\tif (samples.length === 0) {\n\t\treturn {\n\t\t\tlast,\n\t\t\tavg: 0,\n\t\t\tmin: 0,\n\t\t\tmax: 0,\n\t\t\tcount: 0\n\t\t};\n\t}\n\n\tlet sum = 0;\n\tlet min = Number.POSITIVE_INFINITY;\n\tlet max = Number.NEGATIVE_INFINITY;\n\n\tfor (const value of samples) {\n\t\tsum += value;\n\t\tif (value < min) {\n\t\t\tmin = value;\n\t\t}\n\t\tif (value > max) {\n\t\t\tmax = value;\n\t\t}\n\t}\n\n\treturn {\n\t\tlast,\n\t\tavg: sum / samples.length,\n\t\tmin,\n\t\tmax,\n\t\tcount: samples.length\n\t};\n}\n\n/**\n * Dependency graph sorting options used for diagnostics labels.\n */\ninterface SortDependenciesOptions<T extends { key: FrameKey; order: number }> {\n\tgraphName: string;\n\tgetItemLabel: (item: T) => string;\n\tisKnownExternalDependency?: (key: FrameKey) => boolean;\n}\n\n/**\n * Deterministically sorts dependency keys for stable traversal and diagnostics.\n */\nfunction sortDependencyKeys(keys: Iterable<FrameKey>): FrameKey[] {\n\treturn Array.from(keys).sort((a, b) => frameKeyToString(a).localeCompare(frameKeyToString(b)));\n}\n\n/**\n * Finds one deterministic cycle path in the directed dependency graph.\n */\nfunction findDependencyCycle<T extends { key: FrameKey; order: number }>(\n\titems: T[],\n\tedges: ReadonlyMap<FrameKey, ReadonlySet<FrameKey>>\n): FrameKey[] | null {\n\tconst visitState = new Map<FrameKey, 0 | 1 | 2>();\n\tconst stack: FrameKey[] = [];\n\tlet cycle: FrameKey[] | null = null;\n\tconst sortedItems = [...items].sort((a, b) => a.order - b.order);\n\n\tconst visit = (key: FrameKey): boolean => {\n\t\tvisitState.set(key, 1);\n\t\tstack.push(key);\n\n\t\tfor (const childKey of sortDependencyKeys(edges.get(key) ?? [])) {\n\t\t\tconst state = visitState.get(childKey) ?? 0;\n\t\t\tif (state === 0) {\n\t\t\t\tif (visit(childKey)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (state === 1) {\n\t\t\t\tconst cycleStartIndex = stack.findIndex((entry) => entry === childKey);\n\t\t\t\tconst cyclePath = cycleStartIndex === -1 ? [childKey] : stack.slice(cycleStartIndex);\n\t\t\t\tcycle = [...cyclePath, childKey];\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tstack.pop();\n\t\tvisitState.set(key, 2);\n\t\treturn false;\n\t};\n\n\tfor (const item of sortedItems) {\n\t\tif ((visitState.get(item.key) ?? 0) !== 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (visit(item.key)) {\n\t\t\treturn cycle;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Topologically sorts items by `before`/`after` dependencies.\n *\n * Throws deterministic errors when dependencies are missing or cyclic.\n */\nfunction sortByDependencies<T extends { key: FrameKey; order: number }>(\n\titems: T[],\n\tgetBefore: (item: T) => Iterable<FrameKey>,\n\tgetAfter: (item: T) => Iterable<FrameKey>,\n\toptions: SortDependenciesOptions<T>\n): T[] {\n\tconst itemsByKey = new Map<FrameKey, T>();\n\tfor (const item of items) {\n\t\titemsByKey.set(item.key, item);\n\t}\n\n\tconst indegree = new Map<FrameKey, number>();\n\tconst edges = new Map<FrameKey, Set<FrameKey>>();\n\n\tfor (const item of items) {\n\t\tindegree.set(item.key, 0);\n\t\tedges.set(item.key, new Set());\n\t}\n\n\tfor (const item of items) {\n\t\tfor (const dependencyKey of getAfter(item)) {\n\t\t\tif (!itemsByKey.has(dependencyKey)) {\n\t\t\t\tif (options.isKnownExternalDependency?.(dependencyKey)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${options.graphName} dependency error: ${options.getItemLabel(item)} references missing dependency \"${frameKeyToString(dependencyKey)}\" in \"after\".`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tedges.get(dependencyKey)?.add(item.key);\n\t\t\tindegree.set(item.key, (indegree.get(item.key) ?? 0) + 1);\n\t\t}\n\n\t\tfor (const dependencyKey of getBefore(item)) {\n\t\t\tif (!itemsByKey.has(dependencyKey)) {\n\t\t\t\tif (options.isKnownExternalDependency?.(dependencyKey)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${options.graphName} dependency error: ${options.getItemLabel(item)} references missing dependency \"${frameKeyToString(dependencyKey)}\" in \"before\".`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tedges.get(item.key)?.add(dependencyKey);\n\t\t\tindegree.set(dependencyKey, (indegree.get(dependencyKey) ?? 0) + 1);\n\t\t}\n\t}\n\n\tconst queue = items.filter((item) => (indegree.get(item.key) ?? 0) === 0);\n\tqueue.sort((a, b) => a.order - b.order);\n\n\tconst ordered: T[] = [];\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (!current) {\n\t\t\tbreak;\n\t\t}\n\n\t\tordered.push(current);\n\n\t\tfor (const childKey of edges.get(current.key) ?? []) {\n\t\t\tconst nextDegree = (indegree.get(childKey) ?? 0) - 1;\n\t\t\tindegree.set(childKey, nextDegree);\n\t\t\tif (nextDegree === 0) {\n\t\t\t\tconst child = itemsByKey.get(childKey);\n\t\t\t\tif (child) {\n\t\t\t\t\tqueue.push(child);\n\t\t\t\t\tqueue.sort((a, b) => a.order - b.order);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (ordered.length !== items.length) {\n\t\tconst cycle = findDependencyCycle(items, edges);\n\t\tif (cycle) {\n\t\t\tthrow new Error(\n\t\t\t\t`${options.graphName} dependency cycle detected: ${cycle.map((key) => frameKeyToString(key)).join(' -> ')}`\n\t\t\t);\n\t\t}\n\n\t\tthrow new Error(`${options.graphName} dependency resolution failed.`);\n\t}\n\n\treturn ordered;\n}\n\n/**\n * Runtime registry that stores frame tasks/stages and drives render scheduling.\n */\nexport interface FrameRegistry {\n\t/**\n\t * Registers a frame callback in the scheduler.\n\t */\n\tregister: (\n\t\tkeyOrCallback: FrameKey | FrameCallback,\n\t\tcallbackOrOptions?: FrameCallback | UseFrameOptions,\n\t\tmaybeOptions?: UseFrameOptions\n\t) => RegisteredFrameTask;\n\t/**\n\t * Executes one scheduler run.\n\t */\n\trun: (state: FrameState) => void;\n\t/**\n\t * Marks frame as invalidated for `on-demand` mode.\n\t */\n\tinvalidate: (token?: FrameInvalidationToken) => void;\n\t/**\n\t * Requests a single render in `manual` mode.\n\t */\n\tadvance: () => void;\n\t/**\n\t * Returns whether renderer should submit a frame now.\n\t */\n\tshouldRender: () => boolean;\n\t/**\n\t * Resets one-frame invalidation/advance flags.\n\t */\n\tendFrame: () => void;\n\t/**\n\t * Sets render scheduling mode.\n\t */\n\tsetRenderMode: (mode: RenderMode) => void;\n\t/**\n\t * Enables or disables automatic rendering entirely.\n\t */\n\tsetAutoRender: (enabled: boolean) => void;\n\t/**\n\t * Sets maximum allowed delta passed to frame tasks.\n\t */\n\tsetMaxDelta: (value: number) => void;\n\t/**\n\t * Enables/disables frame profiling.\n\t */\n\tsetProfilingEnabled: (enabled: boolean) => void;\n\t/**\n\t * Sets profiling history window (in frames).\n\t */\n\tsetProfilingWindow: (window: number) => void;\n\t/**\n\t * Clears collected profiling samples.\n\t */\n\tresetProfiling: () => void;\n\t/**\n\t * Enables/disables diagnostics capture.\n\t */\n\tsetDiagnosticsEnabled: (enabled: boolean) => void;\n\t/**\n\t * Returns current render mode.\n\t */\n\tgetRenderMode: () => RenderMode;\n\t/**\n\t * Returns whether automatic rendering is enabled.\n\t */\n\tgetAutoRender: () => boolean;\n\t/**\n\t * Returns current max delta clamp.\n\t */\n\tgetMaxDelta: () => number;\n\t/**\n\t * Returns profiling toggle state.\n\t */\n\tgetProfilingEnabled: () => boolean;\n\t/**\n\t * Returns active profiling history window (in frames).\n\t */\n\tgetProfilingWindow: () => number;\n\t/**\n\t * Returns aggregated profiling snapshot.\n\t */\n\tgetProfilingSnapshot: () => FrameProfilingSnapshot | null;\n\t/**\n\t * Returns diagnostics toggle state.\n\t */\n\tgetDiagnosticsEnabled: () => boolean;\n\t/**\n\t * Returns last run timings snapshot when diagnostics are enabled.\n\t */\n\tgetLastRunTimings: () => FrameRunTimings | null;\n\t/**\n\t * Returns dependency-sorted schedule snapshot.\n\t */\n\tgetSchedule: () => FrameScheduleSnapshot;\n\t/**\n\t * Creates or updates a stage.\n\t */\n\tcreateStage: (\n\t\tkey: FrameKey,\n\t\toptions?: {\n\t\t\tbefore?: (FrameKey | FrameStage) | (FrameKey | FrameStage)[];\n\t\t\tafter?: (FrameKey | FrameStage) | (FrameKey | FrameStage)[];\n\t\t\tcallback?: FrameStageCallback | null;\n\t\t}\n\t) => FrameStage;\n\t/**\n\t * Reads stage metadata by key.\n\t */\n\tgetStage: (key: FrameKey) => FrameStage | undefined;\n\t/**\n\t * Removes all tasks from all stages.\n\t */\n\tclear: () => void;\n}\n\n/**\n * Creates a frame registry used by `FragCanvas` and `useFrame`.\n *\n * @param options - Initial scheduler options.\n * @returns Mutable frame registry instance.\n */\nexport function createFrameRegistry(options?: {\n\trenderMode?: RenderMode;\n\tautoRender?: boolean;\n\tmaxDelta?: number;\n\tprofilingEnabled?: boolean;\n\tprofilingWindow?: number;\n\tdiagnosticsEnabled?: boolean;\n}): FrameRegistry {\n\tlet renderMode: RenderMode = options?.renderMode ?? 'always';\n\tlet autoRender = options?.autoRender ?? true;\n\tlet maxDelta = options?.maxDelta ?? 0.1;\n\tlet profilingEnabled = options?.profilingEnabled ?? options?.diagnosticsEnabled ?? false;\n\tlet profilingWindow = options?.profilingWindow ?? 120;\n\tlet lastRunTimings: FrameRunTimings | null = null;\n\tconst profilingHistory: FrameRunTimings[] = [];\n\tlet hasUntokenizedInvalidation = true;\n\tconst invalidationTokens = new Set<FrameInvalidationToken>();\n\tlet shouldAdvance = false;\n\tlet orderCounter = 0;\n\n\tconst assertMaxDelta = (value: number): number => {\n\t\tif (!Number.isFinite(value) || value <= 0) {\n\t\t\tthrow new Error('maxDelta must be a finite number greater than 0');\n\t\t}\n\t\treturn value;\n\t};\n\n\tconst assertProfilingWindow = (value: number): number => {\n\t\tif (!Number.isFinite(value) || value <= 0) {\n\t\t\tthrow new Error('profilingWindow must be a finite number greater than 0');\n\t\t}\n\t\treturn Math.floor(value);\n\t};\n\n\tmaxDelta = assertMaxDelta(maxDelta);\n\tprofilingWindow = assertProfilingWindow(profilingWindow);\n\n\tconst stages = new Map<FrameKey, InternalStage>();\n\tlet scheduleDirty = true;\n\tlet sortedStages: InternalStage[] = [];\n\tconst sortedTasksByStage = new Map<FrameKey, InternalTask[]>();\n\tlet scheduleSnapshot: FrameScheduleSnapshot = { stages: [] };\n\n\tconst markScheduleDirty = (): void => {\n\t\tscheduleDirty = true;\n\t};\n\n\tconst syncSchedule = (): void => {\n\t\tif (!scheduleDirty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst stageList = sortByDependencies(\n\t\t\tArray.from(stages.values()),\n\t\t\t(stage) => stage.before,\n\t\t\t(stage) => stage.after,\n\t\t\t{\n\t\t\t\tgraphName: 'Frame stage graph',\n\t\t\t\tgetItemLabel: (stage) => `stage \"${frameKeyToString(stage.key)}\"`\n\t\t\t}\n\t\t);\n\t\tconst nextTasksByStage = new Map<FrameKey, InternalTask[]>();\n\t\tconst globalTaskKeys = new Set<FrameKey>();\n\t\tfor (const stage of stageList) {\n\t\t\tfor (const task of stage.tasks.values()) {\n\t\t\t\tglobalTaskKeys.add(task.task.key);\n\t\t\t}\n\t\t}\n\n\t\tfor (const stage of stageList) {\n\t\t\tconst taskList = sortByDependencies(\n\t\t\t\tArray.from(stage.tasks.values()).map((task) => ({\n\t\t\t\t\tkey: task.task.key,\n\t\t\t\t\torder: task.order,\n\t\t\t\t\ttask\n\t\t\t\t})),\n\t\t\t\t(task) => task.task.before,\n\t\t\t\t(task) => task.task.after,\n\t\t\t\t{\n\t\t\t\t\tgraphName: `Frame task graph for stage \"${frameKeyToString(stage.key)}\"`,\n\t\t\t\t\tgetItemLabel: (task) => `task \"${frameKeyToString(task.key)}\"`,\n\t\t\t\t\tisKnownExternalDependency: (key) => globalTaskKeys.has(key)\n\t\t\t\t}\n\t\t\t).map((task) => task.task);\n\t\t\tnextTasksByStage.set(stage.key, taskList);\n\t\t}\n\n\t\tsortedStages = stageList;\n\t\tsortedTasksByStage.clear();\n\t\tfor (const [stageKey, taskList] of nextTasksByStage) {\n\t\t\tsortedTasksByStage.set(stageKey, taskList);\n\t\t}\n\n\t\tscheduleSnapshot = {\n\t\t\tstages: sortedStages.map((stage) => ({\n\t\t\t\tkey: frameKeyToString(stage.key),\n\t\t\t\ttasks: (sortedTasksByStage.get(stage.key) ?? []).map((task) =>\n\t\t\t\t\tframeKeyToString(task.task.key)\n\t\t\t\t)\n\t\t\t}))\n\t\t};\n\n\t\tscheduleDirty = false;\n\t};\n\n\tconst pushProfile = (timings: FrameRunTimings): void => {\n\t\tprofilingHistory.push(timings);\n\t\twhile (profilingHistory.length > profilingWindow) {\n\t\t\tprofilingHistory.shift();\n\t\t}\n\t};\n\n\tconst clearProfiling = (): void => {\n\t\tprofilingHistory.length = 0;\n\t\tlastRunTimings = null;\n\t};\n\n\tconst buildProfilingSnapshot = (): FrameProfilingSnapshot | null => {\n\t\tif (!profilingEnabled) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst stageBuckets = new Map<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tdurations: number[];\n\t\t\t\ttaskDurations: Map<string, number[]>;\n\t\t\t}\n\t\t>();\n\t\tconst totalDurations: number[] = [];\n\n\t\tfor (const frame of profilingHistory) {\n\t\t\ttotalDurations.push(frame.total);\n\t\t\tfor (const [stageKey, stageTiming] of Object.entries(frame.stages)) {\n\t\t\t\tconst stageBucket = stageBuckets.get(stageKey) ?? {\n\t\t\t\t\tdurations: [],\n\t\t\t\t\ttaskDurations: new Map<string, number[]>()\n\t\t\t\t};\n\t\t\t\tstageBucket.durations.push(stageTiming.duration);\n\n\t\t\t\tfor (const [taskKey, taskDuration] of Object.entries(stageTiming.tasks)) {\n\t\t\t\t\tconst bucket = stageBucket.taskDurations.get(taskKey) ?? [];\n\t\t\t\t\tbucket.push(taskDuration);\n\t\t\t\t\tstageBucket.taskDurations.set(taskKey, bucket);\n\t\t\t\t}\n\n\t\t\t\tstageBuckets.set(stageKey, stageBucket);\n\t\t\t}\n\t\t}\n\n\t\tconst stagesSnapshot: FrameProfilingSnapshot['stages'] = {};\n\t\tfor (const [stageKey, stageBucket] of stageBuckets) {\n\t\t\tconst lastStageDuration = lastRunTimings?.stages[stageKey]?.duration ?? 0;\n\t\t\tconst taskSnapshot: Record<string, FrameTimingStats> = {};\n\t\t\tfor (const [taskKey, taskDurations] of stageBucket.taskDurations) {\n\t\t\t\tconst lastTaskDuration = lastRunTimings?.stages[stageKey]?.tasks[taskKey] ?? 0;\n\t\t\t\ttaskSnapshot[taskKey] = buildTimingStats(taskDurations, lastTaskDuration);\n\t\t\t}\n\n\t\t\tstagesSnapshot[stageKey] = {\n\t\t\t\ttimings: buildTimingStats(stageBucket.durations, lastStageDuration),\n\t\t\t\ttasks: taskSnapshot\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\twindow: profilingWindow,\n\t\t\tframeCount: profilingHistory.length,\n\t\t\tlastFrame: lastRunTimings,\n\t\t\ttotal: buildTimingStats(totalDurations, lastRunTimings?.total ?? 0),\n\t\t\tstages: stagesSnapshot\n\t\t};\n\t};\n\n\tconst ensureStage = (\n\t\tstageReference: FrameKey | FrameStage,\n\t\tstageOptions?: {\n\t\t\tbefore?: (FrameKey | FrameStage)[];\n\t\t\tafter?: (FrameKey | FrameStage)[];\n\t\t\tcallback?: FrameStageCallback | null;\n\t\t}\n\t): InternalStage => {\n\t\tconst stageKey = toStageKey(stageReference);\n\t\tconst existing = stages.get(stageKey);\n\t\tif (existing) {\n\t\t\tif (stageOptions?.before !== undefined) {\n\t\t\t\texisting.before = new Set(stageOptions.before.map((entry) => toStageKey(entry)));\n\t\t\t\tmarkScheduleDirty();\n\t\t\t}\n\t\t\tif (stageOptions?.after !== undefined) {\n\t\t\t\texisting.after = new Set(stageOptions.after.map((entry) => toStageKey(entry)));\n\t\t\t\tmarkScheduleDirty();\n\t\t\t}\n\t\t\tif (stageOptions && Object.prototype.hasOwnProperty.call(stageOptions, 'callback')) {\n\t\t\t\texisting.callback = stageOptions.callback ?? DEFAULT_STAGE_CALLBACK;\n\t\t\t}\n\t\t\treturn existing;\n\t\t}\n\n\t\tconst stage: InternalStage = {\n\t\t\tkey: stageKey,\n\t\t\torder: orderCounter++,\n\t\t\tstarted: true,\n\t\t\tbefore: new Set((stageOptions?.before ?? []).map((entry) => toStageKey(entry))),\n\t\t\tafter: new Set((stageOptions?.after ?? []).map((entry) => toStageKey(entry))),\n\t\t\tcallback: stageOptions?.callback ?? DEFAULT_STAGE_CALLBACK,\n\t\t\ttasks: new Map()\n\t\t};\n\t\tstages.set(stageKey, stage);\n\t\tmarkScheduleDirty();\n\t\treturn stage;\n\t};\n\n\tensureStage(MAIN_STAGE_KEY);\n\n\tconst resolveEffectiveRunning = (task: InternalTask): boolean => {\n\t\tconst running = task.started && (task.running?.() ?? true);\n\t\tif (task.lastRunning !== running) {\n\t\t\ttask.lastRunning = running;\n\t\t\ttask.startedStoreSet(running);\n\t\t}\n\t\treturn running;\n\t};\n\n\tconst hasPendingInvalidation = (): boolean => {\n\t\treturn hasUntokenizedInvalidation || invalidationTokens.size > 0;\n\t};\n\n\tconst invalidateWithToken = (token?: FrameInvalidationToken): void => {\n\t\tif (token === undefined) {\n\t\t\thasUntokenizedInvalidation = true;\n\t\t\treturn;\n\t\t}\n\n\t\tinvalidationTokens.add(token);\n\t};\n\n\tconst applyTaskInvalidation = (task: InternalTask): void => {\n\t\tconst config = task.invalidation;\n\t\tif (config.mode === 'never') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (config.mode === 'always') {\n\t\t\tconst token = resolveInvalidationToken(config.token);\n\t\t\tinvalidateWithToken(token ?? task.task.key);\n\t\t\treturn;\n\t\t}\n\n\t\tconst token = resolveInvalidationToken(config.token);\n\t\tif (token === null) {\n\t\t\tconfig.hasToken = false;\n\t\t\tconfig.lastToken = null;\n\t\t\treturn;\n\t\t}\n\n\t\tconst changed = !config.hasToken || config.lastToken !== token;\n\t\tconfig.hasToken = true;\n\t\tconfig.lastToken = token;\n\t\tif (changed) {\n\t\t\tinvalidateWithToken(token);\n\t\t}\n\t};\n\n\treturn {\n\t\tregister(keyOrCallback, callbackOrOptions, maybeOptions) {\n\t\t\tconst key =\n\t\t\t\ttypeof keyOrCallback === 'function'\n\t\t\t\t\t? (Symbol('motiongpu-task') as FrameKey)\n\t\t\t\t\t: (keyOrCallback as FrameKey);\n\t\t\tconst callback =\n\t\t\t\ttypeof keyOrCallback === 'function' ? keyOrCallback : (callbackOrOptions as FrameCallback);\n\t\t\tconst taskOptions =\n\t\t\t\ttypeof keyOrCallback === 'function'\n\t\t\t\t\t? ((callbackOrOptions as UseFrameOptions | undefined) ?? {})\n\t\t\t\t\t: (maybeOptions ?? {});\n\n\t\t\tif (typeof callback !== 'function') {\n\t\t\t\tthrow new Error('useFrame requires a callback');\n\t\t\t}\n\n\t\t\tconst before = asArray(taskOptions.before);\n\t\t\tconst after = asArray(taskOptions.after);\n\t\t\tconst inferredStage = [...before, ...after].find(\n\t\t\t\t(entry) => typeof entry === 'object' && entry !== null && 'stage' in entry\n\t\t\t) as FrameTask | undefined;\n\t\t\tconst stageKey = taskOptions.stage\n\t\t\t\t? toStageKey(taskOptions.stage)\n\t\t\t\t: (inferredStage?.stage ?? MAIN_STAGE_KEY);\n\n\t\t\tconst stage = ensureStage(stageKey);\n\t\t\tconst startedWritable: CurrentWritable<boolean> = createCurrentWritable(\n\t\t\t\ttaskOptions.autoStart ?? true\n\t\t\t);\n\n\t\t\tconst internalTask: InternalTask = {\n\t\t\t\ttask: { key, stage: stage.key },\n\t\t\t\tcallback,\n\t\t\t\torder: orderCounter++,\n\t\t\t\tstarted: taskOptions.autoStart ?? true,\n\t\t\t\tlastRunning: taskOptions.autoStart ?? true,\n\t\t\t\tstartedStoreSet: startedWritable.set,\n\t\t\t\tstartedStore: { subscribe: startedWritable.subscribe },\n\t\t\t\tbefore: new Set(before.map((entry) => toTaskKey(entry))),\n\t\t\t\tafter: new Set(after.map((entry) => toTaskKey(entry))),\n\t\t\t\tinvalidation: normalizeTaskInvalidation(key, taskOptions)\n\t\t\t};\n\n\t\t\tif (taskOptions.running) {\n\t\t\t\tinternalTask.running = taskOptions.running;\n\t\t\t}\n\n\t\t\tstage.tasks.set(key, internalTask);\n\t\t\tmarkScheduleDirty();\n\t\t\tinternalTask.startedStoreSet(resolveEffectiveRunning(internalTask));\n\n\t\t\tconst start = () => {\n\t\t\t\tinternalTask.started = true;\n\t\t\t\tresolveEffectiveRunning(internalTask);\n\t\t\t};\n\n\t\t\tconst stop = () => {\n\t\t\t\tinternalTask.started = false;\n\t\t\t\tresolveEffectiveRunning(internalTask);\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\ttask: internalTask.task,\n\t\t\t\tstart,\n\t\t\t\tstop,\n\t\t\t\tstarted: internalTask.startedStore,\n\t\t\t\tunsubscribe: () => {\n\t\t\t\t\tif (stage.tasks.delete(key)) {\n\t\t\t\t\t\tmarkScheduleDirty();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\trun(state) {\n\t\t\tconst clampedDelta = Math.min(state.delta, maxDelta);\n\t\t\tconst frameState =\n\t\t\t\tclampedDelta === state.delta\n\t\t\t\t\t? state\n\t\t\t\t\t: {\n\t\t\t\t\t\t\t...state,\n\t\t\t\t\t\t\tdelta: clampedDelta\n\t\t\t\t\t\t};\n\t\t\tsyncSchedule();\n\t\t\tconst frameStart = profilingEnabled ? performance.now() : 0;\n\t\t\tconst stageTimings: FrameRunTimings['stages'] = {};\n\n\t\t\tfor (const stage of sortedStages) {\n\t\t\t\tif (!stage.started) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst stageStart = profilingEnabled ? performance.now() : 0;\n\t\t\t\tconst taskTimings: Record<string, number> = {};\n\t\t\t\tconst taskList = sortedTasksByStage.get(stage.key) ?? [];\n\n\t\t\t\tstage.callback(frameState, () => {\n\t\t\t\t\tfor (const task of taskList) {\n\t\t\t\t\t\tif (!resolveEffectiveRunning(task)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst taskStart = profilingEnabled ? performance.now() : 0;\n\n\t\t\t\t\t\ttask.callback(frameState);\n\t\t\t\t\t\tif (profilingEnabled) {\n\t\t\t\t\t\t\ttaskTimings[frameKeyToString(task.task.key)] = performance.now() - taskStart;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tapplyTaskInvalidation(task);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (profilingEnabled) {\n\t\t\t\t\tstageTimings[frameKeyToString(stage.key)] = {\n\t\t\t\t\t\tduration: performance.now() - stageStart,\n\t\t\t\t\t\ttasks: taskTimings\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (profilingEnabled) {\n\t\t\t\tconst timings = {\n\t\t\t\t\ttotal: performance.now() - frameStart,\n\t\t\t\t\tstages: stageTimings\n\t\t\t\t};\n\t\t\t\tlastRunTimings = timings;\n\t\t\t\tpushProfile(timings);\n\t\t\t}\n\t\t},\n\t\tinvalidate(token) {\n\t\t\tinvalidateWithToken(token);\n\t\t},\n\t\tadvance() {\n\t\t\tshouldAdvance = true;\n\t\t\tinvalidateWithToken();\n\t\t},\n\t\tshouldRender() {\n\t\t\tif (!autoRender) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (renderMode === 'always') {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (renderMode === 'on-demand') {\n\t\t\t\treturn shouldAdvance || hasPendingInvalidation();\n\t\t\t}\n\n\t\t\treturn shouldAdvance;\n\t\t},\n\t\tendFrame() {\n\t\t\thasUntokenizedInvalidation = false;\n\t\t\tinvalidationTokens.clear();\n\t\t\tshouldAdvance = false;\n\t\t},\n\t\tsetRenderMode(mode) {\n\t\t\tif (renderMode === mode) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\trenderMode = mode;\n\t\t\tshouldAdvance = false;\n\t\t\tif (mode === 'on-demand') {\n\t\t\t\tinvalidateWithToken(RENDER_MODE_INVALIDATION_TOKEN);\n\t\t\t}\n\t\t},\n\t\tsetAutoRender(enabled) {\n\t\t\tautoRender = enabled;\n\t\t},\n\t\tsetMaxDelta(value) {\n\t\t\tmaxDelta = assertMaxDelta(value);\n\t\t},\n\t\tsetProfilingEnabled(enabled) {\n\t\t\tprofilingEnabled = enabled;\n\t\t\tif (!enabled) {\n\t\t\t\tclearProfiling();\n\t\t\t}\n\t\t},\n\t\tsetProfilingWindow(window) {\n\t\t\tprofilingWindow = assertProfilingWindow(window);\n\t\t\twhile (profilingHistory.length > profilingWindow) {\n\t\t\t\tprofilingHistory.shift();\n\t\t\t}\n\t\t},\n\t\tresetProfiling() {\n\t\t\tclearProfiling();\n\t\t},\n\t\tsetDiagnosticsEnabled(enabled) {\n\t\t\tprofilingEnabled = enabled;\n\t\t\tif (!enabled) {\n\t\t\t\tclearProfiling();\n\t\t\t}\n\t\t},\n\t\tgetRenderMode() {\n\t\t\treturn renderMode;\n\t\t},\n\t\tgetAutoRender() {\n\t\t\treturn autoRender;\n\t\t},\n\t\tgetMaxDelta() {\n\t\t\treturn maxDelta;\n\t\t},\n\t\tgetProfilingEnabled() {\n\t\t\treturn profilingEnabled;\n\t\t},\n\t\tgetProfilingWindow() {\n\t\t\treturn profilingWindow;\n\t\t},\n\t\tgetProfilingSnapshot() {\n\t\t\treturn buildProfilingSnapshot();\n\t\t},\n\t\tgetDiagnosticsEnabled() {\n\t\t\treturn profilingEnabled;\n\t\t},\n\t\tgetLastRunTimings() {\n\t\t\treturn lastRunTimings;\n\t\t},\n\t\tgetSchedule() {\n\t\t\tsyncSchedule();\n\t\t\treturn scheduleSnapshot;\n\t\t},\n\t\tcreateStage(key, options) {\n\t\t\tconst stageOptions: Parameters<typeof ensureStage>[1] | undefined = options\n\t\t\t\t? {\n\t\t\t\t\t\t...(Object.prototype.hasOwnProperty.call(options, 'before')\n\t\t\t\t\t\t\t? { before: asArray(options.before) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t...(Object.prototype.hasOwnProperty.call(options, 'after')\n\t\t\t\t\t\t\t? { after: asArray(options.after) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t...(Object.prototype.hasOwnProperty.call(options, 'callback')\n\t\t\t\t\t\t\t? { callback: options.callback ?? null }\n\t\t\t\t\t\t\t: {})\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t\tconst stage = ensureStage(key, stageOptions);\n\t\t\treturn { key: stage.key };\n\t\t},\n\t\tgetStage(key) {\n\t\t\tconst stage = stages.get(key);\n\t\t\tif (!stage) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn { key: stage.key };\n\t\t},\n\t\tclear() {\n\t\t\tfor (const stage of stages.values()) {\n\t\t\t\tstage.tasks.clear();\n\t\t\t}\n\t\t\tmarkScheduleDirty();\n\t\t}\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"frame-registry.js","names":[],"sources":["../../src/lib/core/frame-registry.ts"],"sourcesContent":["import { createCurrentWritable, type CurrentWritable, type Subscribable } from './current-value.js';\nimport type { FrameInvalidationToken, FrameState, RenderMode } from './types.js';\n\n/**\n * Per-frame callback executed by the frame scheduler.\n */\nexport type FrameCallback = (state: FrameState) => void;\n\n/**\n * Stable key type used to identify frame tasks and stages.\n */\nexport type FrameKey = string | symbol;\n\n/**\n * Public metadata describing a registered frame task.\n */\nexport interface FrameTask {\n\tkey: FrameKey;\n\tstage: FrameKey;\n}\n\n/**\n * Public metadata describing a frame stage.\n */\nexport interface FrameStage {\n\tkey: FrameKey;\n}\n\n/**\n * Stage callback allowing custom orchestration around task execution.\n */\nexport type FrameStageCallback = (state: FrameState, runTasks: () => void) => void;\n\n/**\n * Options controlling task registration and scheduling behavior.\n */\nexport interface UseFrameOptions {\n\t/**\n\t * Whether task starts in active state.\n\t *\n\t * @default true\n\t */\n\tautoStart?: boolean;\n\t/**\n\t * Whether task execution invalidates frame automatically.\n\t *\n\t * @default true\n\t */\n\tautoInvalidate?: boolean;\n\t/**\n\t * Explicit task invalidation policy.\n\t */\n\tinvalidation?: FrameTaskInvalidation;\n\t/**\n\t * Stage to register task in.\n\t *\n\t * If omitted, main stage is used unless inferred from task dependencies.\n\t */\n\tstage?: FrameKey | FrameStage;\n\t/**\n\t * Task dependencies that should run after this task.\n\t */\n\tbefore?: (FrameKey | FrameTask) | (FrameKey | FrameTask)[];\n\t/**\n\t * Task dependencies that should run before this task.\n\t */\n\tafter?: (FrameKey | FrameTask) | (FrameKey | FrameTask)[];\n\t/**\n\t * Dynamic predicate controlling whether the task is currently active.\n\t */\n\trunning?: () => boolean;\n}\n\n/**\n * Invalidation token value or resolver.\n */\nexport type FrameTaskInvalidationToken =\n\t| FrameInvalidationToken\n\t| (() => FrameInvalidationToken | null | undefined);\n\n/**\n * Explicit task invalidation policy.\n */\nexport type FrameTaskInvalidation =\n\t| 'never'\n\t| 'always'\n\t| {\n\t\t\tmode?: 'never' | 'always';\n\t\t\ttoken?: FrameTaskInvalidationToken;\n\t }\n\t| {\n\t\t\tmode: 'on-change';\n\t\t\ttoken: FrameTaskInvalidationToken;\n\t };\n\n/**\n * Handle returned by `useFrame` registration.\n */\nexport interface UseFrameResult {\n\t/**\n\t * Registered task metadata.\n\t */\n\ttask: FrameTask;\n\t/**\n\t * Starts task execution.\n\t */\n\tstart: () => void;\n\t/**\n\t * Stops task execution.\n\t */\n\tstop: () => void;\n\t/**\n\t * Readable flag representing effective running state.\n\t */\n\tstarted: Subscribable<boolean>;\n}\n\n/**\n * Snapshot of the resolved stage/task execution order.\n */\nexport interface FrameScheduleSnapshot {\n\tstages: Array<{\n\t\tkey: string;\n\t\ttasks: string[];\n\t}>;\n}\n\n/**\n * Optional scheduler diagnostics payload captured for the last run.\n */\nexport interface FrameRunTimings {\n\ttotal: number;\n\tstages: Record<\n\t\tstring,\n\t\t{\n\t\t\tduration: number;\n\t\t\ttasks: Record<string, number>;\n\t\t}\n\t>;\n}\n\n/**\n * Aggregated timing statistics for stage/task profiling.\n */\nexport interface FrameTimingStats {\n\tlast: number;\n\tavg: number;\n\tmin: number;\n\tmax: number;\n\tcount: number;\n}\n\n/**\n * Profiling snapshot aggregated from the configured history window.\n */\nexport interface FrameProfilingSnapshot {\n\twindow: number;\n\tframeCount: number;\n\tlastFrame: FrameRunTimings | null;\n\ttotal: FrameTimingStats;\n\tstages: Record<\n\t\tstring,\n\t\t{\n\t\t\ttimings: FrameTimingStats;\n\t\t\ttasks: Record<string, FrameTimingStats>;\n\t\t}\n\t>;\n}\n\n/**\n * Internal registration payload including unsubscribe callback.\n */\ninterface RegisteredFrameTask extends UseFrameResult {\n\tunsubscribe: () => void;\n}\n\n/**\n * Internal mutable task descriptor used by scheduler runtime.\n */\ninterface InternalTask {\n\ttask: FrameTask;\n\tcallback: FrameCallback;\n\torder: number;\n\tstarted: boolean;\n\tlastRunning: boolean;\n\tstartedStoreSet: (value: boolean) => void;\n\tstartedStore: Subscribable<boolean>;\n\tbefore: Set<FrameKey>;\n\tafter: Set<FrameKey>;\n\tinvalidation: {\n\t\tmode: 'never' | 'always' | 'on-change';\n\t\ttoken?: FrameTaskInvalidationToken;\n\t\tlastToken: FrameInvalidationToken | null;\n\t\thasToken: boolean;\n\t};\n\trunning?: () => boolean;\n}\n\n/**\n * Internal mutable stage descriptor used by scheduler runtime.\n */\ninterface InternalStage {\n\tkey: FrameKey;\n\torder: number;\n\tstarted: boolean;\n\tbefore: Set<FrameKey>;\n\tafter: Set<FrameKey>;\n\tcallback: FrameStageCallback;\n\ttasks: Map<FrameKey, InternalTask>;\n}\n\n/**\n * Default stage key used when task stage is not explicitly specified.\n */\nconst MAIN_STAGE_KEY = Symbol('motiongpu-main-stage');\nconst RENDER_MODE_INVALIDATION_TOKEN = Symbol('motiongpu-render-mode-change');\n\n/**\n * Default stage callback that runs tasks immediately.\n */\nconst DEFAULT_STAGE_CALLBACK: FrameStageCallback = (_state, runTasks) => runTasks();\n\n/**\n * Normalizes scalar-or-array options to array form.\n */\nfunction asArray<T>(value: T | T[] | undefined): T[] {\n\tif (!value) {\n\t\treturn [];\n\t}\n\n\treturn Array.isArray(value) ? value : [value];\n}\n\n/**\n * Normalizes frame keys to readable string labels.\n */\nfunction frameKeyToString(key: FrameKey): string {\n\treturn typeof key === 'symbol' ? key.toString() : key;\n}\n\n/**\n * Extracts task key from either direct key or task reference.\n */\nfunction toTaskKey(reference: FrameKey | FrameTask): FrameKey {\n\tif (typeof reference === 'string' || typeof reference === 'symbol') {\n\t\treturn reference;\n\t}\n\n\treturn reference.key;\n}\n\n/**\n * Extracts stage key from either direct key or stage reference.\n */\nfunction toStageKey(reference: FrameKey | FrameStage): FrameKey {\n\tif (typeof reference === 'string' || typeof reference === 'symbol') {\n\t\treturn reference;\n\t}\n\n\treturn reference.key;\n}\n\n/**\n * Resolves invalidation token from static value or resolver callback.\n */\nfunction resolveInvalidationToken(\n\ttoken: FrameTaskInvalidationToken | undefined\n): FrameInvalidationToken | null {\n\tif (token === undefined) {\n\t\treturn null;\n\t}\n\n\tconst resolved = typeof token === 'function' ? token() : token;\n\tif (resolved === null || resolved === undefined) {\n\t\treturn null;\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Normalizes task invalidation options to runtime representation.\n */\nfunction normalizeTaskInvalidation(\n\tkey: FrameKey,\n\toptions: UseFrameOptions\n): InternalTask['invalidation'] {\n\tconst explicit = options.invalidation;\n\tif (explicit === undefined) {\n\t\tif (options.autoInvalidate === false) {\n\t\t\treturn {\n\t\t\t\tmode: 'never',\n\t\t\t\tlastToken: null,\n\t\t\t\thasToken: false\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmode: 'always',\n\t\t\ttoken: key,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\tif (explicit === 'never' || explicit === 'always') {\n\t\tif (explicit === 'never') {\n\t\t\treturn {\n\t\t\t\tmode: explicit,\n\t\t\t\tlastToken: null,\n\t\t\t\thasToken: false\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tmode: explicit,\n\t\t\ttoken: key,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\tconst mode = explicit.mode ?? 'always';\n\tconst token = explicit.token;\n\tif (mode === 'on-change' && token === undefined) {\n\t\tthrow new Error('Task invalidation mode \"on-change\" requires a token');\n\t}\n\n\tif (mode === 'never') {\n\t\treturn {\n\t\t\tmode,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\tif (mode === 'on-change') {\n\t\treturn {\n\t\t\tmode,\n\t\t\ttoken: token as FrameTaskInvalidationToken,\n\t\t\tlastToken: null,\n\t\t\thasToken: false\n\t\t};\n\t}\n\n\treturn {\n\t\tmode,\n\t\ttoken: token ?? key,\n\t\tlastToken: null,\n\t\thasToken: false\n\t};\n}\n\n/**\n * Computes aggregate timing stats from sampled durations.\n */\nfunction buildTimingStats(samples: number[], last: number): FrameTimingStats {\n\tif (samples.length === 0) {\n\t\treturn {\n\t\t\tlast,\n\t\t\tavg: 0,\n\t\t\tmin: 0,\n\t\t\tmax: 0,\n\t\t\tcount: 0\n\t\t};\n\t}\n\n\tlet sum = 0;\n\tlet min = Number.POSITIVE_INFINITY;\n\tlet max = Number.NEGATIVE_INFINITY;\n\n\tfor (const value of samples) {\n\t\tsum += value;\n\t\tif (value < min) {\n\t\t\tmin = value;\n\t\t}\n\t\tif (value > max) {\n\t\t\tmax = value;\n\t\t}\n\t}\n\n\treturn {\n\t\tlast,\n\t\tavg: sum / samples.length,\n\t\tmin,\n\t\tmax,\n\t\tcount: samples.length\n\t};\n}\n\n/**\n * Dependency graph sorting options used for diagnostics labels.\n */\ninterface SortDependenciesOptions<T extends { key: FrameKey; order: number }> {\n\tgraphName: string;\n\tgetItemLabel: (item: T) => string;\n\tisKnownExternalDependency?: (key: FrameKey) => boolean;\n}\n\n/**\n * Deterministically sorts dependency keys for stable traversal and diagnostics.\n */\nfunction sortDependencyKeys(keys: Iterable<FrameKey>): FrameKey[] {\n\treturn Array.from(keys).sort((a, b) => frameKeyToString(a).localeCompare(frameKeyToString(b)));\n}\n\n/**\n * Finds one deterministic cycle path in the directed dependency graph.\n */\nfunction findDependencyCycle<T extends { key: FrameKey; order: number }>(\n\titems: T[],\n\tedges: ReadonlyMap<FrameKey, ReadonlySet<FrameKey>>\n): FrameKey[] | null {\n\tconst visitState = new Map<FrameKey, 0 | 1 | 2>();\n\tconst stack: FrameKey[] = [];\n\tlet cycle: FrameKey[] | null = null;\n\tconst sortedItems = [...items].sort((a, b) => a.order - b.order);\n\n\tconst visit = (key: FrameKey): boolean => {\n\t\tvisitState.set(key, 1);\n\t\tstack.push(key);\n\n\t\tfor (const childKey of sortDependencyKeys(edges.get(key) ?? [])) {\n\t\t\tconst state = visitState.get(childKey) ?? 0;\n\t\t\tif (state === 0) {\n\t\t\t\tif (visit(childKey)) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (state === 1) {\n\t\t\t\tconst cycleStartIndex = stack.findIndex((entry) => entry === childKey);\n\t\t\t\tconst cyclePath = cycleStartIndex === -1 ? [childKey] : stack.slice(cycleStartIndex);\n\t\t\t\tcycle = [...cyclePath, childKey];\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\tstack.pop();\n\t\tvisitState.set(key, 2);\n\t\treturn false;\n\t};\n\n\tfor (const item of sortedItems) {\n\t\tif ((visitState.get(item.key) ?? 0) !== 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (visit(item.key)) {\n\t\t\treturn cycle;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n/**\n * Topologically sorts items by `before`/`after` dependencies.\n *\n * Throws deterministic errors when dependencies are missing or cyclic.\n */\nfunction sortByDependencies<T extends { key: FrameKey; order: number }>(\n\titems: T[],\n\tgetBefore: (item: T) => Iterable<FrameKey>,\n\tgetAfter: (item: T) => Iterable<FrameKey>,\n\toptions: SortDependenciesOptions<T>\n): T[] {\n\tconst itemsByKey = new Map<FrameKey, T>();\n\tfor (const item of items) {\n\t\titemsByKey.set(item.key, item);\n\t}\n\n\tconst indegree = new Map<FrameKey, number>();\n\tconst edges = new Map<FrameKey, Set<FrameKey>>();\n\n\tfor (const item of items) {\n\t\tindegree.set(item.key, 0);\n\t\tedges.set(item.key, new Set());\n\t}\n\n\tfor (const item of items) {\n\t\tfor (const dependencyKey of getAfter(item)) {\n\t\t\tif (!itemsByKey.has(dependencyKey)) {\n\t\t\t\tif (options.isKnownExternalDependency?.(dependencyKey)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${options.graphName} dependency error: ${options.getItemLabel(item)} references missing dependency \"${frameKeyToString(dependencyKey)}\" in \"after\".`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tedges.get(dependencyKey)?.add(item.key);\n\t\t\tindegree.set(item.key, (indegree.get(item.key) ?? 0) + 1);\n\t\t}\n\n\t\tfor (const dependencyKey of getBefore(item)) {\n\t\t\tif (!itemsByKey.has(dependencyKey)) {\n\t\t\t\tif (options.isKnownExternalDependency?.(dependencyKey)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${options.graphName} dependency error: ${options.getItemLabel(item)} references missing dependency \"${frameKeyToString(dependencyKey)}\" in \"before\".`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tedges.get(item.key)?.add(dependencyKey);\n\t\t\tindegree.set(dependencyKey, (indegree.get(dependencyKey) ?? 0) + 1);\n\t\t}\n\t}\n\n\tconst queue = items.filter((item) => (indegree.get(item.key) ?? 0) === 0);\n\tqueue.sort((a, b) => a.order - b.order);\n\n\tconst ordered: T[] = [];\n\twhile (queue.length > 0) {\n\t\tconst current = queue.shift();\n\t\tif (!current) {\n\t\t\tbreak;\n\t\t}\n\n\t\tordered.push(current);\n\n\t\tfor (const childKey of edges.get(current.key) ?? []) {\n\t\t\tconst nextDegree = (indegree.get(childKey) ?? 0) - 1;\n\t\t\tindegree.set(childKey, nextDegree);\n\t\t\tif (nextDegree === 0) {\n\t\t\t\tconst child = itemsByKey.get(childKey);\n\t\t\t\tif (child) {\n\t\t\t\t\tqueue.push(child);\n\t\t\t\t\tqueue.sort((a, b) => a.order - b.order);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif (ordered.length !== items.length) {\n\t\tconst cycle = findDependencyCycle(items, edges);\n\t\tif (cycle) {\n\t\t\tthrow new Error(\n\t\t\t\t`${options.graphName} dependency cycle detected: ${cycle.map((key) => frameKeyToString(key)).join(' -> ')}`\n\t\t\t);\n\t\t}\n\n\t\tthrow new Error(`${options.graphName} dependency resolution failed.`);\n\t}\n\n\treturn ordered;\n}\n\n/**\n * Runtime registry that stores frame tasks/stages and drives render scheduling.\n */\nexport interface FrameRegistry {\n\t/**\n\t * Registers a frame callback in the scheduler.\n\t */\n\tregister: (\n\t\tkeyOrCallback: FrameKey | FrameCallback,\n\t\tcallbackOrOptions?: FrameCallback | UseFrameOptions,\n\t\tmaybeOptions?: UseFrameOptions\n\t) => RegisteredFrameTask;\n\t/**\n\t * Executes one scheduler run.\n\t */\n\trun: (state: FrameState) => void;\n\t/**\n\t * Marks frame as invalidated for `on-demand` mode.\n\t */\n\tinvalidate: (token?: FrameInvalidationToken) => void;\n\t/**\n\t * Requests a single render in `manual` mode.\n\t */\n\tadvance: () => void;\n\t/**\n\t * Returns whether renderer should submit a frame now.\n\t */\n\tshouldRender: () => boolean;\n\t/**\n\t * Resets one-frame invalidation/advance flags.\n\t */\n\tendFrame: () => void;\n\t/**\n\t * Sets render scheduling mode.\n\t */\n\tsetRenderMode: (mode: RenderMode) => void;\n\t/**\n\t * Enables or disables automatic rendering entirely.\n\t */\n\tsetAutoRender: (enabled: boolean) => void;\n\t/**\n\t * Sets maximum allowed delta passed to frame tasks.\n\t */\n\tsetMaxDelta: (value: number) => void;\n\t/**\n\t * Enables/disables frame profiling.\n\t */\n\tsetProfilingEnabled: (enabled: boolean) => void;\n\t/**\n\t * Sets profiling history window (in frames).\n\t */\n\tsetProfilingWindow: (window: number) => void;\n\t/**\n\t * Clears collected profiling samples.\n\t */\n\tresetProfiling: () => void;\n\t/**\n\t * Enables/disables diagnostics capture.\n\t */\n\tsetDiagnosticsEnabled: (enabled: boolean) => void;\n\t/**\n\t * Returns current render mode.\n\t */\n\tgetRenderMode: () => RenderMode;\n\t/**\n\t * Returns whether automatic rendering is enabled.\n\t */\n\tgetAutoRender: () => boolean;\n\t/**\n\t * Returns current max delta clamp.\n\t */\n\tgetMaxDelta: () => number;\n\t/**\n\t * Returns profiling toggle state.\n\t */\n\tgetProfilingEnabled: () => boolean;\n\t/**\n\t * Returns active profiling history window (in frames).\n\t */\n\tgetProfilingWindow: () => number;\n\t/**\n\t * Returns aggregated profiling snapshot.\n\t */\n\tgetProfilingSnapshot: () => FrameProfilingSnapshot | null;\n\t/**\n\t * Returns diagnostics toggle state.\n\t */\n\tgetDiagnosticsEnabled: () => boolean;\n\t/**\n\t * Returns last run timings snapshot when diagnostics are enabled.\n\t */\n\tgetLastRunTimings: () => FrameRunTimings | null;\n\t/**\n\t * Returns dependency-sorted schedule snapshot.\n\t */\n\tgetSchedule: () => FrameScheduleSnapshot;\n\t/**\n\t * Creates or updates a stage.\n\t */\n\tcreateStage: (\n\t\tkey: FrameKey,\n\t\toptions?: {\n\t\t\tbefore?: (FrameKey | FrameStage) | (FrameKey | FrameStage)[];\n\t\t\tafter?: (FrameKey | FrameStage) | (FrameKey | FrameStage)[];\n\t\t\tcallback?: FrameStageCallback | null;\n\t\t}\n\t) => FrameStage;\n\t/**\n\t * Reads stage metadata by key.\n\t */\n\tgetStage: (key: FrameKey) => FrameStage | undefined;\n\t/**\n\t * Removes all tasks from all stages.\n\t */\n\tclear: () => void;\n}\n\n/**\n * Creates a frame registry used by `FragCanvas` and `useFrame`.\n *\n * @param options - Initial scheduler options.\n * @returns Mutable frame registry instance.\n */\nexport function createFrameRegistry(options?: {\n\trenderMode?: RenderMode;\n\tautoRender?: boolean;\n\tmaxDelta?: number;\n\tprofilingEnabled?: boolean;\n\tprofilingWindow?: number;\n\tdiagnosticsEnabled?: boolean;\n}): FrameRegistry {\n\tlet renderMode: RenderMode = options?.renderMode ?? 'always';\n\tlet autoRender = options?.autoRender ?? true;\n\tlet maxDelta = options?.maxDelta ?? 0.1;\n\tlet profilingEnabled = options?.profilingEnabled ?? options?.diagnosticsEnabled ?? false;\n\tlet profilingWindow = options?.profilingWindow ?? 120;\n\tlet lastRunTimings: FrameRunTimings | null = null;\n\tconst profilingHistory: FrameRunTimings[] = [];\n\tlet hasUntokenizedInvalidation = true;\n\tconst invalidationTokens = new Set<FrameInvalidationToken>();\n\tlet shouldAdvance = false;\n\tlet orderCounter = 0;\n\n\tconst assertMaxDelta = (value: number): number => {\n\t\tif (!Number.isFinite(value) || value <= 0) {\n\t\t\tthrow new Error('maxDelta must be a finite number greater than 0');\n\t\t}\n\t\treturn value;\n\t};\n\n\tconst assertProfilingWindow = (value: number): number => {\n\t\tif (!Number.isFinite(value) || value <= 0) {\n\t\t\tthrow new Error('profilingWindow must be a finite number greater than 0');\n\t\t}\n\t\treturn Math.floor(value);\n\t};\n\n\tmaxDelta = assertMaxDelta(maxDelta);\n\tprofilingWindow = assertProfilingWindow(profilingWindow);\n\n\tconst stages = new Map<FrameKey, InternalStage>();\n\tlet scheduleDirty = true;\n\tlet sortedStages: InternalStage[] = [];\n\tconst sortedTasksByStage = new Map<FrameKey, InternalTask[]>();\n\tlet scheduleSnapshot: FrameScheduleSnapshot = { stages: [] };\n\n\tconst markScheduleDirty = (): void => {\n\t\tscheduleDirty = true;\n\t};\n\n\tconst syncSchedule = (): void => {\n\t\tif (!scheduleDirty) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst stageList = sortByDependencies(\n\t\t\tArray.from(stages.values()),\n\t\t\t(stage) => stage.before,\n\t\t\t(stage) => stage.after,\n\t\t\t{\n\t\t\t\tgraphName: 'Frame stage graph',\n\t\t\t\tgetItemLabel: (stage) => `stage \"${frameKeyToString(stage.key)}\"`\n\t\t\t}\n\t\t);\n\t\tconst nextTasksByStage = new Map<FrameKey, InternalTask[]>();\n\t\tconst globalTaskKeys = new Set<FrameKey>();\n\t\tfor (const stage of stageList) {\n\t\t\tfor (const task of stage.tasks.values()) {\n\t\t\t\tglobalTaskKeys.add(task.task.key);\n\t\t\t}\n\t\t}\n\n\t\tfor (const stage of stageList) {\n\t\t\tconst taskList = sortByDependencies(\n\t\t\t\tArray.from(stage.tasks.values()).map((task) => ({\n\t\t\t\t\tkey: task.task.key,\n\t\t\t\t\torder: task.order,\n\t\t\t\t\ttask\n\t\t\t\t})),\n\t\t\t\t(task) => task.task.before,\n\t\t\t\t(task) => task.task.after,\n\t\t\t\t{\n\t\t\t\t\tgraphName: `Frame task graph for stage \"${frameKeyToString(stage.key)}\"`,\n\t\t\t\t\tgetItemLabel: (task) => `task \"${frameKeyToString(task.key)}\"`,\n\t\t\t\t\tisKnownExternalDependency: (key) => globalTaskKeys.has(key)\n\t\t\t\t}\n\t\t\t).map((task) => task.task);\n\t\t\tnextTasksByStage.set(stage.key, taskList);\n\t\t}\n\n\t\tsortedStages = stageList;\n\t\tsortedTasksByStage.clear();\n\t\tfor (const [stageKey, taskList] of nextTasksByStage) {\n\t\t\tsortedTasksByStage.set(stageKey, taskList);\n\t\t}\n\n\t\tscheduleSnapshot = {\n\t\t\tstages: sortedStages.map((stage) => ({\n\t\t\t\tkey: frameKeyToString(stage.key),\n\t\t\t\ttasks: (sortedTasksByStage.get(stage.key) ?? []).map((task) =>\n\t\t\t\t\tframeKeyToString(task.task.key)\n\t\t\t\t)\n\t\t\t}))\n\t\t};\n\n\t\tscheduleDirty = false;\n\t};\n\n\tconst pushProfile = (timings: FrameRunTimings): void => {\n\t\tprofilingHistory.push(timings);\n\t\twhile (profilingHistory.length > profilingWindow) {\n\t\t\tprofilingHistory.shift();\n\t\t}\n\t};\n\n\tconst clearProfiling = (): void => {\n\t\tprofilingHistory.length = 0;\n\t\tlastRunTimings = null;\n\t};\n\n\tconst buildProfilingSnapshot = (): FrameProfilingSnapshot | null => {\n\t\tif (!profilingEnabled) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst stageBuckets = new Map<\n\t\t\tstring,\n\t\t\t{\n\t\t\t\tdurations: number[];\n\t\t\t\ttaskDurations: Map<string, number[]>;\n\t\t\t}\n\t\t>();\n\t\tconst totalDurations: number[] = [];\n\n\t\tfor (const frame of profilingHistory) {\n\t\t\ttotalDurations.push(frame.total);\n\t\t\tfor (const [stageKey, stageTiming] of Object.entries(frame.stages)) {\n\t\t\t\tconst stageBucket = stageBuckets.get(stageKey) ?? {\n\t\t\t\t\tdurations: [],\n\t\t\t\t\ttaskDurations: new Map<string, number[]>()\n\t\t\t\t};\n\t\t\t\tstageBucket.durations.push(stageTiming.duration);\n\n\t\t\t\tfor (const [taskKey, taskDuration] of Object.entries(stageTiming.tasks)) {\n\t\t\t\t\tconst bucket = stageBucket.taskDurations.get(taskKey) ?? [];\n\t\t\t\t\tbucket.push(taskDuration);\n\t\t\t\t\tstageBucket.taskDurations.set(taskKey, bucket);\n\t\t\t\t}\n\n\t\t\t\tstageBuckets.set(stageKey, stageBucket);\n\t\t\t}\n\t\t}\n\n\t\tconst stagesSnapshot: FrameProfilingSnapshot['stages'] = {};\n\t\tfor (const [stageKey, stageBucket] of stageBuckets) {\n\t\t\tconst lastStageDuration = lastRunTimings?.stages[stageKey]?.duration ?? 0;\n\t\t\tconst taskSnapshot: Record<string, FrameTimingStats> = {};\n\t\t\tfor (const [taskKey, taskDurations] of stageBucket.taskDurations) {\n\t\t\t\tconst lastTaskDuration = lastRunTimings?.stages[stageKey]?.tasks[taskKey] ?? 0;\n\t\t\t\ttaskSnapshot[taskKey] = buildTimingStats(taskDurations, lastTaskDuration);\n\t\t\t}\n\n\t\t\tstagesSnapshot[stageKey] = {\n\t\t\t\ttimings: buildTimingStats(stageBucket.durations, lastStageDuration),\n\t\t\t\ttasks: taskSnapshot\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\twindow: profilingWindow,\n\t\t\tframeCount: profilingHistory.length,\n\t\t\tlastFrame: lastRunTimings,\n\t\t\ttotal: buildTimingStats(totalDurations, lastRunTimings?.total ?? 0),\n\t\t\tstages: stagesSnapshot\n\t\t};\n\t};\n\n\tconst ensureStage = (\n\t\tstageReference: FrameKey | FrameStage,\n\t\tstageOptions?: {\n\t\t\tbefore?: (FrameKey | FrameStage)[];\n\t\t\tafter?: (FrameKey | FrameStage)[];\n\t\t\tcallback?: FrameStageCallback | null;\n\t\t}\n\t): InternalStage => {\n\t\tconst stageKey = toStageKey(stageReference);\n\t\tconst existing = stages.get(stageKey);\n\t\tif (existing) {\n\t\t\tif (stageOptions?.before !== undefined) {\n\t\t\t\texisting.before = new Set(stageOptions.before.map((entry) => toStageKey(entry)));\n\t\t\t\tmarkScheduleDirty();\n\t\t\t}\n\t\t\tif (stageOptions?.after !== undefined) {\n\t\t\t\texisting.after = new Set(stageOptions.after.map((entry) => toStageKey(entry)));\n\t\t\t\tmarkScheduleDirty();\n\t\t\t}\n\t\t\tif (stageOptions && Object.prototype.hasOwnProperty.call(stageOptions, 'callback')) {\n\t\t\t\texisting.callback = stageOptions.callback ?? DEFAULT_STAGE_CALLBACK;\n\t\t\t}\n\t\t\treturn existing;\n\t\t}\n\n\t\tconst stage: InternalStage = {\n\t\t\tkey: stageKey,\n\t\t\torder: orderCounter++,\n\t\t\tstarted: true,\n\t\t\tbefore: new Set((stageOptions?.before ?? []).map((entry) => toStageKey(entry))),\n\t\t\tafter: new Set((stageOptions?.after ?? []).map((entry) => toStageKey(entry))),\n\t\t\tcallback: stageOptions?.callback ?? DEFAULT_STAGE_CALLBACK,\n\t\t\ttasks: new Map()\n\t\t};\n\t\tstages.set(stageKey, stage);\n\t\tmarkScheduleDirty();\n\t\treturn stage;\n\t};\n\n\tensureStage(MAIN_STAGE_KEY);\n\n\tconst resolveEffectiveRunning = (task: InternalTask): boolean => {\n\t\tconst running = task.started && (task.running?.() ?? true);\n\t\tif (task.lastRunning !== running) {\n\t\t\ttask.lastRunning = running;\n\t\t\ttask.startedStoreSet(running);\n\t\t}\n\t\treturn running;\n\t};\n\n\tconst hasPendingInvalidation = (): boolean => {\n\t\treturn hasUntokenizedInvalidation || invalidationTokens.size > 0;\n\t};\n\n\tconst invalidateWithToken = (token?: FrameInvalidationToken): void => {\n\t\tif (token === undefined) {\n\t\t\thasUntokenizedInvalidation = true;\n\t\t\treturn;\n\t\t}\n\n\t\tinvalidationTokens.add(token);\n\t};\n\n\tconst applyTaskInvalidation = (task: InternalTask): void => {\n\t\tconst config = task.invalidation;\n\t\tif (config.mode === 'never') {\n\t\t\treturn;\n\t\t}\n\n\t\tif (config.mode === 'always') {\n\t\t\tconst token = resolveInvalidationToken(config.token);\n\t\t\tinvalidateWithToken(token ?? task.task.key);\n\t\t\treturn;\n\t\t}\n\n\t\tconst token = resolveInvalidationToken(config.token);\n\t\tif (token === null) {\n\t\t\tconfig.hasToken = false;\n\t\t\tconfig.lastToken = null;\n\t\t\treturn;\n\t\t}\n\n\t\tconst changed = !config.hasToken || config.lastToken !== token;\n\t\tconfig.hasToken = true;\n\t\tconfig.lastToken = token;\n\t\tif (changed) {\n\t\t\tinvalidateWithToken(token);\n\t\t}\n\t};\n\n\treturn {\n\t\tregister(keyOrCallback, callbackOrOptions, maybeOptions) {\n\t\t\tconst key =\n\t\t\t\ttypeof keyOrCallback === 'function'\n\t\t\t\t\t? (Symbol('motiongpu-task') as FrameKey)\n\t\t\t\t\t: (keyOrCallback as FrameKey);\n\t\t\tconst callback =\n\t\t\t\ttypeof keyOrCallback === 'function' ? keyOrCallback : (callbackOrOptions as FrameCallback);\n\t\t\tconst taskOptions =\n\t\t\t\ttypeof keyOrCallback === 'function'\n\t\t\t\t\t? ((callbackOrOptions as UseFrameOptions | undefined) ?? {})\n\t\t\t\t\t: (maybeOptions ?? {});\n\n\t\t\tif (typeof callback !== 'function') {\n\t\t\t\tthrow new Error('useFrame requires a callback');\n\t\t\t}\n\n\t\t\tconst before = asArray(taskOptions.before);\n\t\t\tconst after = asArray(taskOptions.after);\n\t\t\tconst inferredStage = [...before, ...after].find(\n\t\t\t\t(entry) => typeof entry === 'object' && entry !== null && 'stage' in entry\n\t\t\t) as FrameTask | undefined;\n\t\t\tconst stageKey = taskOptions.stage\n\t\t\t\t? toStageKey(taskOptions.stage)\n\t\t\t\t: (inferredStage?.stage ?? MAIN_STAGE_KEY);\n\n\t\t\tconst stage = ensureStage(stageKey);\n\t\t\tconst startedWritable: CurrentWritable<boolean> = createCurrentWritable(\n\t\t\t\ttaskOptions.autoStart ?? true\n\t\t\t);\n\n\t\t\tconst internalTask: InternalTask = {\n\t\t\t\ttask: { key, stage: stage.key },\n\t\t\t\tcallback,\n\t\t\t\torder: orderCounter++,\n\t\t\t\tstarted: taskOptions.autoStart ?? true,\n\t\t\t\tlastRunning: taskOptions.autoStart ?? true,\n\t\t\t\tstartedStoreSet: startedWritable.set,\n\t\t\t\tstartedStore: { subscribe: startedWritable.subscribe },\n\t\t\t\tbefore: new Set(before.map((entry) => toTaskKey(entry))),\n\t\t\t\tafter: new Set(after.map((entry) => toTaskKey(entry))),\n\t\t\t\tinvalidation: normalizeTaskInvalidation(key, taskOptions)\n\t\t\t};\n\n\t\t\tif (taskOptions.running) {\n\t\t\t\tinternalTask.running = taskOptions.running;\n\t\t\t}\n\n\t\t\tstage.tasks.set(key, internalTask);\n\t\t\tmarkScheduleDirty();\n\t\t\tinternalTask.startedStoreSet(resolveEffectiveRunning(internalTask));\n\n\t\t\tconst start = () => {\n\t\t\t\tinternalTask.started = true;\n\t\t\t\tresolveEffectiveRunning(internalTask);\n\t\t\t};\n\n\t\t\tconst stop = () => {\n\t\t\t\tinternalTask.started = false;\n\t\t\t\tresolveEffectiveRunning(internalTask);\n\t\t\t};\n\n\t\t\treturn {\n\t\t\t\ttask: internalTask.task,\n\t\t\t\tstart,\n\t\t\t\tstop,\n\t\t\t\tstarted: internalTask.startedStore,\n\t\t\t\tunsubscribe: () => {\n\t\t\t\t\tconst current = stage.tasks.get(key);\n\t\t\t\t\tif (current === internalTask && stage.tasks.delete(key)) {\n\t\t\t\t\t\tmarkScheduleDirty();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t},\n\t\trun(state) {\n\t\t\tconst clampedDelta = Math.min(state.delta, maxDelta);\n\t\t\tconst frameState =\n\t\t\t\tclampedDelta === state.delta\n\t\t\t\t\t? state\n\t\t\t\t\t: {\n\t\t\t\t\t\t\t...state,\n\t\t\t\t\t\t\tdelta: clampedDelta\n\t\t\t\t\t\t};\n\t\t\tsyncSchedule();\n\t\t\tconst frameStart = profilingEnabled ? performance.now() : 0;\n\t\t\tconst stageTimings: FrameRunTimings['stages'] = {};\n\n\t\t\tfor (const stage of sortedStages) {\n\t\t\t\tif (!stage.started) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tconst stageStart = profilingEnabled ? performance.now() : 0;\n\t\t\t\tconst taskTimings: Record<string, number> = {};\n\t\t\t\tconst taskList = sortedTasksByStage.get(stage.key) ?? [];\n\n\t\t\t\tstage.callback(frameState, () => {\n\t\t\t\t\tfor (const task of taskList) {\n\t\t\t\t\t\tif (!resolveEffectiveRunning(task)) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst taskStart = profilingEnabled ? performance.now() : 0;\n\n\t\t\t\t\t\ttask.callback(frameState);\n\t\t\t\t\t\tif (profilingEnabled) {\n\t\t\t\t\t\t\ttaskTimings[frameKeyToString(task.task.key)] = performance.now() - taskStart;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tapplyTaskInvalidation(task);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (profilingEnabled) {\n\t\t\t\t\tstageTimings[frameKeyToString(stage.key)] = {\n\t\t\t\t\t\tduration: performance.now() - stageStart,\n\t\t\t\t\t\ttasks: taskTimings\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (profilingEnabled) {\n\t\t\t\tconst timings = {\n\t\t\t\t\ttotal: performance.now() - frameStart,\n\t\t\t\t\tstages: stageTimings\n\t\t\t\t};\n\t\t\t\tlastRunTimings = timings;\n\t\t\t\tpushProfile(timings);\n\t\t\t}\n\t\t},\n\t\tinvalidate(token) {\n\t\t\tinvalidateWithToken(token);\n\t\t},\n\t\tadvance() {\n\t\t\tshouldAdvance = true;\n\t\t\tinvalidateWithToken();\n\t\t},\n\t\tshouldRender() {\n\t\t\tif (!autoRender) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (renderMode === 'always') {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tif (renderMode === 'on-demand') {\n\t\t\t\treturn shouldAdvance || hasPendingInvalidation();\n\t\t\t}\n\n\t\t\treturn shouldAdvance;\n\t\t},\n\t\tendFrame() {\n\t\t\thasUntokenizedInvalidation = false;\n\t\t\tinvalidationTokens.clear();\n\t\t\tshouldAdvance = false;\n\t\t},\n\t\tsetRenderMode(mode) {\n\t\t\tif (renderMode === mode) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\trenderMode = mode;\n\t\t\tshouldAdvance = false;\n\t\t\tif (mode === 'on-demand') {\n\t\t\t\tinvalidateWithToken(RENDER_MODE_INVALIDATION_TOKEN);\n\t\t\t}\n\t\t},\n\t\tsetAutoRender(enabled) {\n\t\t\tautoRender = enabled;\n\t\t},\n\t\tsetMaxDelta(value) {\n\t\t\tmaxDelta = assertMaxDelta(value);\n\t\t},\n\t\tsetProfilingEnabled(enabled) {\n\t\t\tprofilingEnabled = enabled;\n\t\t\tif (!enabled) {\n\t\t\t\tclearProfiling();\n\t\t\t}\n\t\t},\n\t\tsetProfilingWindow(window) {\n\t\t\tprofilingWindow = assertProfilingWindow(window);\n\t\t\twhile (profilingHistory.length > profilingWindow) {\n\t\t\t\tprofilingHistory.shift();\n\t\t\t}\n\t\t},\n\t\tresetProfiling() {\n\t\t\tclearProfiling();\n\t\t},\n\t\tsetDiagnosticsEnabled(enabled) {\n\t\t\tprofilingEnabled = enabled;\n\t\t\tif (!enabled) {\n\t\t\t\tclearProfiling();\n\t\t\t}\n\t\t},\n\t\tgetRenderMode() {\n\t\t\treturn renderMode;\n\t\t},\n\t\tgetAutoRender() {\n\t\t\treturn autoRender;\n\t\t},\n\t\tgetMaxDelta() {\n\t\t\treturn maxDelta;\n\t\t},\n\t\tgetProfilingEnabled() {\n\t\t\treturn profilingEnabled;\n\t\t},\n\t\tgetProfilingWindow() {\n\t\t\treturn profilingWindow;\n\t\t},\n\t\tgetProfilingSnapshot() {\n\t\t\treturn buildProfilingSnapshot();\n\t\t},\n\t\tgetDiagnosticsEnabled() {\n\t\t\treturn profilingEnabled;\n\t\t},\n\t\tgetLastRunTimings() {\n\t\t\treturn lastRunTimings;\n\t\t},\n\t\tgetSchedule() {\n\t\t\tsyncSchedule();\n\t\t\treturn scheduleSnapshot;\n\t\t},\n\t\tcreateStage(key, options) {\n\t\t\tconst stageOptions: Parameters<typeof ensureStage>[1] | undefined = options\n\t\t\t\t? {\n\t\t\t\t\t\t...(Object.prototype.hasOwnProperty.call(options, 'before')\n\t\t\t\t\t\t\t? { before: asArray(options.before) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t...(Object.prototype.hasOwnProperty.call(options, 'after')\n\t\t\t\t\t\t\t? { after: asArray(options.after) }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t\t...(Object.prototype.hasOwnProperty.call(options, 'callback')\n\t\t\t\t\t\t\t? { callback: options.callback ?? null }\n\t\t\t\t\t\t\t: {})\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t\tconst stage = ensureStage(key, stageOptions);\n\t\t\treturn { key: stage.key };\n\t\t},\n\t\tgetStage(key) {\n\t\t\tconst stage = stages.get(key);\n\t\t\tif (!stage) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn { key: stage.key };\n\t\t},\n\t\tclear() {\n\t\t\tfor (const stage of stages.values()) {\n\t\t\t\tstage.tasks.clear();\n\t\t\t}\n\t\t\tmarkScheduleDirty();\n\t\t}\n\t};\n}\n"],"mappings":"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"}
@@ -9,12 +9,15 @@ export { createCurrentWritable } from './current-value.js';
9
9
  export { createFrameRegistry } from './frame-registry.js';
10
10
  export { createMotionGPURuntimeLoop } from './runtime-loop.js';
11
11
  export { loadTexturesFromUrls } from './texture-loader.js';
12
- export { BlitPass, CopyPass, ShaderPass } from '../passes/index.js';
12
+ export { BlitPass, CopyPass, ShaderPass, ComputePass, PingPongComputePass } from '../passes/index.js';
13
13
  export type { CurrentReadable, CurrentWritable, Subscribable } from './current-value.js';
14
14
  export type { MotionGPUErrorCode, MotionGPUErrorContext, MotionGPUErrorPhase, MotionGPUErrorReport, MotionGPUErrorSeverity, MotionGPUErrorSource, MotionGPUErrorSourceLine } from './error-report.js';
15
15
  export type { FrameCallback, FrameKey, FrameProfilingSnapshot, FrameRegistry, FrameRunTimings, FrameScheduleSnapshot, FrameStage, FrameStageCallback, FrameTask, FrameTaskInvalidation, FrameTaskInvalidationToken, FrameTimingStats, UseFrameOptions, UseFrameResult } from './frame-registry.js';
16
16
  export type { FragMaterial, FragMaterialInput, MaterialDefineValue, MaterialDefines, MaterialIncludes, ResolvedMaterial, TypedMaterialDefineValue } from './material.js';
17
17
  export type { MotionGPURuntimeLoop, MotionGPURuntimeLoopOptions } from './runtime-loop.js';
18
18
  export type { LoadedTexture, TextureDecodeOptions, TextureLoadOptions } from './texture-loader.js';
19
- export type { FrameInvalidationToken, FrameState, OutputColorSpace, RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot, RenderMode, RenderTarget, RenderTargetDefinition, RenderTargetDefinitionMap, TextureData, TextureDefinition, TextureDefinitionMap, TextureMap, TextureSource, TextureUpdateMode, TextureValue, TypedUniform, UniformLayout, UniformLayoutEntry, UniformMap, UniformMat4Value, UniformType, UniformValue } from './types.js';
19
+ export type { FrameInvalidationToken, FrameState, OutputColorSpace, AnyPass, ComputePassLike, RenderPass, RenderPassContext, RenderPassFlags, RenderPassInputSlot, RenderPassOutputSlot, RenderMode, RenderTarget, RenderTargetDefinition, RenderTargetDefinitionMap, TextureData, TextureDefinition, TextureDefinitionMap, TextureMap, TextureSource, TextureUpdateMode, TextureValue, TypedUniform, UniformLayout, UniformLayoutEntry, UniformMap, UniformMat4Value, UniformType, UniformValue } from './types.js';
20
+ export type { StorageBufferAccess, StorageBufferDefinition, StorageBufferDefinitionMap, StorageBufferType, ComputePassContext } from './types.js';
21
+ export type { ComputePassOptions, ComputeDispatchContext } from '../passes/ComputePass.js';
22
+ export type { PingPongComputePassOptions } from '../passes/PingPongComputePass.js';
20
23
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/core/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACpE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACzF,YAAY,EACX,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACX,aAAa,EACb,QAAQ,EACR,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,kBAAkB,EAClB,SAAS,EACT,qBAAqB,EACrB,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACX,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACnG,YAAY,EACX,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,YAAY,EACZ,sBAAsB,EACtB,yBAAyB,EACzB,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/core/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,mBAAmB,EACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACzF,YAAY,EACX,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACpB,wBAAwB,EACxB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACX,aAAa,EACb,QAAQ,EACR,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,UAAU,EACV,kBAAkB,EAClB,SAAS,EACT,qBAAqB,EACrB,0BAA0B,EAC1B,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACX,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,wBAAwB,EACxB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC3F,YAAY,EAAE,aAAa,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACnG,YAAY,EACX,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,OAAO,EACP,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,UAAU,EACV,YAAY,EACZ,sBAAsB,EACtB,yBAAyB,EACzB,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,MAAM,YAAY,CAAC;AACpB,YAAY,EACX,mBAAmB,EACnB,uBAAuB,EACvB,0BAA0B,EAC1B,iBAAiB,EACjB,kBAAkB,EAClB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAC3F,YAAY,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC"}
@@ -7,5 +7,7 @@ import { loadTexturesFromUrls } from "./texture-loader.js";
7
7
  import { BlitPass } from "../passes/BlitPass.js";
8
8
  import { CopyPass } from "../passes/CopyPass.js";
9
9
  import { ShaderPass } from "../passes/ShaderPass.js";
10
+ import { ComputePass } from "../passes/ComputePass.js";
11
+ import { PingPongComputePass } from "../passes/PingPongComputePass.js";
10
12
  import "../passes/index.js";
11
- export { BlitPass, CopyPass, ShaderPass, createCurrentWritable, createFrameRegistry, createMotionGPURuntimeLoop, defineMaterial, loadTexturesFromUrls, resolveMaterial, toMotionGPUErrorReport };
13
+ export { BlitPass, ComputePass, CopyPass, PingPongComputePass, ShaderPass, createCurrentWritable, createFrameRegistry, createMotionGPURuntimeLoop, defineMaterial, loadTexturesFromUrls, resolveMaterial, toMotionGPUErrorReport };
@@ -1 +1 @@
1
- {"version":3,"file":"material-preprocess.d.ts","sourceRoot":"","sources":["../../src/lib/core/material-preprocess.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAEhB,MAAM,eAAe,CAAC;AAIvB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC;;OAEG;IACH,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAqCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,SAAS,MAAM,EACzD,OAAO,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG,SAAS,GAC9C,eAAe,CAAC,UAAU,CAAC,CA0B7B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,SAAS,MAAM,EAC3D,QAAQ,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,SAAS,GACjD,gBAAgB,CAAC,WAAW,CAAC,CAY/B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAyB5E;AA0DD;;GAEG;AACH,wBAAgB,0BAA0B,CACzC,UAAU,SAAS,MAAM,EACzB,WAAW,SAAS,MAAM,EACzB,KAAK,EAAE;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACzC,GAAG,4BAA4B,CA6C/B"}
1
+ {"version":3,"file":"material-preprocess.d.ts","sourceRoot":"","sources":["../../src/lib/core/material-preprocess.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAEhB,MAAM,eAAe,CAAC;AAIvB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC;;OAEG;IACH,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IACxC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;AAEnE;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,eAAe,CAAC;IACzB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;CAC1B;AAqCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,SAAS,MAAM,EACzD,OAAO,EAAE,eAAe,CAAC,UAAU,CAAC,GAAG,SAAS,GAC9C,eAAe,CAAC,UAAU,CAAC,CA0B7B;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,SAAS,MAAM,EAC3D,QAAQ,EAAE,gBAAgB,CAAC,WAAW,CAAC,GAAG,SAAS,GACjD,gBAAgB,CAAC,WAAW,CAAC,CAY/B;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAyB5E;AAoED;;GAEG;AACH,wBAAgB,0BAA0B,CACzC,UAAU,SAAS,MAAM,EACzB,WAAW,SAAS,MAAM,EACzB,KAAK,EAAE;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACtC,QAAQ,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACzC,GAAG,4BAA4B,CA8C/B"}
@@ -65,7 +65,7 @@ function toDefineLine(key, value) {
65
65
  if (value.type === "i32") return `const ${key}: i32 = ${value.value};`;
66
66
  return `const ${key}: u32 = ${value.value}u;`;
67
67
  }
68
- function expandChunk(source, kind, includeName, includes, stack) {
68
+ function expandChunk(source, kind, includeName, includes, stack, expandedIncludes) {
69
69
  const sourceLines = source.split("\n");
70
70
  const lines = [];
71
71
  const mapEntries = [];
@@ -88,7 +88,9 @@ function expandChunk(source, kind, includeName, includes, stack) {
88
88
  const includeSource = includes[includeKey];
89
89
  if (!includeSource) throw new Error(`Unknown include "${includeKey}" referenced in fragment shader.`);
90
90
  if (stack.includes(includeKey)) throw new Error(`Circular include detected for "${includeKey}". Include stack: ${[...stack, includeKey].join(" -> ")}.`);
91
- const nested = expandChunk(includeSource, "include", includeKey, includes, [...stack, includeKey]);
91
+ if (expandedIncludes.has(includeKey)) continue;
92
+ expandedIncludes.add(includeKey);
93
+ const nested = expandChunk(includeSource, "include", includeKey, includes, [...stack, includeKey], expandedIncludes);
92
94
  lines.push(...nested.lines);
93
95
  mapEntries.push(...nested.mapEntries);
94
96
  }
@@ -103,7 +105,7 @@ function expandChunk(source, kind, includeName, includes, stack) {
103
105
  function preprocessMaterialFragment(input) {
104
106
  const normalizedDefines = normalizeDefines(input.defines);
105
107
  const normalizedIncludes = normalizeIncludes(input.includes);
106
- const fragmentExpanded = expandChunk(input.fragment, "fragment", void 0, normalizedIncludes, []);
108
+ const fragmentExpanded = expandChunk(input.fragment, "fragment", void 0, normalizedIncludes, [], /* @__PURE__ */ new Set());
107
109
  const defineEntries = Object.entries(normalizedDefines).sort(([a], [b]) => a.localeCompare(b));
108
110
  const lines = [];
109
111
  const defineLines = [];
@@ -1 +1 @@
1
- {"version":3,"file":"material-preprocess.js","names":[],"sources":["../../src/lib/core/material-preprocess.ts"],"sourcesContent":["import { assertUniformName } from './uniforms.js';\nimport type {\n\tMaterialDefineValue,\n\tMaterialDefines,\n\tMaterialIncludes,\n\tTypedMaterialDefineValue\n} from './material.js';\n\nconst INCLUDE_DIRECTIVE_PATTERN = /^\\s*#include\\s+<([A-Za-z_][A-Za-z0-9_]*)>\\s*$/;\n\n/**\n * Source location metadata for one generated fragment line.\n */\nexport interface MaterialSourceLocation {\n\t/**\n\t * Origin category for this generated line.\n\t */\n\tkind: 'fragment' | 'include' | 'define';\n\t/**\n\t * 1-based line in the origin source.\n\t */\n\tline: number;\n\t/**\n\t * Include chunk identifier when `kind === \"include\"`.\n\t */\n\tinclude?: string;\n\t/**\n\t * Define identifier when `kind === \"define\"`.\n\t */\n\tdefine?: string;\n}\n\n/**\n * 1-based line map from generated fragment WGSL to user source locations.\n */\nexport type MaterialLineMap = Array<MaterialSourceLocation | null>;\n\n/**\n * Preprocess output used by material resolution and diagnostics mapping.\n */\nexport interface PreprocessedMaterialFragment {\n\t/**\n\t * Final fragment source after defines/include expansion.\n\t */\n\tfragment: string;\n\t/**\n\t * 1-based generated-line source map.\n\t */\n\tlineMap: MaterialLineMap;\n\t/**\n\t * Deterministic WGSL define block used to build the final fragment source.\n\t */\n\tdefineBlockSource: string;\n}\n\nfunction normalizeTypedDefine(\n\tname: string,\n\tdefine: TypedMaterialDefineValue\n): TypedMaterialDefineValue {\n\tconst value = define.value;\n\n\tif (define.type === 'bool') {\n\t\tif (typeof value !== 'boolean') {\n\t\t\tthrow new Error(`Invalid define value for \"${name}\". bool define requires boolean value.`);\n\t\t}\n\n\t\treturn {\n\t\t\ttype: 'bool',\n\t\t\tvalue\n\t\t};\n\t}\n\n\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\tthrow new Error(`Invalid define value for \"${name}\". Numeric define must be finite.`);\n\t}\n\n\tif ((define.type === 'i32' || define.type === 'u32') && !Number.isInteger(value)) {\n\t\tthrow new Error(`Invalid define value for \"${name}\". ${define.type} define requires integer.`);\n\t}\n\n\tif (define.type === 'u32' && value < 0) {\n\t\tthrow new Error(`Invalid define value for \"${name}\". u32 define must be >= 0.`);\n\t}\n\n\treturn {\n\t\ttype: define.type,\n\t\tvalue\n\t};\n}\n\n/**\n * Validates and normalizes define entries.\n */\nexport function normalizeDefines<TDefineKey extends string>(\n\tdefines: MaterialDefines<TDefineKey> | undefined\n): MaterialDefines<TDefineKey> {\n\tconst resolved: MaterialDefines<TDefineKey> = {} as MaterialDefines<TDefineKey>;\n\n\tfor (const [name, value] of Object.entries(defines ?? {}) as Array<\n\t\t[TDefineKey, MaterialDefineValue]\n\t>) {\n\t\tassertUniformName(name);\n\n\t\tif (typeof value === 'boolean') {\n\t\t\tresolved[name] = value;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (typeof value === 'number') {\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tthrow new Error(`Invalid define value for \"${name}\". Define numbers must be finite.`);\n\t\t\t}\n\t\t\tresolved[name] = value;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalized = normalizeTypedDefine(name, value);\n\t\tresolved[name] = Object.freeze(normalized);\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Validates include map identifiers and source chunks.\n */\nexport function normalizeIncludes<TIncludeKey extends string>(\n\tincludes: MaterialIncludes<TIncludeKey> | undefined\n): MaterialIncludes<TIncludeKey> {\n\tconst resolved: MaterialIncludes<TIncludeKey> = {} as MaterialIncludes<TIncludeKey>;\n\n\tfor (const [name, source] of Object.entries(includes ?? {}) as Array<[TIncludeKey, string]>) {\n\t\tassertUniformName(name);\n\t\tif (typeof source !== 'string' || source.trim().length === 0) {\n\t\t\tthrow new Error(`Invalid include \"${name}\". Include source must be a non-empty WGSL string.`);\n\t\t}\n\t\tresolved[name] = source;\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Converts one define declaration to WGSL `const`.\n */\nexport function toDefineLine(key: string, value: MaterialDefineValue): string {\n\tif (typeof value === 'boolean') {\n\t\treturn `const ${key}: bool = ${value ? 'true' : 'false'};`;\n\t}\n\n\tif (typeof value === 'number') {\n\t\tconst valueLiteral = Number.isInteger(value) ? `${value}.0` : `${value}`;\n\t\treturn `const ${key}: f32 = ${valueLiteral};`;\n\t}\n\n\tif (value.type === 'bool') {\n\t\treturn `const ${key}: bool = ${value.value ? 'true' : 'false'};`;\n\t}\n\n\tif (value.type === 'f32') {\n\t\tconst numberValue = value.value as number;\n\t\tconst valueLiteral = Number.isInteger(numberValue) ? `${numberValue}.0` : `${numberValue}`;\n\t\treturn `const ${key}: f32 = ${valueLiteral};`;\n\t}\n\n\tif (value.type === 'i32') {\n\t\treturn `const ${key}: i32 = ${value.value};`;\n\t}\n\n\treturn `const ${key}: u32 = ${value.value}u;`;\n}\n\nfunction expandChunk(\n\tsource: string,\n\tkind: 'fragment' | 'include',\n\tincludeName: string | undefined,\n\tincludes: Record<string, string>,\n\tstack: string[]\n): { lines: string[]; mapEntries: MaterialSourceLocation[] } {\n\tconst sourceLines = source.split('\\n');\n\tconst lines: string[] = [];\n\tconst mapEntries: MaterialSourceLocation[] = [];\n\n\tfor (let index = 0; index < sourceLines.length; index += 1) {\n\t\tconst sourceLine = sourceLines[index];\n\t\tif (sourceLine === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst includeMatch = sourceLine.match(INCLUDE_DIRECTIVE_PATTERN);\n\t\tif (!includeMatch) {\n\t\t\tlines.push(sourceLine);\n\t\t\tmapEntries.push({\n\t\t\t\tkind,\n\t\t\t\tline: index + 1,\n\t\t\t\t...(kind === 'include' && includeName ? { include: includeName } : {})\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst includeKey = includeMatch[1];\n\t\tif (!includeKey) {\n\t\t\tthrow new Error('Invalid include directive in fragment shader.');\n\t\t}\n\n\t\tassertUniformName(includeKey);\n\t\tconst includeSource = includes[includeKey];\n\t\tif (!includeSource) {\n\t\t\tthrow new Error(`Unknown include \"${includeKey}\" referenced in fragment shader.`);\n\t\t}\n\n\t\tif (stack.includes(includeKey)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Circular include detected for \"${includeKey}\". Include stack: ${[...stack, includeKey].join(' -> ')}.`\n\t\t\t);\n\t\t}\n\n\t\tconst nested = expandChunk(includeSource, 'include', includeKey, includes, [\n\t\t\t...stack,\n\t\t\tincludeKey\n\t\t]);\n\t\tlines.push(...nested.lines);\n\t\tmapEntries.push(...nested.mapEntries);\n\t}\n\n\treturn { lines, mapEntries };\n}\n\n/**\n * Preprocesses material fragment with deterministic define/include expansion and line mapping.\n */\nexport function preprocessMaterialFragment<\n\tTDefineKey extends string,\n\tTIncludeKey extends string\n>(input: {\n\tfragment: string;\n\tdefines?: MaterialDefines<TDefineKey>;\n\tincludes?: MaterialIncludes<TIncludeKey>;\n}): PreprocessedMaterialFragment {\n\tconst normalizedDefines = normalizeDefines(input.defines);\n\tconst normalizedIncludes = normalizeIncludes(input.includes);\n\n\tconst fragmentExpanded = expandChunk(\n\t\tinput.fragment,\n\t\t'fragment',\n\t\tundefined,\n\t\tnormalizedIncludes,\n\t\t[]\n\t);\n\tconst defineEntries = (\n\t\tObject.entries(normalizedDefines) as Array<[TDefineKey, MaterialDefineValue]>\n\t).sort(([a], [b]) => a.localeCompare(b));\n\tconst lines: string[] = [];\n\tconst defineLines: string[] = [];\n\tconst mapEntries: Array<MaterialSourceLocation | null> = [];\n\n\tfor (let index = 0; index < defineEntries.length; index += 1) {\n\t\tconst entry = defineEntries[index];\n\t\tif (!entry) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst [name, value] = entry;\n\t\tconst defineLine = toDefineLine(name, value);\n\t\tlines.push(defineLine);\n\t\tdefineLines.push(defineLine);\n\t\tmapEntries.push({ kind: 'define', line: index + 1, define: name });\n\t}\n\n\tif (defineEntries.length > 0) {\n\t\tlines.push('');\n\t\tmapEntries.push(null);\n\t}\n\n\tlines.push(...fragmentExpanded.lines);\n\tmapEntries.push(...fragmentExpanded.mapEntries);\n\n\tconst lineMap: MaterialLineMap = [null, ...mapEntries];\n\treturn {\n\t\tfragment: lines.join('\\n'),\n\t\tlineMap,\n\t\tdefineBlockSource: defineLines.join('\\n')\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"material-preprocess.js","names":[],"sources":["../../src/lib/core/material-preprocess.ts"],"sourcesContent":["import { assertUniformName } from './uniforms.js';\nimport type {\n\tMaterialDefineValue,\n\tMaterialDefines,\n\tMaterialIncludes,\n\tTypedMaterialDefineValue\n} from './material.js';\n\nconst INCLUDE_DIRECTIVE_PATTERN = /^\\s*#include\\s+<([A-Za-z_][A-Za-z0-9_]*)>\\s*$/;\n\n/**\n * Source location metadata for one generated fragment line.\n */\nexport interface MaterialSourceLocation {\n\t/**\n\t * Origin category for this generated line.\n\t */\n\tkind: 'fragment' | 'include' | 'define';\n\t/**\n\t * 1-based line in the origin source.\n\t */\n\tline: number;\n\t/**\n\t * Include chunk identifier when `kind === \"include\"`.\n\t */\n\tinclude?: string;\n\t/**\n\t * Define identifier when `kind === \"define\"`.\n\t */\n\tdefine?: string;\n}\n\n/**\n * 1-based line map from generated fragment WGSL to user source locations.\n */\nexport type MaterialLineMap = Array<MaterialSourceLocation | null>;\n\n/**\n * Preprocess output used by material resolution and diagnostics mapping.\n */\nexport interface PreprocessedMaterialFragment {\n\t/**\n\t * Final fragment source after defines/include expansion.\n\t */\n\tfragment: string;\n\t/**\n\t * 1-based generated-line source map.\n\t */\n\tlineMap: MaterialLineMap;\n\t/**\n\t * Deterministic WGSL define block used to build the final fragment source.\n\t */\n\tdefineBlockSource: string;\n}\n\nfunction normalizeTypedDefine(\n\tname: string,\n\tdefine: TypedMaterialDefineValue\n): TypedMaterialDefineValue {\n\tconst value = define.value;\n\n\tif (define.type === 'bool') {\n\t\tif (typeof value !== 'boolean') {\n\t\t\tthrow new Error(`Invalid define value for \"${name}\". bool define requires boolean value.`);\n\t\t}\n\n\t\treturn {\n\t\t\ttype: 'bool',\n\t\t\tvalue\n\t\t};\n\t}\n\n\tif (typeof value !== 'number' || !Number.isFinite(value)) {\n\t\tthrow new Error(`Invalid define value for \"${name}\". Numeric define must be finite.`);\n\t}\n\n\tif ((define.type === 'i32' || define.type === 'u32') && !Number.isInteger(value)) {\n\t\tthrow new Error(`Invalid define value for \"${name}\". ${define.type} define requires integer.`);\n\t}\n\n\tif (define.type === 'u32' && value < 0) {\n\t\tthrow new Error(`Invalid define value for \"${name}\". u32 define must be >= 0.`);\n\t}\n\n\treturn {\n\t\ttype: define.type,\n\t\tvalue\n\t};\n}\n\n/**\n * Validates and normalizes define entries.\n */\nexport function normalizeDefines<TDefineKey extends string>(\n\tdefines: MaterialDefines<TDefineKey> | undefined\n): MaterialDefines<TDefineKey> {\n\tconst resolved: MaterialDefines<TDefineKey> = {} as MaterialDefines<TDefineKey>;\n\n\tfor (const [name, value] of Object.entries(defines ?? {}) as Array<\n\t\t[TDefineKey, MaterialDefineValue]\n\t>) {\n\t\tassertUniformName(name);\n\n\t\tif (typeof value === 'boolean') {\n\t\t\tresolved[name] = value;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (typeof value === 'number') {\n\t\t\tif (!Number.isFinite(value)) {\n\t\t\t\tthrow new Error(`Invalid define value for \"${name}\". Define numbers must be finite.`);\n\t\t\t}\n\t\t\tresolved[name] = value;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst normalized = normalizeTypedDefine(name, value);\n\t\tresolved[name] = Object.freeze(normalized);\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Validates include map identifiers and source chunks.\n */\nexport function normalizeIncludes<TIncludeKey extends string>(\n\tincludes: MaterialIncludes<TIncludeKey> | undefined\n): MaterialIncludes<TIncludeKey> {\n\tconst resolved: MaterialIncludes<TIncludeKey> = {} as MaterialIncludes<TIncludeKey>;\n\n\tfor (const [name, source] of Object.entries(includes ?? {}) as Array<[TIncludeKey, string]>) {\n\t\tassertUniformName(name);\n\t\tif (typeof source !== 'string' || source.trim().length === 0) {\n\t\t\tthrow new Error(`Invalid include \"${name}\". Include source must be a non-empty WGSL string.`);\n\t\t}\n\t\tresolved[name] = source;\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Converts one define declaration to WGSL `const`.\n */\nexport function toDefineLine(key: string, value: MaterialDefineValue): string {\n\tif (typeof value === 'boolean') {\n\t\treturn `const ${key}: bool = ${value ? 'true' : 'false'};`;\n\t}\n\n\tif (typeof value === 'number') {\n\t\tconst valueLiteral = Number.isInteger(value) ? `${value}.0` : `${value}`;\n\t\treturn `const ${key}: f32 = ${valueLiteral};`;\n\t}\n\n\tif (value.type === 'bool') {\n\t\treturn `const ${key}: bool = ${value.value ? 'true' : 'false'};`;\n\t}\n\n\tif (value.type === 'f32') {\n\t\tconst numberValue = value.value as number;\n\t\tconst valueLiteral = Number.isInteger(numberValue) ? `${numberValue}.0` : `${numberValue}`;\n\t\treturn `const ${key}: f32 = ${valueLiteral};`;\n\t}\n\n\tif (value.type === 'i32') {\n\t\treturn `const ${key}: i32 = ${value.value};`;\n\t}\n\n\treturn `const ${key}: u32 = ${value.value}u;`;\n}\n\nfunction expandChunk(\n\tsource: string,\n\tkind: 'fragment' | 'include',\n\tincludeName: string | undefined,\n\tincludes: Record<string, string>,\n\tstack: string[],\n\texpandedIncludes: Set<string>\n): { lines: string[]; mapEntries: MaterialSourceLocation[] } {\n\tconst sourceLines = source.split('\\n');\n\tconst lines: string[] = [];\n\tconst mapEntries: MaterialSourceLocation[] = [];\n\n\tfor (let index = 0; index < sourceLines.length; index += 1) {\n\t\tconst sourceLine = sourceLines[index];\n\t\tif (sourceLine === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst includeMatch = sourceLine.match(INCLUDE_DIRECTIVE_PATTERN);\n\t\tif (!includeMatch) {\n\t\t\tlines.push(sourceLine);\n\t\t\tmapEntries.push({\n\t\t\t\tkind,\n\t\t\t\tline: index + 1,\n\t\t\t\t...(kind === 'include' && includeName ? { include: includeName } : {})\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst includeKey = includeMatch[1];\n\t\tif (!includeKey) {\n\t\t\tthrow new Error('Invalid include directive in fragment shader.');\n\t\t}\n\n\t\tassertUniformName(includeKey);\n\t\tconst includeSource = includes[includeKey];\n\t\tif (!includeSource) {\n\t\t\tthrow new Error(`Unknown include \"${includeKey}\" referenced in fragment shader.`);\n\t\t}\n\n\t\tif (stack.includes(includeKey)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Circular include detected for \"${includeKey}\". Include stack: ${[...stack, includeKey].join(' -> ')}.`\n\t\t\t);\n\t\t}\n\n\t\tif (expandedIncludes.has(includeKey)) {\n\t\t\tcontinue;\n\t\t}\n\t\texpandedIncludes.add(includeKey);\n\n\t\tconst nested = expandChunk(\n\t\t\tincludeSource,\n\t\t\t'include',\n\t\t\tincludeKey,\n\t\t\tincludes,\n\t\t\t[...stack, includeKey],\n\t\t\texpandedIncludes\n\t\t);\n\t\tlines.push(...nested.lines);\n\t\tmapEntries.push(...nested.mapEntries);\n\t}\n\n\treturn { lines, mapEntries };\n}\n\n/**\n * Preprocesses material fragment with deterministic define/include expansion and line mapping.\n */\nexport function preprocessMaterialFragment<\n\tTDefineKey extends string,\n\tTIncludeKey extends string\n>(input: {\n\tfragment: string;\n\tdefines?: MaterialDefines<TDefineKey>;\n\tincludes?: MaterialIncludes<TIncludeKey>;\n}): PreprocessedMaterialFragment {\n\tconst normalizedDefines = normalizeDefines(input.defines);\n\tconst normalizedIncludes = normalizeIncludes(input.includes);\n\n\tconst fragmentExpanded = expandChunk(\n\t\tinput.fragment,\n\t\t'fragment',\n\t\tundefined,\n\t\tnormalizedIncludes,\n\t\t[],\n\t\tnew Set()\n\t);\n\tconst defineEntries = (\n\t\tObject.entries(normalizedDefines) as Array<[TDefineKey, MaterialDefineValue]>\n\t).sort(([a], [b]) => a.localeCompare(b));\n\tconst lines: string[] = [];\n\tconst defineLines: string[] = [];\n\tconst mapEntries: Array<MaterialSourceLocation | null> = [];\n\n\tfor (let index = 0; index < defineEntries.length; index += 1) {\n\t\tconst entry = defineEntries[index];\n\t\tif (!entry) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst [name, value] = entry;\n\t\tconst defineLine = toDefineLine(name, value);\n\t\tlines.push(defineLine);\n\t\tdefineLines.push(defineLine);\n\t\tmapEntries.push({ kind: 'define', line: index + 1, define: name });\n\t}\n\n\tif (defineEntries.length > 0) {\n\t\tlines.push('');\n\t\tmapEntries.push(null);\n\t}\n\n\tlines.push(...fragmentExpanded.lines);\n\tmapEntries.push(...fragmentExpanded.mapEntries);\n\n\tconst lineMap: MaterialLineMap = [null, ...mapEntries];\n\treturn {\n\t\tfragment: lines.join('\\n'),\n\t\tlineMap,\n\t\tdefineBlockSource: defineLines.join('\\n')\n\t};\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import type { MaterialSourceMetadata } from './error-diagnostics.js';
2
2
  import { resolveUniformLayout } from './uniforms.js';
3
3
  import { type MaterialLineMap } from './material-preprocess.js';
4
- import type { TextureDefinitionMap, UniformMap } from './types.js';
4
+ import type { StorageBufferDefinitionMap, TextureDefinitionMap, UniformMap } from './types.js';
5
5
  /**
6
6
  * Typed compile-time define declaration.
7
7
  */
@@ -39,7 +39,7 @@ export type MaterialIncludes<TKey extends string = string> = Record<TKey, string
39
39
  /**
40
40
  * External material input accepted by {@link defineMaterial}.
41
41
  */
42
- export interface FragMaterialInput<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string> {
42
+ export interface FragMaterialInput<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string, TStorageBufferKey extends string = string> {
43
43
  /**
44
44
  * User WGSL source containing `frag(uv: vec2f) -> vec4f`.
45
45
  */
@@ -60,11 +60,15 @@ export interface FragMaterialInput<TUniformKey extends string = string, TTexture
60
60
  * Optional WGSL include chunks used by `#include <name>` directives.
61
61
  */
62
62
  includes?: MaterialIncludes<TIncludeKey>;
63
+ /**
64
+ * Optional storage buffer definitions for compute shaders.
65
+ */
66
+ storageBuffers?: StorageBufferDefinitionMap<TStorageBufferKey>;
63
67
  }
64
68
  /**
65
69
  * Normalized and immutable material declaration consumed by `FragCanvas`.
66
70
  */
67
- export interface FragMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string> {
71
+ export interface FragMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string, TStorageBufferKey extends string = string> {
68
72
  /**
69
73
  * User WGSL source containing `frag(uv: vec2f) -> vec4f`.
70
74
  */
@@ -85,11 +89,15 @@ export interface FragMaterial<TUniformKey extends string = string, TTextureKey e
85
89
  * Optional WGSL include chunks used by `#include <name>` directives.
86
90
  */
87
91
  readonly includes: Readonly<MaterialIncludes<TIncludeKey>>;
92
+ /**
93
+ * Storage buffer definitions for compute shaders. Empty when not provided.
94
+ */
95
+ readonly storageBuffers: Readonly<StorageBufferDefinitionMap<TStorageBufferKey>>;
88
96
  }
89
97
  /**
90
98
  * Fully resolved, immutable material snapshot used for renderer creation/caching.
91
99
  */
92
- export interface ResolvedMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TIncludeKey extends string = string> {
100
+ export interface ResolvedMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TIncludeKey extends string = string, TStorageBufferKey extends string = string> {
93
101
  /**
94
102
  * Final fragment WGSL after define injection.
95
103
  */
@@ -134,6 +142,14 @@ export interface ResolvedMaterial<TUniformKey extends string = string, TTextureK
134
142
  * Source metadata used for diagnostics.
135
143
  */
136
144
  source: Readonly<MaterialSourceMetadata> | null;
145
+ /**
146
+ * Sorted storage buffer keys. Empty array when no storage buffers declared.
147
+ */
148
+ storageBufferKeys: TStorageBufferKey[];
149
+ /**
150
+ * Sorted storage texture keys (textures with storage: true).
151
+ */
152
+ storageTextureKeys: TTextureKey[];
137
153
  }
138
154
  /**
139
155
  * Creates a stable WGSL define block from the provided map.
@@ -156,12 +172,12 @@ export declare function applyMaterialDefines(fragment: string, defines: Material
156
172
  * @param input - User material declaration.
157
173
  * @returns Frozen material object safe to share and cache.
158
174
  */
159
- export declare function defineMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string>(input: FragMaterialInput<TUniformKey, TTextureKey, TDefineKey, TIncludeKey>): FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey>;
175
+ export declare function defineMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string, TStorageBufferKey extends string = string>(input: FragMaterialInput<TUniformKey, TTextureKey, TDefineKey, TIncludeKey, TStorageBufferKey>): FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey, TStorageBufferKey>;
160
176
  /**
161
177
  * Resolves a material to renderer-ready data and a deterministic signature.
162
178
  *
163
179
  * @param material - Material input created via {@link defineMaterial}.
164
180
  * @returns Resolved material with packed uniform layout, sorted texture keys and cache signature.
165
181
  */
166
- export declare function resolveMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string>(material: FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey>): ResolvedMaterial<TUniformKey, TTextureKey, TIncludeKey>;
182
+ export declare function resolveMaterial<TUniformKey extends string = string, TTextureKey extends string = string, TDefineKey extends string = string, TIncludeKey extends string = string, TStorageBufferKey extends string = string>(material: FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey, TStorageBufferKey>): ResolvedMaterial<TUniformKey, TTextureKey, TIncludeKey, TStorageBufferKey>;
167
183
  //# sourceMappingURL=material.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/lib/core/material.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAIN,oBAAoB,EACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EAKN,KAAK,eAAe,EAEpB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAGX,oBAAoB,EAGpB,UAAU,EAEV,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,MAAM,wBAAwB,GACjC;IACA;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;CACd,GACD;IACA;;OAEG;IACH,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;IAC5B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;CACb,CAAC;AAEL;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,MAAM,GAAG,wBAAwB,CAAC;AAE9E;;GAEG;AACH,MAAM,MAAM,eAAe,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,mBAAmB,CAAC,CAAC;AAE9F;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAElF;;GAEG;AACH,MAAM,WAAW,iBAAiB,CACjC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM;IAEnC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,CAAC,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IACnC;;OAEG;IACH,QAAQ,CAAC,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC7C;;OAEG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC,UAAU,CAAC,CAAC;IACtC;;OAEG;IACH,QAAQ,CAAC,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAC5B,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM;IAEnC;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;IACrD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC;IAC/D;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;IACxD;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB,CAChC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM;IAEnC;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,eAAe,EAAE,eAAe,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,UAAU,CAAC,WAAW,CAAC,CAAC;IAClC;;OAEG;IACH,QAAQ,EAAE,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAC5C;;OAEG;IACH,aAAa,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;IACvD;;OAEG;IACH,WAAW,EAAE,WAAW,EAAE,CAAC;IAC3B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB;;OAEG;IACH,cAAc,EAAE,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC9C;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,MAAM,EAAE,QAAQ,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC;CAChD;AA4VD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,CAa9E;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,eAAe,GAAG,SAAS,GAClC,MAAM,CAOR;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC7B,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM,EAEnC,KAAK,EAAE,iBAAiB,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,GACzE,YAAY,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAyBjE;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC9B,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,WAAW,SAAS,MAAM,GAAG,MAAM,EACnC,UAAU,SAAS,MAAM,GAAG,MAAM,EAClC,WAAW,SAAS,MAAM,GAAG,MAAM,EAEnC,QAAQ,EAAE,YAAY,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,GACvE,gBAAgB,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC,CA6CzD"}
1
+ {"version":3,"file":"material.d.ts","sourceRoot":"","sources":["../../src/lib/core/material.ts"],"names":[],"mappings":"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"}