@motion-core/motion-gpu 0.4.1 → 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 (228) hide show
  1. package/README.md +99 -0
  2. package/dist/advanced.d.ts +1 -0
  3. package/dist/advanced.d.ts.map +1 -0
  4. package/dist/advanced.js +14 -6
  5. package/dist/core/advanced.d.ts +1 -0
  6. package/dist/core/advanced.d.ts.map +1 -0
  7. package/dist/core/advanced.js +14 -5
  8. package/dist/core/compute-shader.d.ts +87 -0
  9. package/dist/core/compute-shader.d.ts.map +1 -0
  10. package/dist/core/compute-shader.js +205 -0
  11. package/dist/core/compute-shader.js.map +1 -0
  12. package/dist/core/current-value.d.ts +1 -0
  13. package/dist/core/current-value.d.ts.map +1 -0
  14. package/dist/core/current-value.js +35 -34
  15. package/dist/core/current-value.js.map +1 -0
  16. package/dist/core/error-diagnostics.d.ts +1 -0
  17. package/dist/core/error-diagnostics.d.ts.map +1 -0
  18. package/dist/core/error-diagnostics.js +70 -137
  19. package/dist/core/error-diagnostics.js.map +1 -0
  20. package/dist/core/error-report.d.ts +2 -1
  21. package/dist/core/error-report.d.ts.map +1 -0
  22. package/dist/core/error-report.js +247 -233
  23. package/dist/core/error-report.js.map +1 -0
  24. package/dist/core/frame-registry.d.ts +1 -0
  25. package/dist/core/frame-registry.d.ts.map +1 -0
  26. package/dist/core/frame-registry.js +546 -662
  27. package/dist/core/frame-registry.js.map +1 -0
  28. package/dist/core/index.d.ts +6 -2
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +13 -12
  31. package/dist/core/material-preprocess.d.ts +1 -0
  32. package/dist/core/material-preprocess.d.ts.map +1 -0
  33. package/dist/core/material-preprocess.js +131 -152
  34. package/dist/core/material-preprocess.js.map +1 -0
  35. package/dist/core/material.d.ts +23 -6
  36. package/dist/core/material.d.ts.map +1 -0
  37. package/dist/core/material.js +290 -317
  38. package/dist/core/material.js.map +1 -0
  39. package/dist/core/recompile-policy.d.ts +1 -0
  40. package/dist/core/recompile-policy.d.ts.map +1 -0
  41. package/dist/core/recompile-policy.js +18 -13
  42. package/dist/core/recompile-policy.js.map +1 -0
  43. package/dist/core/render-graph.d.ts +8 -3
  44. package/dist/core/render-graph.d.ts.map +1 -0
  45. package/dist/core/render-graph.js +77 -68
  46. package/dist/core/render-graph.js.map +1 -0
  47. package/dist/core/render-targets.d.ts +1 -0
  48. package/dist/core/render-targets.d.ts.map +1 -0
  49. package/dist/core/render-targets.js +52 -53
  50. package/dist/core/render-targets.js.map +1 -0
  51. package/dist/core/renderer.d.ts +1 -0
  52. package/dist/core/renderer.d.ts.map +1 -0
  53. package/dist/core/renderer.js +1337 -1081
  54. package/dist/core/renderer.js.map +1 -0
  55. package/dist/core/runtime-loop.d.ts +3 -2
  56. package/dist/core/runtime-loop.d.ts.map +1 -0
  57. package/dist/core/runtime-loop.js +353 -362
  58. package/dist/core/runtime-loop.js.map +1 -0
  59. package/dist/core/scheduler-helpers.d.ts +1 -0
  60. package/dist/core/scheduler-helpers.d.ts.map +1 -0
  61. package/dist/core/scheduler-helpers.js +52 -51
  62. package/dist/core/scheduler-helpers.js.map +1 -0
  63. package/dist/core/shader.d.ts +10 -1
  64. package/dist/core/shader.d.ts.map +1 -0
  65. package/dist/core/shader.js +109 -115
  66. package/dist/core/shader.js.map +1 -0
  67. package/dist/core/storage-buffers.d.ts +37 -0
  68. package/dist/core/storage-buffers.d.ts.map +1 -0
  69. package/dist/core/storage-buffers.js +95 -0
  70. package/dist/core/storage-buffers.js.map +1 -0
  71. package/dist/core/texture-loader.d.ts +1 -0
  72. package/dist/core/texture-loader.d.ts.map +1 -0
  73. package/dist/core/texture-loader.js +209 -273
  74. package/dist/core/texture-loader.js.map +1 -0
  75. package/dist/core/textures.d.ts +13 -0
  76. package/dist/core/textures.d.ts.map +1 -0
  77. package/dist/core/textures.js +111 -116
  78. package/dist/core/textures.js.map +1 -0
  79. package/dist/core/types.d.ts +147 -4
  80. package/dist/core/types.d.ts.map +1 -0
  81. package/dist/core/types.js +0 -4
  82. package/dist/core/uniforms.d.ts +1 -0
  83. package/dist/core/uniforms.d.ts.map +1 -0
  84. package/dist/core/uniforms.js +170 -191
  85. package/dist/core/uniforms.js.map +1 -0
  86. package/dist/index.d.ts +1 -0
  87. package/dist/index.d.ts.map +1 -0
  88. package/dist/index.js +13 -6
  89. package/dist/passes/BlitPass.d.ts +1 -0
  90. package/dist/passes/BlitPass.d.ts.map +1 -0
  91. package/dist/passes/BlitPass.js +23 -18
  92. package/dist/passes/BlitPass.js.map +1 -0
  93. package/dist/passes/ComputePass.d.ts +83 -0
  94. package/dist/passes/ComputePass.d.ts.map +1 -0
  95. package/dist/passes/ComputePass.js +92 -0
  96. package/dist/passes/ComputePass.js.map +1 -0
  97. package/dist/passes/CopyPass.d.ts +1 -0
  98. package/dist/passes/CopyPass.d.ts.map +1 -0
  99. package/dist/passes/CopyPass.js +58 -52
  100. package/dist/passes/CopyPass.js.map +1 -0
  101. package/dist/passes/FullscreenPass.d.ts +1 -0
  102. package/dist/passes/FullscreenPass.d.ts.map +1 -0
  103. package/dist/passes/FullscreenPass.js +127 -130
  104. package/dist/passes/FullscreenPass.js.map +1 -0
  105. package/dist/passes/PingPongComputePass.d.ts +104 -0
  106. package/dist/passes/PingPongComputePass.d.ts.map +1 -0
  107. package/dist/passes/PingPongComputePass.js +132 -0
  108. package/dist/passes/PingPongComputePass.js.map +1 -0
  109. package/dist/passes/ShaderPass.d.ts +1 -0
  110. package/dist/passes/ShaderPass.d.ts.map +1 -0
  111. package/dist/passes/ShaderPass.js +41 -37
  112. package/dist/passes/ShaderPass.js.map +1 -0
  113. package/dist/passes/index.d.ts +3 -0
  114. package/dist/passes/index.d.ts.map +1 -0
  115. package/dist/passes/index.js +6 -3
  116. package/dist/react/FragCanvas.d.ts +3 -2
  117. package/dist/react/FragCanvas.d.ts.map +1 -0
  118. package/dist/react/FragCanvas.js +234 -211
  119. package/dist/react/FragCanvas.js.map +1 -0
  120. package/dist/react/MotionGPUErrorOverlay.d.ts +1 -0
  121. package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -0
  122. package/dist/react/MotionGPUErrorOverlay.js +200 -14
  123. package/dist/react/MotionGPUErrorOverlay.js.map +1 -0
  124. package/dist/react/Portal.d.ts +1 -0
  125. package/dist/react/Portal.d.ts.map +1 -0
  126. package/dist/react/Portal.js +18 -21
  127. package/dist/react/Portal.js.map +1 -0
  128. package/dist/react/advanced.d.ts +1 -0
  129. package/dist/react/advanced.d.ts.map +1 -0
  130. package/dist/react/advanced.js +14 -6
  131. package/dist/react/frame-context.d.ts +1 -0
  132. package/dist/react/frame-context.d.ts.map +1 -0
  133. package/dist/react/frame-context.js +88 -94
  134. package/dist/react/frame-context.js.map +1 -0
  135. package/dist/react/index.d.ts +6 -2
  136. package/dist/react/index.d.ts.map +1 -0
  137. package/dist/react/index.js +12 -9
  138. package/dist/react/motiongpu-context.d.ts +1 -0
  139. package/dist/react/motiongpu-context.d.ts.map +1 -0
  140. package/dist/react/motiongpu-context.js +18 -15
  141. package/dist/react/motiongpu-context.js.map +1 -0
  142. package/dist/react/use-motiongpu-user-context.d.ts +1 -0
  143. package/dist/react/use-motiongpu-user-context.d.ts.map +1 -0
  144. package/dist/react/use-motiongpu-user-context.js +83 -82
  145. package/dist/react/use-motiongpu-user-context.js.map +1 -0
  146. package/dist/react/use-texture.d.ts +1 -0
  147. package/dist/react/use-texture.d.ts.map +1 -0
  148. package/dist/react/use-texture.js +132 -152
  149. package/dist/react/use-texture.js.map +1 -0
  150. package/dist/svelte/FragCanvas.svelte +2 -2
  151. package/dist/svelte/FragCanvas.svelte.d.ts +3 -2
  152. package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -0
  153. package/dist/svelte/MotionGPUErrorOverlay.svelte +137 -7
  154. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts +1 -0
  155. package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -0
  156. package/dist/svelte/Portal.svelte.d.ts +1 -0
  157. package/dist/svelte/Portal.svelte.d.ts.map +1 -0
  158. package/dist/svelte/advanced.d.ts +1 -0
  159. package/dist/svelte/advanced.d.ts.map +1 -0
  160. package/dist/svelte/advanced.js +13 -6
  161. package/dist/svelte/frame-context.d.ts +1 -0
  162. package/dist/svelte/frame-context.d.ts.map +1 -0
  163. package/dist/svelte/frame-context.js +27 -27
  164. package/dist/svelte/frame-context.js.map +1 -0
  165. package/dist/svelte/index.d.ts +6 -2
  166. package/dist/svelte/index.d.ts.map +1 -0
  167. package/dist/svelte/index.js +12 -9
  168. package/dist/svelte/motiongpu-context.d.ts +1 -0
  169. package/dist/svelte/motiongpu-context.d.ts.map +1 -0
  170. package/dist/svelte/motiongpu-context.js +24 -21
  171. package/dist/svelte/motiongpu-context.js.map +1 -0
  172. package/dist/svelte/use-motiongpu-user-context.d.ts +1 -0
  173. package/dist/svelte/use-motiongpu-user-context.d.ts.map +1 -0
  174. package/dist/svelte/use-motiongpu-user-context.js +69 -70
  175. package/dist/svelte/use-motiongpu-user-context.js.map +1 -0
  176. package/dist/svelte/use-texture.d.ts +1 -0
  177. package/dist/svelte/use-texture.d.ts.map +1 -0
  178. package/dist/svelte/use-texture.js +125 -147
  179. package/dist/svelte/use-texture.js.map +1 -0
  180. package/package.json +12 -7
  181. package/src/lib/advanced.ts +6 -0
  182. package/src/lib/core/advanced.ts +12 -0
  183. package/src/lib/core/compute-shader.ts +326 -0
  184. package/src/lib/core/current-value.ts +64 -0
  185. package/src/lib/core/error-diagnostics.ts +236 -0
  186. package/src/lib/core/error-report.ts +535 -0
  187. package/src/lib/core/frame-registry.ts +1190 -0
  188. package/src/lib/core/index.ts +94 -0
  189. package/src/lib/core/material-preprocess.ts +295 -0
  190. package/src/lib/core/material.ts +748 -0
  191. package/src/lib/core/recompile-policy.ts +31 -0
  192. package/src/lib/core/render-graph.ts +173 -0
  193. package/src/lib/core/render-targets.ts +107 -0
  194. package/src/lib/core/renderer.ts +2161 -0
  195. package/src/lib/core/runtime-loop.ts +537 -0
  196. package/src/lib/core/scheduler-helpers.ts +136 -0
  197. package/src/lib/core/shader.ts +301 -0
  198. package/src/lib/core/storage-buffers.ts +142 -0
  199. package/src/lib/core/texture-loader.ts +482 -0
  200. package/src/lib/core/textures.ts +257 -0
  201. package/src/lib/core/types.ts +743 -0
  202. package/src/lib/core/uniforms.ts +282 -0
  203. package/src/lib/index.ts +6 -0
  204. package/src/lib/passes/BlitPass.ts +54 -0
  205. package/src/lib/passes/ComputePass.ts +136 -0
  206. package/src/lib/passes/CopyPass.ts +80 -0
  207. package/src/lib/passes/FullscreenPass.ts +173 -0
  208. package/src/lib/passes/PingPongComputePass.ts +180 -0
  209. package/src/lib/passes/ShaderPass.ts +89 -0
  210. package/src/lib/passes/index.ts +9 -0
  211. package/src/lib/react/FragCanvas.tsx +345 -0
  212. package/src/lib/react/MotionGPUErrorOverlay.tsx +524 -0
  213. package/src/lib/react/Portal.tsx +34 -0
  214. package/src/lib/react/advanced.ts +36 -0
  215. package/src/lib/react/frame-context.ts +169 -0
  216. package/src/lib/react/index.ts +68 -0
  217. package/src/lib/react/motiongpu-context.ts +88 -0
  218. package/src/lib/react/use-motiongpu-user-context.ts +186 -0
  219. package/src/lib/react/use-texture.ts +233 -0
  220. package/src/lib/svelte/FragCanvas.svelte +249 -0
  221. package/src/lib/svelte/MotionGPUErrorOverlay.svelte +512 -0
  222. package/src/lib/svelte/Portal.svelte +31 -0
  223. package/src/lib/svelte/advanced.ts +32 -0
  224. package/src/lib/svelte/frame-context.ts +87 -0
  225. package/src/lib/svelte/index.ts +68 -0
  226. package/src/lib/svelte/motiongpu-context.ts +97 -0
  227. package/src/lib/svelte/use-motiongpu-user-context.ts +145 -0
  228. package/src/lib/svelte/use-texture.ts +232 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-loop.js","names":[],"sources":["../../src/lib/core/runtime-loop.ts"],"sourcesContent":["import type { CurrentReadable, CurrentWritable } from './current-value.js';\nimport { resolveMaterial, type FragMaterial, type ResolvedMaterial } from './material.js';\nimport {\n\ttoMotionGPUErrorReport,\n\ttype MotionGPUErrorPhase,\n\ttype MotionGPUErrorReport\n} from './error-report.js';\nimport { createRenderer } from './renderer.js';\nimport { buildRendererPipelineSignature } from './recompile-policy.js';\nimport { assertUniformValueForType } from './uniforms.js';\nimport type { FrameRegistry } from './frame-registry.js';\nimport type {\n\tAnyPass,\n\tFrameInvalidationToken,\n\tOutputColorSpace,\n\tPendingStorageWrite,\n\tRenderer,\n\tRenderTargetDefinitionMap,\n\tStorageBufferDefinitionMap,\n\tTextureMap,\n\tTextureValue,\n\tUniformType,\n\tUniformValue\n} from './types.js';\n\nexport interface MotionGPURuntimeLoopOptions {\n\tcanvas: HTMLCanvasElement;\n\tregistry: FrameRegistry;\n\tsize: CurrentWritable<{ width: number; height: number }>;\n\tdpr: CurrentReadable<number>;\n\tmaxDelta: CurrentReadable<number>;\n\tgetMaterial: () => FragMaterial;\n\tgetRenderTargets: () => RenderTargetDefinitionMap;\n\tgetPasses: () => AnyPass[];\n\tgetClearColor: () => [number, number, number, number];\n\tgetOutputColorSpace: () => OutputColorSpace;\n\tgetAdapterOptions: () => GPURequestAdapterOptions | undefined;\n\tgetDeviceDescriptor: () => GPUDeviceDescriptor | undefined;\n\tgetOnError: () => ((report: MotionGPUErrorReport) => void) | undefined;\n\treportError: (report: MotionGPUErrorReport | null) => void;\n\tgetErrorHistoryLimit?: () => number | undefined;\n\tgetOnErrorHistory?: () => ((history: MotionGPUErrorReport[]) => void) | undefined;\n\treportErrorHistory?: (history: MotionGPUErrorReport[]) => void;\n}\n\nexport interface MotionGPURuntimeLoop {\n\trequestFrame: () => void;\n\tinvalidate: (token?: FrameInvalidationToken) => void;\n\tadvance: () => void;\n\tdestroy: () => void;\n}\n\nfunction getRendererRetryDelayMs(attempt: number): number {\n\treturn Math.min(8000, 250 * 2 ** Math.max(0, attempt - 1));\n}\n\nexport function createMotionGPURuntimeLoop(\n\toptions: MotionGPURuntimeLoopOptions\n): MotionGPURuntimeLoop {\n\tconst { canvas: canvasElement, registry, size } = options;\n\tlet frameId: number | null = null;\n\tlet renderer: Renderer | null = null;\n\tlet isDisposed = false;\n\tlet previousTime = performance.now() / 1000;\n\tlet activeRendererSignature = '';\n\tlet failedRendererSignature: string | null = null;\n\tlet failedRendererAttempts = 0;\n\tlet nextRendererRetryAt = 0;\n\tlet rendererRebuildPromise: Promise<void> | null = null;\n\n\tconst runtimeUniforms: Record<string, UniformValue> = {};\n\tconst runtimeTextures: TextureMap = {};\n\tlet activeUniforms: Record<string, UniformValue> = {};\n\tlet activeTextures: Record<string, { source?: TextureValue }> = {};\n\tlet uniformKeys: string[] = [];\n\tlet uniformKeySet = new Set<string>();\n\tlet uniformTypes = new Map<string, UniformType>();\n\tlet textureKeys: string[] = [];\n\tlet textureKeySet = new Set<string>();\n\tlet activeMaterialSignature = '';\n\tlet currentCssWidth = -1;\n\tlet currentCssHeight = -1;\n\tconst renderUniforms: Record<string, UniformValue> = {};\n\tconst renderTextures: TextureMap = {};\n\tconst canvasSize = { width: 0, height: 0 };\n\tlet storageBufferKeys: string[] = [];\n\tlet storageBufferKeySet = new Set<string>();\n\tlet storageBufferDefinitions: StorageBufferDefinitionMap = {};\n\tconst pendingStorageWrites: PendingStorageWrite[] = [];\n\tlet shouldContinueAfterFrame = false;\n\tlet activeErrorKey: string | null = null;\n\tlet errorHistory: MotionGPUErrorReport[] = [];\n\n\tconst getHistoryLimit = (): number => {\n\t\tconst value = options.getErrorHistoryLimit?.() ?? 0;\n\t\tif (!Number.isFinite(value) || value <= 0) {\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn Math.floor(value);\n\t};\n\n\tconst publishErrorHistory = (): void => {\n\t\toptions.reportErrorHistory?.(errorHistory);\n\t\tconst onErrorHistory = options.getOnErrorHistory?.();\n\t\tif (!onErrorHistory) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tonErrorHistory(errorHistory);\n\t\t} catch {\n\t\t\t// User-provided error history handlers must not break runtime error recovery.\n\t\t}\n\t};\n\n\tconst syncErrorHistory = (): void => {\n\t\tconst limit = getHistoryLimit();\n\t\tif (limit <= 0) {\n\t\t\tif (errorHistory.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\terrorHistory = [];\n\t\t\tpublishErrorHistory();\n\t\t\treturn;\n\t\t}\n\n\t\tif (errorHistory.length <= limit) {\n\t\t\treturn;\n\t\t}\n\n\t\terrorHistory = errorHistory.slice(errorHistory.length - limit);\n\t\tpublishErrorHistory();\n\t};\n\n\tconst setError = (error: unknown, phase: MotionGPUErrorPhase): void => {\n\t\tconst report = toMotionGPUErrorReport(error, phase);\n\t\tconst reportKey = JSON.stringify({\n\t\t\tphase: report.phase,\n\t\t\ttitle: report.title,\n\t\t\tmessage: report.message,\n\t\t\trawMessage: report.rawMessage\n\t\t});\n\t\tif (activeErrorKey === reportKey) {\n\t\t\treturn;\n\t\t}\n\t\tactiveErrorKey = reportKey;\n\t\tconst historyLimit = getHistoryLimit();\n\t\tif (historyLimit > 0) {\n\t\t\terrorHistory = [...errorHistory, report];\n\t\t\tif (errorHistory.length > historyLimit) {\n\t\t\t\terrorHistory = errorHistory.slice(errorHistory.length - historyLimit);\n\t\t\t}\n\t\t\tpublishErrorHistory();\n\t\t}\n\t\toptions.reportError(report);\n\t\tconst onError = options.getOnError();\n\t\tif (!onError) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tonError(report);\n\t\t} catch {\n\t\t\t// User-provided error handlers must not break runtime error recovery.\n\t\t}\n\t};\n\n\tconst clearError = (): void => {\n\t\tif (activeErrorKey === null) {\n\t\t\treturn;\n\t\t}\n\n\t\tactiveErrorKey = null;\n\t\toptions.reportError(null);\n\t};\n\n\tconst scheduleFrame = (): void => {\n\t\tif (isDisposed || frameId !== null) {\n\t\t\treturn;\n\t\t}\n\n\t\tframeId = requestAnimationFrame(renderFrame);\n\t};\n\n\tconst requestFrame = (): void => {\n\t\tscheduleFrame();\n\t};\n\n\tconst invalidate = (token?: FrameInvalidationToken): void => {\n\t\tregistry.invalidate(token);\n\t\trequestFrame();\n\t};\n\n\tconst advance = (): void => {\n\t\tregistry.advance();\n\t\trequestFrame();\n\t};\n\n\tconst resetRuntimeMaps = (): void => {\n\t\tfor (const key of Object.keys(runtimeUniforms)) {\n\t\t\tif (!uniformKeySet.has(key)) {\n\t\t\t\tReflect.deleteProperty(runtimeUniforms, key);\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of Object.keys(runtimeTextures)) {\n\t\t\tif (!textureKeySet.has(key)) {\n\t\t\t\tReflect.deleteProperty(runtimeTextures, key);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst resetRenderPayloadMaps = (): void => {\n\t\tfor (const key of Object.keys(renderUniforms)) {\n\t\t\tif (!uniformKeySet.has(key)) {\n\t\t\t\tReflect.deleteProperty(renderUniforms, key);\n\t\t\t}\n\t\t}\n\n\t\tfor (const key of Object.keys(renderTextures)) {\n\t\t\tif (!textureKeySet.has(key)) {\n\t\t\t\tReflect.deleteProperty(renderTextures, key);\n\t\t\t}\n\t\t}\n\t};\n\n\tconst syncMaterialRuntimeState = (materialState: ResolvedMaterial): void => {\n\t\tconst signatureChanged = activeMaterialSignature !== materialState.signature;\n\t\tconst defaultsChanged =\n\t\t\tactiveUniforms !== materialState.uniforms || activeTextures !== materialState.textures;\n\n\t\tif (!signatureChanged && !defaultsChanged) {\n\t\t\treturn;\n\t\t}\n\n\t\tactiveUniforms = materialState.uniforms;\n\t\tactiveTextures = materialState.textures;\n\t\tif (!signatureChanged) {\n\t\t\treturn;\n\t\t}\n\n\t\tuniformKeys = materialState.uniformLayout.entries.map((entry) => entry.name);\n\t\tuniformTypes = new Map(\n\t\t\tmaterialState.uniformLayout.entries.map((entry) => [entry.name, entry.type])\n\t\t);\n\t\ttextureKeys = materialState.textureKeys;\n\t\tuniformKeySet = new Set(uniformKeys);\n\t\ttextureKeySet = new Set(textureKeys);\n\t\tstorageBufferKeys = materialState.storageBufferKeys;\n\t\tstorageBufferKeySet = new Set(storageBufferKeys);\n\t\tstorageBufferDefinitions = (options.getMaterial().storageBuffers ??\n\t\t\t{}) as StorageBufferDefinitionMap;\n\t\tresetRuntimeMaps();\n\t\tresetRenderPayloadMaps();\n\t\tactiveMaterialSignature = materialState.signature;\n\t};\n\n\tconst resolveActiveMaterial = (): ResolvedMaterial => {\n\t\treturn resolveMaterial(options.getMaterial());\n\t};\n\n\tconst setUniform = (name: string, value: UniformValue): void => {\n\t\tif (!uniformKeySet.has(name)) {\n\t\t\tthrow new Error(`Unknown uniform \"${name}\". Declare it in material.uniforms first.`);\n\t\t}\n\t\tconst expectedType = uniformTypes.get(name);\n\t\tif (!expectedType) {\n\t\t\tthrow new Error(`Unknown uniform type for \"${name}\"`);\n\t\t}\n\t\tassertUniformValueForType(expectedType, value);\n\t\truntimeUniforms[name] = value;\n\t};\n\n\tconst setTexture = (name: string, value: TextureValue): void => {\n\t\tif (!textureKeySet.has(name)) {\n\t\t\tthrow new Error(`Unknown texture \"${name}\". Declare it in material.textures first.`);\n\t\t}\n\t\truntimeTextures[name] = value;\n\t};\n\n\tconst writeStorageBuffer = (\n\t\tname: string,\n\t\tdata: ArrayBufferView,\n\t\twriteOptions?: { offset?: number }\n\t): void => {\n\t\tif (!storageBufferKeySet.has(name)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown storage buffer \"${name}\". Declare it in material.storageBuffers first.`\n\t\t\t);\n\t\t}\n\t\tconst definition = storageBufferDefinitions[name];\n\t\tif (!definition) {\n\t\t\tthrow new Error(`Missing definition for storage buffer \"${name}\".`);\n\t\t}\n\t\tconst offset = writeOptions?.offset ?? 0;\n\t\tif (offset < 0 || offset + data.byteLength > definition.size) {\n\t\t\tthrow new Error(\n\t\t\t\t`Storage buffer \"${name}\" write out of bounds: offset=${offset}, dataSize=${data.byteLength}, bufferSize=${definition.size}.`\n\t\t\t);\n\t\t}\n\t\tpendingStorageWrites.push({ name, data, offset });\n\t};\n\n\tconst readStorageBuffer = (name: string): Promise<ArrayBuffer> => {\n\t\tif (!storageBufferKeySet.has(name)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Unknown storage buffer \"${name}\". Declare it in material.storageBuffers first.`\n\t\t\t);\n\t\t}\n\t\tif (!renderer) {\n\t\t\treturn Promise.reject(\n\t\t\t\tnew Error(`Cannot read storage buffer \"${name}\": renderer not initialized.`)\n\t\t\t);\n\t\t}\n\t\tconst gpuBuffer = renderer.getStorageBuffer?.(name);\n\t\tif (!gpuBuffer) {\n\t\t\treturn Promise.reject(new Error(`Storage buffer \"${name}\" not allocated on GPU.`));\n\t\t}\n\t\tconst device = renderer.getDevice?.();\n\t\tif (!device) {\n\t\t\treturn Promise.reject(new Error('Cannot read storage buffer: GPU device unavailable.'));\n\t\t}\n\t\tconst definition = storageBufferDefinitions[name];\n\t\tif (!definition) {\n\t\t\treturn Promise.reject(new Error(`Missing definition for storage buffer \"${name}\".`));\n\t\t}\n\t\tconst stagingBuffer = device.createBuffer({\n\t\t\tsize: definition.size,\n\t\t\tusage: GPUBufferUsage.MAP_READ | GPUBufferUsage.COPY_DST\n\t\t});\n\t\tconst commandEncoder = device.createCommandEncoder();\n\t\tcommandEncoder.copyBufferToBuffer(gpuBuffer, 0, stagingBuffer, 0, definition.size);\n\t\tdevice.queue.submit([commandEncoder.finish()]);\n\t\treturn stagingBuffer.mapAsync(GPUMapMode.READ).then(() => {\n\t\t\tconst result = stagingBuffer.getMappedRange().slice(0);\n\t\t\tstagingBuffer.unmap();\n\t\t\tstagingBuffer.destroy();\n\t\t\treturn result;\n\t\t});\n\t};\n\n\tconst renderFrame = (timestamp: number): void => {\n\t\tframeId = null;\n\t\tif (isDisposed) {\n\t\t\treturn;\n\t\t}\n\t\tsyncErrorHistory();\n\n\t\tlet materialState: ResolvedMaterial;\n\t\ttry {\n\t\t\tmaterialState = resolveActiveMaterial();\n\t\t} catch (error) {\n\t\t\tsetError(error, 'initialization');\n\t\t\tscheduleFrame();\n\t\t\treturn;\n\t\t}\n\n\t\tshouldContinueAfterFrame = false;\n\n\t\tconst outputColorSpace = options.getOutputColorSpace();\n\t\tconst rendererSignature = buildRendererPipelineSignature({\n\t\t\tmaterialSignature: materialState.signature,\n\t\t\toutputColorSpace\n\t\t});\n\t\tsyncMaterialRuntimeState(materialState);\n\n\t\tif (failedRendererSignature && failedRendererSignature !== rendererSignature) {\n\t\t\tfailedRendererSignature = null;\n\t\t\tfailedRendererAttempts = 0;\n\t\t\tnextRendererRetryAt = 0;\n\t\t}\n\n\t\tif (!renderer || activeRendererSignature !== rendererSignature) {\n\t\t\tif (\n\t\t\t\tfailedRendererSignature === rendererSignature &&\n\t\t\t\tperformance.now() < nextRendererRetryAt\n\t\t\t) {\n\t\t\t\tscheduleFrame();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (!rendererRebuildPromise) {\n\t\t\t\trendererRebuildPromise = (async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst nextRenderer = await createRenderer({\n\t\t\t\t\t\t\tcanvas: canvasElement,\n\t\t\t\t\t\t\tfragmentWgsl: materialState.fragmentWgsl,\n\t\t\t\t\t\t\tfragmentLineMap: materialState.fragmentLineMap,\n\t\t\t\t\t\t\tfragmentSource: materialState.fragmentSource,\n\t\t\t\t\t\t\tincludeSources: materialState.includeSources,\n\t\t\t\t\t\t\tdefineBlockSource: materialState.defineBlockSource,\n\t\t\t\t\t\t\tmaterialSource: materialState.source,\n\t\t\t\t\t\t\tmaterialSignature: materialState.signature,\n\t\t\t\t\t\t\tuniformLayout: materialState.uniformLayout,\n\t\t\t\t\t\t\ttextureKeys: materialState.textureKeys,\n\t\t\t\t\t\t\ttextureDefinitions: materialState.textures,\n\t\t\t\t\t\t\tstorageBufferKeys: materialState.storageBufferKeys,\n\t\t\t\t\t\t\tstorageBufferDefinitions,\n\t\t\t\t\t\t\tstorageTextureKeys: materialState.storageTextureKeys,\n\t\t\t\t\t\t\tgetRenderTargets: options.getRenderTargets,\n\t\t\t\t\t\t\tgetPasses: options.getPasses,\n\t\t\t\t\t\t\toutputColorSpace,\n\t\t\t\t\t\t\tgetClearColor: options.getClearColor,\n\t\t\t\t\t\t\tgetDpr: () => options.dpr.current,\n\t\t\t\t\t\t\tadapterOptions: options.getAdapterOptions(),\n\t\t\t\t\t\t\tdeviceDescriptor: options.getDeviceDescriptor()\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (isDisposed) {\n\t\t\t\t\t\t\tnextRenderer.destroy();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\trenderer?.destroy();\n\t\t\t\t\t\trenderer = nextRenderer;\n\t\t\t\t\t\tactiveRendererSignature = rendererSignature;\n\t\t\t\t\t\tfailedRendererSignature = null;\n\t\t\t\t\t\tfailedRendererAttempts = 0;\n\t\t\t\t\t\tnextRendererRetryAt = 0;\n\t\t\t\t\t\tclearError();\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tfailedRendererSignature = rendererSignature;\n\t\t\t\t\t\tfailedRendererAttempts += 1;\n\t\t\t\t\t\tconst retryDelayMs = getRendererRetryDelayMs(failedRendererAttempts);\n\t\t\t\t\t\tnextRendererRetryAt = performance.now() + retryDelayMs;\n\t\t\t\t\t\tsetError(error, 'initialization');\n\t\t\t\t\t} finally {\n\t\t\t\t\t\trendererRebuildPromise = null;\n\t\t\t\t\t\tscheduleFrame();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst time = timestamp / 1000;\n\t\tconst rawDelta = Math.max(0, time - previousTime);\n\t\tconst delta = Math.min(rawDelta, options.maxDelta.current);\n\t\tpreviousTime = time;\n\t\tconst rect = canvasElement.getBoundingClientRect();\n\t\tconst width = Math.max(0, Math.floor(rect.width));\n\t\tconst height = Math.max(0, Math.floor(rect.height));\n\t\tif (width !== currentCssWidth || height !== currentCssHeight) {\n\t\t\tcurrentCssWidth = width;\n\t\t\tcurrentCssHeight = height;\n\t\t\tsize.set({ width, height });\n\t\t}\n\n\t\ttry {\n\t\t\tregistry.run({\n\t\t\t\ttime,\n\t\t\t\tdelta,\n\t\t\t\tsetUniform,\n\t\t\t\tsetTexture,\n\t\t\t\twriteStorageBuffer,\n\t\t\t\treadStorageBuffer,\n\t\t\t\tinvalidate,\n\t\t\t\tadvance,\n\t\t\t\trenderMode: registry.getRenderMode(),\n\t\t\t\tautoRender: registry.getAutoRender(),\n\t\t\t\tcanvas: canvasElement\n\t\t\t});\n\n\t\t\tconst shouldRenderFrame = registry.shouldRender();\n\t\t\tshouldContinueAfterFrame =\n\t\t\t\tregistry.getRenderMode() === 'always' ||\n\t\t\t\t(registry.getRenderMode() === 'on-demand' && shouldRenderFrame);\n\n\t\t\tif (shouldRenderFrame) {\n\t\t\t\tfor (const key of uniformKeys) {\n\t\t\t\t\tconst runtimeValue = runtimeUniforms[key];\n\t\t\t\t\trenderUniforms[key] =\n\t\t\t\t\t\truntimeValue === undefined ? (activeUniforms[key] as UniformValue) : runtimeValue;\n\t\t\t\t}\n\n\t\t\t\tfor (const key of textureKeys) {\n\t\t\t\t\tconst runtimeValue = runtimeTextures[key];\n\t\t\t\t\trenderTextures[key] =\n\t\t\t\t\t\truntimeValue === undefined ? (activeTextures[key]?.source ?? null) : runtimeValue;\n\t\t\t\t}\n\n\t\t\t\tcanvasSize.width = width;\n\t\t\t\tcanvasSize.height = height;\n\t\t\t\trenderer.render({\n\t\t\t\t\ttime,\n\t\t\t\t\tdelta,\n\t\t\t\t\trenderMode: registry.getRenderMode(),\n\t\t\t\t\tuniforms: renderUniforms,\n\t\t\t\t\ttextures: renderTextures,\n\t\t\t\t\tcanvasSize,\n\t\t\t\t\t...(pendingStorageWrites.length > 0\n\t\t\t\t\t\t? { pendingStorageWrites: pendingStorageWrites.splice(0) }\n\t\t\t\t\t\t: {})\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tclearError();\n\t\t} catch (error) {\n\t\t\tsetError(error, 'render');\n\t\t} finally {\n\t\t\tregistry.endFrame();\n\t\t}\n\n\t\tif (shouldContinueAfterFrame) {\n\t\t\tscheduleFrame();\n\t\t}\n\t};\n\n\t(async () => {\n\t\ttry {\n\t\t\tconst initialMaterial = resolveActiveMaterial();\n\t\t\tsyncMaterialRuntimeState(initialMaterial);\n\t\t\tactiveRendererSignature = '';\n\t\t\tscheduleFrame();\n\t\t} catch (error) {\n\t\t\tsetError(error, 'initialization');\n\t\t\tscheduleFrame();\n\t\t}\n\t})();\n\n\treturn {\n\t\trequestFrame,\n\t\tinvalidate,\n\t\tadvance,\n\t\tdestroy: () => {\n\t\t\tisDisposed = true;\n\t\t\tif (frameId !== null) {\n\t\t\t\tcancelAnimationFrame(frameId);\n\t\t\t\tframeId = null;\n\t\t\t}\n\t\t\trenderer?.destroy();\n\t\t\tregistry.clear();\n\t\t}\n\t};\n}\n"],"mappings":"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"}
@@ -46,3 +46,4 @@ export declare function applySchedulerPreset(scheduler: MotionGPUScheduler, pres
46
46
  * Captures an aggregate scheduler diagnostics snapshot.
47
47
  */
48
48
  export declare function captureSchedulerDebugSnapshot(scheduler: MotionGPUScheduler): SchedulerDebugSnapshot;
49
+ //# sourceMappingURL=scheduler-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-helpers.d.ts","sourceRoot":"","sources":["../../src/lib/core/scheduler-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,sBAAsB,EACtB,aAAa,EACb,eAAe,EACf,qBAAqB,EACrB,MAAM,qBAAqB,CAAC;AAE7B;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACpC,aAAa,EACX,aAAa,GACb,UAAU,GACV,uBAAuB,GACvB,uBAAuB,GACvB,mBAAmB,GACnB,aAAa,GACb,qBAAqB,GACrB,oBAAoB,GACpB,gBAAgB,GAChB,qBAAqB,GACrB,oBAAoB,GACpB,sBAAsB,CACxB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,aAAa,CAAC;AAEnE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC3C,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,kBAAkB,EAAE,OAAO,CAAC;IAC5B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,qBAAqB,CAAC;IAChC,cAAc,EAAE,eAAe,GAAG,IAAI,CAAC;IACvC,iBAAiB,EAAE,sBAAsB,GAAG,IAAI,CAAC;CACjD;AA4BD;;;;GAIG;AACH,wBAAgB,oBAAoB,CACnC,SAAS,EAAE,kBAAkB,EAC7B,MAAM,EAAE,eAAe,EACvB,OAAO,GAAE,2BAAgC,GACvC,qBAAqB,CAqBvB;AAED;;GAEG;AACH,wBAAgB,6BAA6B,CAC5C,SAAS,EAAE,kBAAkB,GAC3B,sBAAsB,CASxB"}
@@ -1,58 +1,59 @@
1
- const PRESET_CONFIG = {
2
- performance: {
3
- diagnosticsEnabled: false,
4
- profilingEnabled: false,
5
- profilingWindow: 60
6
- },
7
- balanced: {
8
- diagnosticsEnabled: true,
9
- profilingEnabled: true,
10
- profilingWindow: 120
11
- },
12
- debug: {
13
- diagnosticsEnabled: true,
14
- profilingEnabled: true,
15
- profilingWindow: 240
16
- }
1
+ //#region src/lib/core/scheduler-helpers.ts
2
+ var PRESET_CONFIG = {
3
+ performance: {
4
+ diagnosticsEnabled: false,
5
+ profilingEnabled: false,
6
+ profilingWindow: 60
7
+ },
8
+ balanced: {
9
+ diagnosticsEnabled: true,
10
+ profilingEnabled: true,
11
+ profilingWindow: 120
12
+ },
13
+ debug: {
14
+ diagnosticsEnabled: true,
15
+ profilingEnabled: true,
16
+ profilingWindow: 240
17
+ }
17
18
  };
18
19
  function assertProfilingWindow(value) {
19
- if (!Number.isFinite(value) || value <= 0) {
20
- throw new Error('profilingWindow must be a finite number greater than 0');
21
- }
22
- return Math.floor(value);
20
+ if (!Number.isFinite(value) || value <= 0) throw new Error("profilingWindow must be a finite number greater than 0");
21
+ return Math.floor(value);
23
22
  }
24
23
  /**
25
- * Applies a named scheduler preset to the runtime scheduler instance.
26
- *
27
- * Returns resolved values after overrides for easy logging/telemetry.
28
- */
29
- export function applySchedulerPreset(scheduler, preset, options = {}) {
30
- const base = PRESET_CONFIG[preset];
31
- const diagnosticsEnabled = options.diagnosticsEnabled ?? base.diagnosticsEnabled;
32
- const profilingEnabled = options.profilingEnabled ?? base.profilingEnabled;
33
- if (diagnosticsEnabled !== profilingEnabled) {
34
- throw new Error('MotionGPU scheduler currently shares diagnostics/profiling state; both values must match');
35
- }
36
- const profilingWindow = assertProfilingWindow(options.profilingWindow ?? base.profilingWindow);
37
- scheduler.setProfilingWindow(profilingWindow);
38
- scheduler.setDiagnosticsEnabled(diagnosticsEnabled);
39
- scheduler.setProfilingEnabled(profilingEnabled);
40
- return {
41
- diagnosticsEnabled,
42
- profilingEnabled,
43
- profilingWindow
44
- };
24
+ * Applies a named scheduler preset to the runtime scheduler instance.
25
+ *
26
+ * Returns resolved values after overrides for easy logging/telemetry.
27
+ */
28
+ function applySchedulerPreset(scheduler, preset, options = {}) {
29
+ const base = PRESET_CONFIG[preset];
30
+ const diagnosticsEnabled = options.diagnosticsEnabled ?? base.diagnosticsEnabled;
31
+ const profilingEnabled = options.profilingEnabled ?? base.profilingEnabled;
32
+ if (diagnosticsEnabled !== profilingEnabled) throw new Error("MotionGPU scheduler currently shares diagnostics/profiling state; both values must match");
33
+ const profilingWindow = assertProfilingWindow(options.profilingWindow ?? base.profilingWindow);
34
+ scheduler.setProfilingWindow(profilingWindow);
35
+ scheduler.setDiagnosticsEnabled(diagnosticsEnabled);
36
+ scheduler.setProfilingEnabled(profilingEnabled);
37
+ return {
38
+ diagnosticsEnabled,
39
+ profilingEnabled,
40
+ profilingWindow
41
+ };
45
42
  }
46
43
  /**
47
- * Captures an aggregate scheduler diagnostics snapshot.
48
- */
49
- export function captureSchedulerDebugSnapshot(scheduler) {
50
- return {
51
- diagnosticsEnabled: scheduler.getDiagnosticsEnabled(),
52
- profilingEnabled: scheduler.getProfilingEnabled(),
53
- profilingWindow: scheduler.getProfilingWindow(),
54
- schedule: scheduler.getSchedule(),
55
- lastRunTimings: scheduler.getLastRunTimings(),
56
- profilingSnapshot: scheduler.getProfilingSnapshot()
57
- };
44
+ * Captures an aggregate scheduler diagnostics snapshot.
45
+ */
46
+ function captureSchedulerDebugSnapshot(scheduler) {
47
+ return {
48
+ diagnosticsEnabled: scheduler.getDiagnosticsEnabled(),
49
+ profilingEnabled: scheduler.getProfilingEnabled(),
50
+ profilingWindow: scheduler.getProfilingWindow(),
51
+ schedule: scheduler.getSchedule(),
52
+ lastRunTimings: scheduler.getLastRunTimings(),
53
+ profilingSnapshot: scheduler.getProfilingSnapshot()
54
+ };
58
55
  }
56
+ //#endregion
57
+ export { applySchedulerPreset, captureSchedulerDebugSnapshot };
58
+
59
+ //# sourceMappingURL=scheduler-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler-helpers.js","names":[],"sources":["../../src/lib/core/scheduler-helpers.ts"],"sourcesContent":["import type {\n\tFrameProfilingSnapshot,\n\tFrameRegistry,\n\tFrameRunTimings,\n\tFrameScheduleSnapshot\n} from './frame-registry.js';\n\n/**\n * Public scheduler control surface shared by framework adapters.\n */\nexport type MotionGPUScheduler = Pick<\n\tFrameRegistry,\n\t| 'createStage'\n\t| 'getStage'\n\t| 'setDiagnosticsEnabled'\n\t| 'getDiagnosticsEnabled'\n\t| 'getLastRunTimings'\n\t| 'getSchedule'\n\t| 'setProfilingEnabled'\n\t| 'setProfilingWindow'\n\t| 'resetProfiling'\n\t| 'getProfilingEnabled'\n\t| 'getProfilingWindow'\n\t| 'getProfilingSnapshot'\n>;\n\n/**\n * Named scheduler presets exposed from advanced entrypoints.\n */\nexport type SchedulerPreset = 'balanced' | 'debug' | 'performance';\n\n/**\n * Resolved scheduler timing configuration.\n *\n * Note: diagnostics and profiling currently share one internal toggle in the frame registry.\n */\nexport interface SchedulerPresetConfig {\n\tdiagnosticsEnabled: boolean;\n\tprofilingEnabled: boolean;\n\tprofilingWindow: number;\n}\n\n/**\n * Optional overrides applied on top of a named scheduler preset.\n */\nexport interface ApplySchedulerPresetOptions {\n\tdiagnosticsEnabled?: boolean;\n\tprofilingEnabled?: boolean;\n\tprofilingWindow?: number;\n}\n\n/**\n * Snapshot payload useful for scheduler diagnostics UIs and debug tooling.\n */\nexport interface SchedulerDebugSnapshot {\n\tdiagnosticsEnabled: boolean;\n\tprofilingEnabled: boolean;\n\tprofilingWindow: number;\n\tschedule: FrameScheduleSnapshot;\n\tlastRunTimings: FrameRunTimings | null;\n\tprofilingSnapshot: FrameProfilingSnapshot | null;\n}\n\nconst PRESET_CONFIG: Record<SchedulerPreset, SchedulerPresetConfig> = {\n\tperformance: {\n\t\tdiagnosticsEnabled: false,\n\t\tprofilingEnabled: false,\n\t\tprofilingWindow: 60\n\t},\n\tbalanced: {\n\t\tdiagnosticsEnabled: true,\n\t\tprofilingEnabled: true,\n\t\tprofilingWindow: 120\n\t},\n\tdebug: {\n\t\tdiagnosticsEnabled: true,\n\t\tprofilingEnabled: true,\n\t\tprofilingWindow: 240\n\t}\n};\n\nfunction assertProfilingWindow(value: number): number {\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tthrow new Error('profilingWindow must be a finite number greater than 0');\n\t}\n\n\treturn Math.floor(value);\n}\n\n/**\n * Applies a named scheduler preset to the runtime scheduler instance.\n *\n * Returns resolved values after overrides for easy logging/telemetry.\n */\nexport function applySchedulerPreset(\n\tscheduler: MotionGPUScheduler,\n\tpreset: SchedulerPreset,\n\toptions: ApplySchedulerPresetOptions = {}\n): SchedulerPresetConfig {\n\tconst base = PRESET_CONFIG[preset];\n\tconst diagnosticsEnabled = options.diagnosticsEnabled ?? base.diagnosticsEnabled;\n\tconst profilingEnabled = options.profilingEnabled ?? base.profilingEnabled;\n\tif (diagnosticsEnabled !== profilingEnabled) {\n\t\tthrow new Error(\n\t\t\t'MotionGPU scheduler currently shares diagnostics/profiling state; both values must match'\n\t\t);\n\t}\n\n\tconst profilingWindow = assertProfilingWindow(options.profilingWindow ?? base.profilingWindow);\n\n\tscheduler.setProfilingWindow(profilingWindow);\n\tscheduler.setDiagnosticsEnabled(diagnosticsEnabled);\n\tscheduler.setProfilingEnabled(profilingEnabled);\n\n\treturn {\n\t\tdiagnosticsEnabled,\n\t\tprofilingEnabled,\n\t\tprofilingWindow\n\t};\n}\n\n/**\n * Captures an aggregate scheduler diagnostics snapshot.\n */\nexport function captureSchedulerDebugSnapshot(\n\tscheduler: MotionGPUScheduler\n): SchedulerDebugSnapshot {\n\treturn {\n\t\tdiagnosticsEnabled: scheduler.getDiagnosticsEnabled(),\n\t\tprofilingEnabled: scheduler.getProfilingEnabled(),\n\t\tprofilingWindow: scheduler.getProfilingWindow(),\n\t\tschedule: scheduler.getSchedule(),\n\t\tlastRunTimings: scheduler.getLastRunTimings(),\n\t\tprofilingSnapshot: scheduler.getProfilingSnapshot()\n\t};\n}\n"],"mappings":";AA+DA,IAAM,gBAAgE;CACrE,aAAa;EACZ,oBAAoB;EACpB,kBAAkB;EAClB,iBAAiB;EACjB;CACD,UAAU;EACT,oBAAoB;EACpB,kBAAkB;EAClB,iBAAiB;EACjB;CACD,OAAO;EACN,oBAAoB;EACpB,kBAAkB;EAClB,iBAAiB;EACjB;CACD;AAED,SAAS,sBAAsB,OAAuB;AACrD,KAAI,CAAC,OAAO,SAAS,MAAM,IAAI,SAAS,EACvC,OAAM,IAAI,MAAM,yDAAyD;AAG1E,QAAO,KAAK,MAAM,MAAM;;;;;;;AAQzB,SAAgB,qBACf,WACA,QACA,UAAuC,EAAE,EACjB;CACxB,MAAM,OAAO,cAAc;CAC3B,MAAM,qBAAqB,QAAQ,sBAAsB,KAAK;CAC9D,MAAM,mBAAmB,QAAQ,oBAAoB,KAAK;AAC1D,KAAI,uBAAuB,iBAC1B,OAAM,IAAI,MACT,2FACA;CAGF,MAAM,kBAAkB,sBAAsB,QAAQ,mBAAmB,KAAK,gBAAgB;AAE9F,WAAU,mBAAmB,gBAAgB;AAC7C,WAAU,sBAAsB,mBAAmB;AACnD,WAAU,oBAAoB,iBAAiB;AAE/C,QAAO;EACN;EACA;EACA;EACA;;;;;AAMF,SAAgB,8BACf,WACyB;AACzB,QAAO;EACN,oBAAoB,UAAU,uBAAuB;EACrD,kBAAkB,UAAU,qBAAqB;EACjD,iBAAiB,UAAU,oBAAoB;EAC/C,UAAU,UAAU,aAAa;EACjC,gBAAgB,UAAU,mBAAmB;EAC7C,mBAAmB,UAAU,sBAAsB;EACnD"}
@@ -1,5 +1,5 @@
1
1
  import type { MaterialLineMap, MaterialSourceLocation } from './material-preprocess.js';
2
- import type { UniformLayout } from './types.js';
2
+ import type { StorageBufferType, UniformLayout } from './types.js';
3
3
  /**
4
4
  * 1-based map from generated WGSL lines to original material source lines.
5
5
  */
@@ -28,6 +28,10 @@ export interface BuiltShaderSource {
28
28
  */
29
29
  export declare function buildShaderSource(fragmentWgsl: string, uniformLayout: UniformLayout, textureKeys?: string[], options?: {
30
30
  convertLinearToSrgb?: boolean;
31
+ storageBufferKeys?: string[];
32
+ storageBufferDefinitions?: Record<string, {
33
+ type: StorageBufferType;
34
+ }>;
31
35
  }): string;
32
36
  /**
33
37
  * Assembles complete WGSL shader source with material-source line mapping metadata.
@@ -35,8 +39,13 @@ export declare function buildShaderSource(fragmentWgsl: string, uniformLayout: U
35
39
  export declare function buildShaderSourceWithMap(fragmentWgsl: string, uniformLayout: UniformLayout, textureKeys?: string[], options?: {
36
40
  convertLinearToSrgb?: boolean;
37
41
  fragmentLineMap?: MaterialLineMap;
42
+ storageBufferKeys?: string[];
43
+ storageBufferDefinitions?: Record<string, {
44
+ type: StorageBufferType;
45
+ }>;
38
46
  }): BuiltShaderSource;
39
47
  /**
40
48
  * Converts source location metadata to user-facing diagnostics label.
41
49
  */
42
50
  export declare function formatShaderSourceLocation(location: MaterialSourceLocation | null): string | null;
51
+ //# sourceMappingURL=shader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader.d.ts","sourceRoot":"","sources":["../../src/lib/core/shader.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACxF,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA+InE;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,iBAAiB;IACjC;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,OAAO,EAAE,aAAa,CAAC;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAChC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,GAAE,MAAM,EAAO,EAC1B,OAAO,CAAC,EAAE;IACT,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,iBAAiB,CAAA;KAAE,CAAC,CAAC;CACvE,GACC,MAAM,CAwDR;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CACvC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,aAAa,EAC5B,WAAW,GAAE,MAAM,EAAO,EAC1B,OAAO,CAAC,EAAE;IACT,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,wBAAwB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,iBAAiB,CAAA;KAAE,CAAC,CAAC;CACvE,GACC,iBAAiB,CA4BnB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,sBAAsB,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAcjG"}
@@ -1,69 +1,67 @@
1
- import { assertUniformName } from './uniforms.js';
1
+ import { assertUniformName } from "./uniforms.js";
2
+ //#region src/lib/core/shader.ts
2
3
  /**
3
- * Fallback uniform field used when no custom uniforms are provided.
4
- */
5
- const DEFAULT_UNIFORM_FIELD = 'motiongpu_unused: vec4f,';
4
+ * Fallback uniform field used when no custom uniforms are provided.
5
+ */
6
+ var DEFAULT_UNIFORM_FIELD = "motiongpu_unused: vec4f,";
6
7
  /**
7
- * Builds WGSL struct fields for user uniforms.
8
- */
8
+ * Builds WGSL struct fields for user uniforms.
9
+ */
9
10
  function buildUniformStruct(layout) {
10
- if (layout.entries.length === 0) {
11
- return DEFAULT_UNIFORM_FIELD;
12
- }
13
- return layout.entries
14
- .map((entry) => {
15
- assertUniformName(entry.name);
16
- return `${entry.name}: ${entry.type},`;
17
- })
18
- .join('\n\t');
11
+ if (layout.entries.length === 0) return DEFAULT_UNIFORM_FIELD;
12
+ return layout.entries.map((entry) => {
13
+ assertUniformName(entry.name);
14
+ return `${entry.name}: ${entry.type},`;
15
+ }).join("\n ");
19
16
  }
20
17
  /**
21
- * Builds a numeric expression that references one uniform value to keep bindings alive.
22
- */
18
+ * Builds a numeric expression that references one uniform value to keep bindings alive.
19
+ */
23
20
  function getKeepAliveExpression(layout) {
24
- if (layout.entries.length === 0) {
25
- return 'motiongpuUniforms.motiongpu_unused.x';
26
- }
27
- const [firstEntry] = layout.entries;
28
- if (!firstEntry) {
29
- return 'motiongpuUniforms.motiongpu_unused.x';
30
- }
31
- if (firstEntry.type === 'f32') {
32
- return `motiongpuUniforms.${firstEntry.name}`;
33
- }
34
- if (firstEntry.type === 'mat4x4f') {
35
- return `motiongpuUniforms.${firstEntry.name}[0].x`;
36
- }
37
- return `motiongpuUniforms.${firstEntry.name}.x`;
21
+ if (layout.entries.length === 0) return "motiongpuUniforms.motiongpu_unused.x";
22
+ const [firstEntry] = layout.entries;
23
+ if (!firstEntry) return "motiongpuUniforms.motiongpu_unused.x";
24
+ if (firstEntry.type === "f32") return `motiongpuUniforms.${firstEntry.name}`;
25
+ if (firstEntry.type === "mat4x4f") return `motiongpuUniforms.${firstEntry.name}[0].x`;
26
+ return `motiongpuUniforms.${firstEntry.name}.x`;
38
27
  }
39
28
  /**
40
- * Builds texture sampler/texture binding declarations.
41
- */
29
+ * Builds texture sampler/texture binding declarations.
30
+ */
42
31
  function buildTextureBindings(textureKeys) {
43
- if (textureKeys.length === 0) {
44
- return '';
45
- }
46
- const declarations = [];
47
- for (let index = 0; index < textureKeys.length; index += 1) {
48
- const key = textureKeys[index];
49
- if (key === undefined) {
50
- continue;
51
- }
52
- assertUniformName(key);
53
- const binding = 2 + index * 2;
54
- declarations.push(`@group(0) @binding(${binding}) var ${key}Sampler: sampler;`);
55
- declarations.push(`@group(0) @binding(${binding + 1}) var ${key}: texture_2d<f32>;`);
56
- }
57
- return declarations.join('\n');
32
+ if (textureKeys.length === 0) return "";
33
+ const declarations = [];
34
+ for (let index = 0; index < textureKeys.length; index += 1) {
35
+ const key = textureKeys[index];
36
+ if (key === void 0) continue;
37
+ assertUniformName(key);
38
+ const binding = 2 + index * 2;
39
+ declarations.push(`@group(0) @binding(${binding}) var ${key}Sampler: sampler;`);
40
+ declarations.push(`@group(0) @binding(${binding + 1}) var ${key}: texture_2d<f32>;`);
41
+ }
42
+ return declarations.join("\n");
58
43
  }
59
44
  /**
60
- * Optionally returns helper WGSL for linear-to-sRGB conversion.
61
- */
45
+ * Builds read-only storage buffer bindings for fragment shader.
46
+ */
47
+ function buildFragmentStorageBufferBindings(storageBufferKeys, definitions) {
48
+ if (storageBufferKeys.length === 0) return "";
49
+ const declarations = [];
50
+ for (let index = 0; index < storageBufferKeys.length; index += 1) {
51
+ const key = storageBufferKeys[index];
52
+ if (key === void 0) continue;
53
+ const definition = definitions[key];
54
+ if (!definition) continue;
55
+ declarations.push(`@group(1) @binding(${index}) var<storage, read> ${key}: ${definition.type};`);
56
+ }
57
+ return declarations.join("\n");
58
+ }
59
+ /**
60
+ * Optionally returns helper WGSL for linear-to-sRGB conversion.
61
+ */
62
62
  function buildColorTransformHelpers(enableSrgbTransform) {
63
- if (!enableSrgbTransform) {
64
- return '';
65
- }
66
- return `
63
+ if (!enableSrgbTransform) return "";
64
+ return `
67
65
  fn motiongpuLinearToSrgb(linearColor: vec3f) -> vec3f {
68
66
  let cutoff = vec3f(0.0031308);
69
67
  let lower = linearColor * 12.92;
@@ -73,41 +71,40 @@ fn motiongpuLinearToSrgb(linearColor: vec3f) -> vec3f {
73
71
  `;
74
72
  }
75
73
  /**
76
- * Builds fragment output code with optional color-space conversion.
77
- */
74
+ * Builds fragment output code with optional color-space conversion.
75
+ */
78
76
  function buildFragmentOutput(keepAliveExpression, enableSrgbTransform) {
79
- if (enableSrgbTransform) {
80
- return `
77
+ if (enableSrgbTransform) return `
81
78
  let fragColor = frag(in.uv);
82
79
  let motiongpuKeepAlive = ${keepAliveExpression};
83
80
  let motiongpuLinear = vec4f(fragColor.rgb + motiongpuKeepAlive * 0.0, fragColor.a);
84
81
  let motiongpuSrgb = motiongpuLinearToSrgb(max(motiongpuLinear.rgb, vec3f(0.0)));
85
82
  return vec4f(motiongpuSrgb, motiongpuLinear.a);
86
83
  `;
87
- }
88
- return `
84
+ return `
89
85
  let fragColor = frag(in.uv);
90
86
  let motiongpuKeepAlive = ${keepAliveExpression};
91
87
  return vec4f(fragColor.rgb + motiongpuKeepAlive * 0.0, fragColor.a);
92
88
  `;
93
89
  }
94
90
  /**
95
- * Assembles complete WGSL shader source used by the fullscreen renderer pipeline.
96
- *
97
- * @param fragmentWgsl - User fragment shader code containing `frag(uv: vec2f) -> vec4f`.
98
- * @param uniformLayout - Resolved uniform layout.
99
- * @param textureKeys - Sorted texture keys.
100
- * @param options - Shader build options.
101
- * @returns Complete WGSL source for vertex + fragment stages.
102
- */
103
- export function buildShaderSource(fragmentWgsl, uniformLayout, textureKeys = [], options) {
104
- const uniformFields = buildUniformStruct(uniformLayout);
105
- const keepAliveExpression = getKeepAliveExpression(uniformLayout);
106
- const textureBindings = buildTextureBindings(textureKeys);
107
- const enableSrgbTransform = options?.convertLinearToSrgb ?? false;
108
- const colorTransformHelpers = buildColorTransformHelpers(enableSrgbTransform);
109
- const fragmentOutput = buildFragmentOutput(keepAliveExpression, enableSrgbTransform);
110
- return `
91
+ * Assembles complete WGSL shader source used by the fullscreen renderer pipeline.
92
+ *
93
+ * @param fragmentWgsl - User fragment shader code containing `frag(uv: vec2f) -> vec4f`.
94
+ * @param uniformLayout - Resolved uniform layout.
95
+ * @param textureKeys - Sorted texture keys.
96
+ * @param options - Shader build options.
97
+ * @returns Complete WGSL source for vertex + fragment stages.
98
+ */
99
+ function buildShaderSource(fragmentWgsl, uniformLayout, textureKeys = [], options) {
100
+ const uniformFields = buildUniformStruct(uniformLayout);
101
+ const keepAliveExpression = getKeepAliveExpression(uniformLayout);
102
+ const textureBindings = buildTextureBindings(textureKeys);
103
+ const enableSrgbTransform = options?.convertLinearToSrgb ?? false;
104
+ const colorTransformHelpers = buildColorTransformHelpers(enableSrgbTransform);
105
+ const fragmentOutput = buildFragmentOutput(keepAliveExpression, enableSrgbTransform);
106
+ const storageBufferBindings = buildFragmentStorageBufferBindings(options?.storageBufferKeys ?? [], options?.storageBufferDefinitions ?? {});
107
+ return `
111
108
  struct MotionGPUFrame {
112
109
  time: f32,
113
110
  delta: f32,
@@ -121,6 +118,7 @@ struct MotionGPUUniforms {
121
118
  @group(0) @binding(0) var<uniform> motiongpuFrame: MotionGPUFrame;
122
119
  @group(0) @binding(1) var<uniform> motiongpuUniforms: MotionGPUUniforms;
123
120
  ${textureBindings}
121
+ ${storageBufferBindings ? "\n" + storageBufferBindings : ""}
124
122
  ${colorTransformHelpers}
125
123
 
126
124
  struct MotionGPUVertexOut {
@@ -152,45 +150,41 @@ fn motiongpuFragment(in: MotionGPUVertexOut) -> @location(0) vec4f {
152
150
  `;
153
151
  }
154
152
  /**
155
- * Assembles complete WGSL shader source with material-source line mapping metadata.
156
- */
157
- export function buildShaderSourceWithMap(fragmentWgsl, uniformLayout, textureKeys = [], options) {
158
- const code = buildShaderSource(fragmentWgsl, uniformLayout, textureKeys, options);
159
- const fragmentStartIndex = code.indexOf(fragmentWgsl);
160
- const lineCount = code.split('\n').length;
161
- const lineMap = new Array(lineCount + 1).fill(null);
162
- if (fragmentStartIndex === -1) {
163
- return {
164
- code,
165
- lineMap
166
- };
167
- }
168
- const fragmentStartLine = code.slice(0, fragmentStartIndex).split('\n').length;
169
- const fragmentLineCount = fragmentWgsl.split('\n').length;
170
- for (let line = 0; line < fragmentLineCount; line += 1) {
171
- const generatedLine = fragmentStartLine + line;
172
- lineMap[generatedLine] = options?.fragmentLineMap?.[line + 1] ?? {
173
- kind: 'fragment',
174
- line: line + 1
175
- };
176
- }
177
- return {
178
- code,
179
- lineMap
180
- };
153
+ * Assembles complete WGSL shader source with material-source line mapping metadata.
154
+ */
155
+ function buildShaderSourceWithMap(fragmentWgsl, uniformLayout, textureKeys = [], options) {
156
+ const code = buildShaderSource(fragmentWgsl, uniformLayout, textureKeys, options);
157
+ const fragmentStartIndex = code.indexOf(fragmentWgsl);
158
+ const lineCount = code.split("\n").length;
159
+ const lineMap = new Array(lineCount + 1).fill(null);
160
+ if (fragmentStartIndex === -1) return {
161
+ code,
162
+ lineMap
163
+ };
164
+ const fragmentStartLine = code.slice(0, fragmentStartIndex).split("\n").length;
165
+ const fragmentLineCount = fragmentWgsl.split("\n").length;
166
+ for (let line = 0; line < fragmentLineCount; line += 1) {
167
+ const generatedLine = fragmentStartLine + line;
168
+ lineMap[generatedLine] = options?.fragmentLineMap?.[line + 1] ?? {
169
+ kind: "fragment",
170
+ line: line + 1
171
+ };
172
+ }
173
+ return {
174
+ code,
175
+ lineMap
176
+ };
181
177
  }
182
178
  /**
183
- * Converts source location metadata to user-facing diagnostics label.
184
- */
185
- export function formatShaderSourceLocation(location) {
186
- if (!location) {
187
- return null;
188
- }
189
- if (location.kind === 'fragment') {
190
- return `fragment line ${location.line}`;
191
- }
192
- if (location.kind === 'include') {
193
- return `include <${location.include}> line ${location.line}`;
194
- }
195
- return `define "${location.define}" line ${location.line}`;
179
+ * Converts source location metadata to user-facing diagnostics label.
180
+ */
181
+ function formatShaderSourceLocation(location) {
182
+ if (!location) return null;
183
+ if (location.kind === "fragment") return `fragment line ${location.line}`;
184
+ if (location.kind === "include") return `include <${location.include}> line ${location.line}`;
185
+ return `define "${location.define}" line ${location.line}`;
196
186
  }
187
+ //#endregion
188
+ export { buildShaderSource, buildShaderSourceWithMap, formatShaderSourceLocation };
189
+
190
+ //# sourceMappingURL=shader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shader.js","names":[],"sources":["../../src/lib/core/shader.ts"],"sourcesContent":["import { assertUniformName } from './uniforms.js';\nimport type { MaterialLineMap, MaterialSourceLocation } from './material-preprocess.js';\nimport type { StorageBufferType, UniformLayout } from './types.js';\n\n/**\n * Fallback uniform field used when no custom uniforms are provided.\n */\nconst DEFAULT_UNIFORM_FIELD = 'motiongpu_unused: vec4f,';\n\n/**\n * Builds WGSL struct fields for user uniforms.\n */\nfunction buildUniformStruct(layout: UniformLayout): string {\n\tif (layout.entries.length === 0) {\n\t\treturn DEFAULT_UNIFORM_FIELD;\n\t}\n\n\treturn layout.entries\n\t\t.map((entry) => {\n\t\t\tassertUniformName(entry.name);\n\t\t\treturn `${entry.name}: ${entry.type},`;\n\t\t})\n\t\t.join('\\n\\t');\n}\n\n/**\n * Builds a numeric expression that references one uniform value to keep bindings alive.\n */\nfunction getKeepAliveExpression(layout: UniformLayout): string {\n\tif (layout.entries.length === 0) {\n\t\treturn 'motiongpuUniforms.motiongpu_unused.x';\n\t}\n\n\tconst [firstEntry] = layout.entries;\n\tif (!firstEntry) {\n\t\treturn 'motiongpuUniforms.motiongpu_unused.x';\n\t}\n\n\tif (firstEntry.type === 'f32') {\n\t\treturn `motiongpuUniforms.${firstEntry.name}`;\n\t}\n\n\tif (firstEntry.type === 'mat4x4f') {\n\t\treturn `motiongpuUniforms.${firstEntry.name}[0].x`;\n\t}\n\n\treturn `motiongpuUniforms.${firstEntry.name}.x`;\n}\n\n/**\n * Builds texture sampler/texture binding declarations.\n */\nfunction buildTextureBindings(textureKeys: string[]): string {\n\tif (textureKeys.length === 0) {\n\t\treturn '';\n\t}\n\n\tconst declarations: string[] = [];\n\n\tfor (let index = 0; index < textureKeys.length; index += 1) {\n\t\tconst key = textureKeys[index];\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tassertUniformName(key);\n\t\tconst binding = 2 + index * 2;\n\t\tdeclarations.push(`@group(0) @binding(${binding}) var ${key}Sampler: sampler;`);\n\t\tdeclarations.push(`@group(0) @binding(${binding + 1}) var ${key}: texture_2d<f32>;`);\n\t}\n\n\treturn declarations.join('\\n');\n}\n\n/**\n * Builds read-only storage buffer bindings for fragment shader.\n */\nfunction buildFragmentStorageBufferBindings(\n\tstorageBufferKeys: string[],\n\tdefinitions: Record<string, { type: StorageBufferType }>\n): string {\n\tif (storageBufferKeys.length === 0) {\n\t\treturn '';\n\t}\n\n\tconst declarations: string[] = [];\n\n\tfor (let index = 0; index < storageBufferKeys.length; index += 1) {\n\t\tconst key = storageBufferKeys[index];\n\t\tif (key === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst definition = definitions[key];\n\t\tif (!definition) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdeclarations.push(\n\t\t\t`@group(1) @binding(${index}) var<storage, read> ${key}: ${definition.type};`\n\t\t);\n\t}\n\n\treturn declarations.join('\\n');\n}\n\n/**\n * Optionally returns helper WGSL for linear-to-sRGB conversion.\n */\nfunction buildColorTransformHelpers(enableSrgbTransform: boolean): string {\n\tif (!enableSrgbTransform) {\n\t\treturn '';\n\t}\n\n\treturn `\nfn motiongpuLinearToSrgb(linearColor: vec3f) -> vec3f {\n\tlet cutoff = vec3f(0.0031308);\n\tlet lower = linearColor * 12.92;\n\tlet higher = vec3f(1.055) * pow(linearColor, vec3f(1.0 / 2.4)) - vec3f(0.055);\n\treturn select(lower, higher, linearColor > cutoff);\n}\n`;\n}\n\n/**\n * Builds fragment output code with optional color-space conversion.\n */\nfunction buildFragmentOutput(keepAliveExpression: string, enableSrgbTransform: boolean): string {\n\tif (enableSrgbTransform) {\n\t\treturn `\n\tlet fragColor = frag(in.uv);\n\tlet motiongpuKeepAlive = ${keepAliveExpression};\n\tlet motiongpuLinear = vec4f(fragColor.rgb + motiongpuKeepAlive * 0.0, fragColor.a);\n\tlet motiongpuSrgb = motiongpuLinearToSrgb(max(motiongpuLinear.rgb, vec3f(0.0)));\n\treturn vec4f(motiongpuSrgb, motiongpuLinear.a);\n`;\n\t}\n\n\treturn `\n\tlet fragColor = frag(in.uv);\n\tlet motiongpuKeepAlive = ${keepAliveExpression};\n\treturn vec4f(fragColor.rgb + motiongpuKeepAlive * 0.0, fragColor.a);\n`;\n}\n\n/**\n * 1-based map from generated WGSL lines to original material source lines.\n */\nexport type ShaderLineMap = Array<MaterialSourceLocation | null>;\n\n/**\n * Result of shader source generation with line mapping metadata.\n */\nexport interface BuiltShaderSource {\n\t/**\n\t * Full WGSL source code.\n\t */\n\tcode: string;\n\t/**\n\t * 1-based generated-line map to material source locations.\n\t */\n\tlineMap: ShaderLineMap;\n}\n\n/**\n * Assembles complete WGSL shader source used by the fullscreen renderer pipeline.\n *\n * @param fragmentWgsl - User fragment shader code containing `frag(uv: vec2f) -> vec4f`.\n * @param uniformLayout - Resolved uniform layout.\n * @param textureKeys - Sorted texture keys.\n * @param options - Shader build options.\n * @returns Complete WGSL source for vertex + fragment stages.\n */\nexport function buildShaderSource(\n\tfragmentWgsl: string,\n\tuniformLayout: UniformLayout,\n\ttextureKeys: string[] = [],\n\toptions?: {\n\t\tconvertLinearToSrgb?: boolean;\n\t\tstorageBufferKeys?: string[];\n\t\tstorageBufferDefinitions?: Record<string, { type: StorageBufferType }>;\n\t}\n): string {\n\tconst uniformFields = buildUniformStruct(uniformLayout);\n\tconst keepAliveExpression = getKeepAliveExpression(uniformLayout);\n\tconst textureBindings = buildTextureBindings(textureKeys);\n\tconst enableSrgbTransform = options?.convertLinearToSrgb ?? false;\n\tconst colorTransformHelpers = buildColorTransformHelpers(enableSrgbTransform);\n\tconst fragmentOutput = buildFragmentOutput(keepAliveExpression, enableSrgbTransform);\n\tconst storageBufferBindings = buildFragmentStorageBufferBindings(\n\t\toptions?.storageBufferKeys ?? [],\n\t\toptions?.storageBufferDefinitions ?? {}\n\t);\n\n\treturn `\nstruct MotionGPUFrame {\n\ttime: f32,\n\tdelta: f32,\n\tresolution: vec2f,\n};\n\nstruct MotionGPUUniforms {\n\t${uniformFields}\n};\n\n@group(0) @binding(0) var<uniform> motiongpuFrame: MotionGPUFrame;\n@group(0) @binding(1) var<uniform> motiongpuUniforms: MotionGPUUniforms;\n${textureBindings}\n${storageBufferBindings ? '\\n' + storageBufferBindings : ''}\n${colorTransformHelpers}\n\nstruct MotionGPUVertexOut {\n\t@builtin(position) position: vec4f,\n\t@location(0) uv: vec2f,\n};\n\n@vertex\nfn motiongpuVertex(@builtin(vertex_index) index: u32) -> MotionGPUVertexOut {\n\tvar positions = array<vec2f, 3>(\n\t\tvec2f(-1.0, -3.0),\n\t\tvec2f(-1.0, 1.0),\n\t\tvec2f(3.0, 1.0)\n\t);\n\n\tlet position = positions[index];\n\tvar out: MotionGPUVertexOut;\n\tout.position = vec4f(position, 0.0, 1.0);\n\tout.uv = (position + vec2f(1.0, 1.0)) * 0.5;\n\treturn out;\n}\n\n${fragmentWgsl}\n\n@fragment\nfn motiongpuFragment(in: MotionGPUVertexOut) -> @location(0) vec4f {\n\t${fragmentOutput}\n}\n`;\n}\n\n/**\n * Assembles complete WGSL shader source with material-source line mapping metadata.\n */\nexport function buildShaderSourceWithMap(\n\tfragmentWgsl: string,\n\tuniformLayout: UniformLayout,\n\ttextureKeys: string[] = [],\n\toptions?: {\n\t\tconvertLinearToSrgb?: boolean;\n\t\tfragmentLineMap?: MaterialLineMap;\n\t\tstorageBufferKeys?: string[];\n\t\tstorageBufferDefinitions?: Record<string, { type: StorageBufferType }>;\n\t}\n): BuiltShaderSource {\n\tconst code = buildShaderSource(fragmentWgsl, uniformLayout, textureKeys, options);\n\tconst fragmentStartIndex = code.indexOf(fragmentWgsl);\n\tconst lineCount = code.split('\\n').length;\n\tconst lineMap: ShaderLineMap = new Array(lineCount + 1).fill(null);\n\n\tif (fragmentStartIndex === -1) {\n\t\treturn {\n\t\t\tcode,\n\t\t\tlineMap\n\t\t};\n\t}\n\n\tconst fragmentStartLine = code.slice(0, fragmentStartIndex).split('\\n').length;\n\tconst fragmentLineCount = fragmentWgsl.split('\\n').length;\n\n\tfor (let line = 0; line < fragmentLineCount; line += 1) {\n\t\tconst generatedLine = fragmentStartLine + line;\n\t\tlineMap[generatedLine] = options?.fragmentLineMap?.[line + 1] ?? {\n\t\t\tkind: 'fragment',\n\t\t\tline: line + 1\n\t\t};\n\t}\n\n\treturn {\n\t\tcode,\n\t\tlineMap\n\t};\n}\n\n/**\n * Converts source location metadata to user-facing diagnostics label.\n */\nexport function formatShaderSourceLocation(location: MaterialSourceLocation | null): string | null {\n\tif (!location) {\n\t\treturn null;\n\t}\n\n\tif (location.kind === 'fragment') {\n\t\treturn `fragment line ${location.line}`;\n\t}\n\n\tif (location.kind === 'include') {\n\t\treturn `include <${location.include}> line ${location.line}`;\n\t}\n\n\treturn `define \"${location.define}\" line ${location.line}`;\n}\n"],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /// <reference types="@webgpu/types" />
2
+ import type { StorageBufferDefinition, StorageBufferDefinitionMap } from './types.js';
3
+ /**
4
+ * Storage-compatible texture formats for `texture_storage_2d`.
5
+ */
6
+ export declare const STORAGE_TEXTURE_FORMATS: ReadonlySet<GPUTextureFormat>;
7
+ /**
8
+ * Validates a single storage buffer definition.
9
+ *
10
+ * @param name - Buffer identifier.
11
+ * @param definition - Storage buffer definition to validate.
12
+ * @throws {Error} When any field is invalid.
13
+ */
14
+ export declare function assertStorageBufferDefinition(name: string, definition: StorageBufferDefinition): void;
15
+ /**
16
+ * Validates and returns sorted storage buffer keys.
17
+ *
18
+ * @param definitions - Storage buffer definition map.
19
+ * @returns Lexicographically sorted buffer keys.
20
+ */
21
+ export declare function resolveStorageBufferKeys(definitions: StorageBufferDefinitionMap): string[];
22
+ /**
23
+ * Normalizes a storage buffer definition with defaults applied.
24
+ *
25
+ * @param definition - Raw definition.
26
+ * @returns Normalized definition with access default.
27
+ */
28
+ export declare function normalizeStorageBufferDefinition(definition: StorageBufferDefinition): Required<Pick<StorageBufferDefinition, 'size' | 'type' | 'access'>>;
29
+ /**
30
+ * Validates that a texture format is storage-compatible.
31
+ *
32
+ * @param name - Texture identifier.
33
+ * @param format - GPU texture format.
34
+ * @throws {Error} When format is not storage-compatible.
35
+ */
36
+ export declare function assertStorageTextureFormat(name: string, format: GPUTextureFormat): void;
37
+ //# sourceMappingURL=storage-buffers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-buffers.d.ts","sourceRoot":"","sources":["../../src/lib/core/storage-buffers.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EACX,uBAAuB,EACvB,0BAA0B,EAE1B,MAAM,YAAY,CAAC;AAgBpB;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,gBAAgB,CAkB1C,CAAC;AAEzB;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAC5C,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,uBAAuB,GACjC,IAAI,CAsCN;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,0BAA0B,GAAG,MAAM,EAAE,CAS1F;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,CAC/C,UAAU,EAAE,uBAAuB,GACjC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,EAAE,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC,CAAC,CAMrE;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAOvF"}