@motion-core/motion-gpu 0.5.0 → 0.7.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 (71) hide show
  1. package/README.md +35 -2
  2. package/dist/core/compute-bindgroup-cache.d.ts +13 -0
  3. package/dist/core/compute-bindgroup-cache.d.ts.map +1 -0
  4. package/dist/core/compute-bindgroup-cache.js +45 -0
  5. package/dist/core/compute-bindgroup-cache.js.map +1 -0
  6. package/dist/core/compute-shader.d.ts +48 -0
  7. package/dist/core/compute-shader.d.ts.map +1 -1
  8. package/dist/core/compute-shader.js +34 -1
  9. package/dist/core/compute-shader.js.map +1 -1
  10. package/dist/core/error-diagnostics.d.ts +8 -1
  11. package/dist/core/error-diagnostics.d.ts.map +1 -1
  12. package/dist/core/error-diagnostics.js +7 -3
  13. package/dist/core/error-diagnostics.js.map +1 -1
  14. package/dist/core/error-report.d.ts.map +1 -1
  15. package/dist/core/error-report.js +19 -1
  16. package/dist/core/error-report.js.map +1 -1
  17. package/dist/core/material.d.ts.map +1 -1
  18. package/dist/core/material.js +2 -1
  19. package/dist/core/material.js.map +1 -1
  20. package/dist/core/pointer.d.ts +96 -0
  21. package/dist/core/pointer.d.ts.map +1 -0
  22. package/dist/core/pointer.js +71 -0
  23. package/dist/core/pointer.js.map +1 -0
  24. package/dist/core/renderer.d.ts.map +1 -1
  25. package/dist/core/renderer.js +150 -85
  26. package/dist/core/renderer.js.map +1 -1
  27. package/dist/core/runtime-loop.d.ts.map +1 -1
  28. package/dist/core/runtime-loop.js +26 -14
  29. package/dist/core/runtime-loop.js.map +1 -1
  30. package/dist/core/shader.d.ts +7 -2
  31. package/dist/core/shader.d.ts.map +1 -1
  32. package/dist/core/shader.js +1 -0
  33. package/dist/core/shader.js.map +1 -1
  34. package/dist/core/textures.d.ts +4 -0
  35. package/dist/core/textures.d.ts.map +1 -1
  36. package/dist/core/textures.js +2 -1
  37. package/dist/core/textures.js.map +1 -1
  38. package/dist/core/types.d.ts +1 -1
  39. package/dist/core/types.d.ts.map +1 -1
  40. package/dist/react/advanced.js +2 -1
  41. package/dist/react/index.d.ts +2 -0
  42. package/dist/react/index.d.ts.map +1 -1
  43. package/dist/react/index.js +2 -1
  44. package/dist/react/use-pointer.d.ts +94 -0
  45. package/dist/react/use-pointer.d.ts.map +1 -0
  46. package/dist/react/use-pointer.js +285 -0
  47. package/dist/react/use-pointer.js.map +1 -0
  48. package/dist/svelte/advanced.js +2 -1
  49. package/dist/svelte/index.d.ts +2 -0
  50. package/dist/svelte/index.d.ts.map +1 -1
  51. package/dist/svelte/index.js +2 -1
  52. package/dist/svelte/use-pointer.d.ts +94 -0
  53. package/dist/svelte/use-pointer.d.ts.map +1 -0
  54. package/dist/svelte/use-pointer.js +292 -0
  55. package/dist/svelte/use-pointer.js.map +1 -0
  56. package/package.json +1 -1
  57. package/src/lib/core/compute-bindgroup-cache.ts +73 -0
  58. package/src/lib/core/compute-shader.ts +86 -0
  59. package/src/lib/core/error-diagnostics.ts +29 -4
  60. package/src/lib/core/error-report.ts +26 -1
  61. package/src/lib/core/material.ts +2 -1
  62. package/src/lib/core/pointer.ts +177 -0
  63. package/src/lib/core/renderer.ts +198 -92
  64. package/src/lib/core/runtime-loop.ts +37 -16
  65. package/src/lib/core/shader.ts +13 -2
  66. package/src/lib/core/textures.ts +6 -1
  67. package/src/lib/core/types.ts +1 -1
  68. package/src/lib/react/index.ts +10 -0
  69. package/src/lib/react/use-pointer.ts +515 -0
  70. package/src/lib/svelte/index.ts +10 -0
  71. package/src/lib/svelte/use-pointer.ts +507 -0
@@ -1 +1 @@
1
- {"version":3,"file":"renderer.js","names":[],"sources":["../../src/lib/core/renderer.ts"],"sourcesContent":["import { buildRenderTargetSignature, resolveRenderTargetDefinitions } from './render-targets.js';\nimport { planRenderGraph, type RenderGraphPlan } from './render-graph.js';\nimport {\n\tbuildShaderSourceWithMap,\n\tformatShaderSourceLocation,\n\ttype ShaderLineMap\n} from './shader.js';\nimport {\n\tattachShaderCompilationDiagnostics,\n\ttype ShaderCompilationRuntimeContext\n} from './error-diagnostics.js';\nimport {\n\tgetTextureMipLevelCount,\n\tnormalizeTextureDefinitions,\n\tresolveTextureUpdateMode,\n\tresolveTextureSize,\n\ttoTextureData\n} from './textures.js';\nimport { packUniformsInto } from './uniforms.js';\nimport {\n\tbuildComputeShaderSource,\n\tbuildPingPongComputeShaderSource,\n\textractWorkgroupSize,\n\tstorageTextureSampleScalarType\n} from './compute-shader.js';\nimport { normalizeStorageBufferDefinition } from './storage-buffers.js';\nimport type {\n\tAnyPass,\n\tRenderPass,\n\tRenderPassInputSlot,\n\tRenderPassOutputSlot,\n\tRenderMode,\n\tRenderTarget,\n\tRenderer,\n\tRendererOptions,\n\tStorageBufferAccess,\n\tStorageBufferType,\n\tTextureSource,\n\tTextureUpdateMode,\n\tTextureValue\n} from './types.js';\n\n/**\n * Binding index for frame uniforms (`time`, `delta`, `resolution`).\n */\nconst FRAME_BINDING = 0;\n\n/**\n * Binding index for material uniform buffer.\n */\nconst UNIFORM_BINDING = 1;\n\n/**\n * First binding index used for texture sampler/texture pairs.\n */\nconst FIRST_TEXTURE_BINDING = 2;\n\n/**\n * Runtime texture binding state associated with a single texture key.\n */\ninterface RuntimeTextureBinding {\n\tkey: string;\n\tsamplerBinding: number;\n\ttextureBinding: number;\n\tsampler: GPUSampler;\n\tfallbackTexture: GPUTexture;\n\tfallbackView: GPUTextureView;\n\ttexture: GPUTexture | null;\n\tview: GPUTextureView;\n\tsource: TextureSource | null;\n\twidth: number | undefined;\n\theight: number | undefined;\n\tmipLevelCount: number;\n\tformat: GPUTextureFormat;\n\tcolorSpace: 'srgb' | 'linear';\n\tdefaultColorSpace: 'srgb' | 'linear';\n\tflipY: boolean;\n\tdefaultFlipY: boolean;\n\tgenerateMipmaps: boolean;\n\tdefaultGenerateMipmaps: boolean;\n\tpremultipliedAlpha: boolean;\n\tdefaultPremultipliedAlpha: boolean;\n\tupdate: TextureUpdateMode;\n\tdefaultUpdate?: TextureUpdateMode;\n\tlastToken: TextureValue;\n}\n\n/**\n * Runtime render target allocation metadata.\n */\ninterface RuntimeRenderTarget {\n\ttexture: GPUTexture;\n\tview: GPUTextureView;\n\twidth: number;\n\theight: number;\n\tformat: GPUTextureFormat;\n}\n\n/**\n * Runtime ping-pong storage textures for a single logical target key.\n */\ninterface PingPongTexturePair {\n\ttarget: string;\n\tformat: GPUTextureFormat;\n\twidth: number;\n\theight: number;\n\ttextureA: GPUTexture;\n\tviewA: GPUTextureView;\n\ttextureB: GPUTexture;\n\tviewB: GPUTextureView;\n\tbindGroupLayout: GPUBindGroupLayout;\n}\n\n/**\n * Cached pass properties used to validate render-graph cache correctness.\n */\ninterface RenderGraphPassSnapshot {\n\tpass: AnyPass;\n\tenabled: RenderPass['enabled'];\n\tneedsSwap: RenderPass['needsSwap'];\n\tinput: RenderPass['input'];\n\toutput: RenderPass['output'];\n\tclear: RenderPass['clear'];\n\tpreserve: RenderPass['preserve'];\n\thasClearColor: boolean;\n\tclearColor0: number;\n\tclearColor1: number;\n\tclearColor2: number;\n\tclearColor3: number;\n}\n\n/**\n * Returns sampler/texture binding slots for a texture index.\n */\nfunction getTextureBindings(index: number): {\n\tsamplerBinding: number;\n\ttextureBinding: number;\n} {\n\tconst samplerBinding = FIRST_TEXTURE_BINDING + index * 2;\n\treturn {\n\t\tsamplerBinding,\n\t\ttextureBinding: samplerBinding + 1\n\t};\n}\n\n/**\n * Maps WGSL scalar texture type to WebGPU sampled texture bind-group sample type.\n */\nfunction toGpuTextureSampleType(type: 'f32' | 'u32' | 'i32'): GPUTextureSampleType {\n\tif (type === 'u32') {\n\t\treturn 'uint';\n\t}\n\tif (type === 'i32') {\n\t\treturn 'sint';\n\t}\n\treturn 'float';\n}\n\n/**\n * Resizes canvas backing store to match client size and DPR.\n */\nfunction resizeCanvas(\n\tcanvas: HTMLCanvasElement,\n\tdprInput: number,\n\tcssSize?: { width: number; height: number }\n): { width: number; height: number } {\n\tconst dpr = Number.isFinite(dprInput) && dprInput > 0 ? dprInput : 1;\n\tconst rect = cssSize ? null : canvas.getBoundingClientRect();\n\tconst cssWidth = Math.max(0, cssSize?.width ?? rect?.width ?? 0);\n\tconst cssHeight = Math.max(0, cssSize?.height ?? rect?.height ?? 0);\n\tconst width = Math.max(1, Math.floor((cssWidth || 1) * dpr));\n\tconst height = Math.max(1, Math.floor((cssHeight || 1) * dpr));\n\n\tif (canvas.width !== width || canvas.height !== height) {\n\t\tcanvas.width = width;\n\t\tcanvas.height = height;\n\t}\n\n\treturn { width, height };\n}\n\n/**\n * Throws when a shader module contains WGSL compilation errors.\n */\nasync function assertCompilation(\n\tmodule: GPUShaderModule,\n\toptions?: {\n\t\tlineMap?: ShaderLineMap;\n\t\tfragmentSource?: string;\n\t\tincludeSources?: Record<string, string>;\n\t\tdefineBlockSource?: string;\n\t\tmaterialSource?: {\n\t\t\tcomponent?: string;\n\t\t\tfile?: string;\n\t\t\tline?: number;\n\t\t\tcolumn?: number;\n\t\t\tfunctionName?: string;\n\t\t} | null;\n\t\truntimeContext?: ShaderCompilationRuntimeContext;\n\t}\n): Promise<void> {\n\tconst info = await module.getCompilationInfo();\n\tconst errors = info.messages.filter((message: GPUCompilationMessage) => message.type === 'error');\n\n\tif (errors.length === 0) {\n\t\treturn;\n\t}\n\n\tconst diagnostics = errors.map((message: GPUCompilationMessage) => ({\n\t\tgeneratedLine: message.lineNum,\n\t\tmessage: message.message,\n\t\tlinePos: message.linePos,\n\t\tlineLength: message.length,\n\t\tsourceLocation: options?.lineMap?.[message.lineNum] ?? null\n\t}));\n\n\tconst summary = diagnostics\n\t\t.map((diagnostic) => {\n\t\t\tconst sourceLabel = formatShaderSourceLocation(diagnostic.sourceLocation);\n\t\t\tconst generatedLineLabel =\n\t\t\t\tdiagnostic.generatedLine > 0 ? `generated WGSL line ${diagnostic.generatedLine}` : null;\n\t\t\tconst contextLabel = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\t\t\tif (contextLabel.length === 0) {\n\t\t\t\treturn diagnostic.message;\n\t\t\t}\n\n\t\t\treturn `[${contextLabel.join(' | ')}] ${diagnostic.message}`;\n\t\t})\n\t\t.join('\\n');\n\tconst error = new Error(`WGSL compilation failed:\\n${summary}`);\n\tthrow attachShaderCompilationDiagnostics(error, {\n\t\tkind: 'shader-compilation',\n\t\tdiagnostics,\n\t\tfragmentSource: options?.fragmentSource ?? '',\n\t\tincludeSources: options?.includeSources ?? {},\n\t\t...(options?.defineBlockSource !== undefined\n\t\t\t? { defineBlockSource: options.defineBlockSource }\n\t\t\t: {}),\n\t\tmaterialSource: options?.materialSource ?? null,\n\t\t...(options?.runtimeContext !== undefined ? { runtimeContext: options.runtimeContext } : {})\n\t});\n}\n\nfunction toSortedUniqueStrings(values: string[]): string[] {\n\treturn Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));\n}\n\nfunction buildPassGraphSnapshot(\n\tpasses: AnyPass[] | undefined\n): NonNullable<ShaderCompilationRuntimeContext['passGraph']> {\n\tconst declaredPasses = passes ?? [];\n\tlet enabledPassCount = 0;\n\tconst inputs: string[] = [];\n\tconst outputs: string[] = [];\n\n\tfor (const pass of declaredPasses) {\n\t\tif (pass.enabled === false) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tenabledPassCount += 1;\n\t\tif ('isCompute' in pass && (pass as { isCompute?: boolean }).isCompute === true) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst rp = pass as RenderPass;\n\t\tconst needsSwap = rp.needsSwap ?? true;\n\t\tconst input = rp.input ?? 'source';\n\t\tconst output = rp.output ?? (needsSwap ? 'target' : 'source');\n\t\tinputs.push(input);\n\t\toutputs.push(output);\n\t}\n\n\treturn {\n\t\tpassCount: declaredPasses.length,\n\t\tenabledPassCount,\n\t\tinputs: toSortedUniqueStrings(inputs),\n\t\toutputs: toSortedUniqueStrings(outputs)\n\t};\n}\n\nfunction buildShaderCompilationRuntimeContext(\n\toptions: RendererOptions\n): ShaderCompilationRuntimeContext {\n\tconst passList = options.getPasses?.() ?? options.passes;\n\tconst renderTargetMap = options.getRenderTargets?.() ?? options.renderTargets;\n\n\treturn {\n\t\t...(options.materialSignature ? { materialSignature: options.materialSignature } : {}),\n\t\tpassGraph: buildPassGraphSnapshot(passList),\n\t\tactiveRenderTargets: Object.keys(renderTargetMap ?? {}).sort((a, b) => a.localeCompare(b))\n\t};\n}\n\n/**\n * Creates a 1x1 white fallback texture used before user textures become available.\n */\nfunction createFallbackTexture(device: GPUDevice, format: GPUTextureFormat): GPUTexture {\n\tconst texture = device.createTexture({\n\t\tsize: { width: 1, height: 1, depthOrArrayLayers: 1 },\n\t\tformat,\n\t\tusage:\n\t\t\tGPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT\n\t});\n\n\tconst pixel = new Uint8Array([255, 255, 255, 255]);\n\tdevice.queue.writeTexture(\n\t\t{ texture },\n\t\tpixel,\n\t\t{ offset: 0, bytesPerRow: 4, rowsPerImage: 1 },\n\t\t{ width: 1, height: 1, depthOrArrayLayers: 1 }\n\t);\n\n\treturn texture;\n}\n\n/**\n * Creates an offscreen canvas used for CPU mipmap generation.\n */\nfunction createMipmapCanvas(width: number, height: number): OffscreenCanvas | HTMLCanvasElement {\n\tif (typeof OffscreenCanvas !== 'undefined') {\n\t\treturn new OffscreenCanvas(width, height);\n\t}\n\n\tconst canvas = document.createElement('canvas');\n\tcanvas.width = width;\n\tcanvas.height = height;\n\treturn canvas;\n}\n\n/**\n * Creates typed descriptor for `copyExternalImageToTexture`.\n */\nfunction createExternalCopySource(\n\tsource: CanvasImageSource,\n\toptions: { flipY?: boolean; premultipliedAlpha?: boolean }\n): GPUCopyExternalImageSourceInfo {\n\tconst descriptor = {\n\t\tsource,\n\t\t...(options.flipY ? { flipY: true } : {}),\n\t\t...(options.premultipliedAlpha ? { premultipliedAlpha: true } : {})\n\t};\n\n\treturn descriptor as GPUCopyExternalImageSourceInfo;\n}\n\n/**\n * Uploads source content to a GPU texture and optionally generates mip chain on CPU.\n */\nfunction uploadTexture(\n\tdevice: GPUDevice,\n\ttexture: GPUTexture,\n\tbinding: Pick<RuntimeTextureBinding, 'flipY' | 'premultipliedAlpha' | 'generateMipmaps'>,\n\tsource: TextureSource,\n\twidth: number,\n\theight: number,\n\tmipLevelCount: number\n): void {\n\tdevice.queue.copyExternalImageToTexture(\n\t\tcreateExternalCopySource(source, {\n\t\t\tflipY: binding.flipY,\n\t\t\tpremultipliedAlpha: binding.premultipliedAlpha\n\t\t}),\n\t\t{ texture, mipLevel: 0 },\n\t\t{ width, height, depthOrArrayLayers: 1 }\n\t);\n\n\tif (!binding.generateMipmaps || mipLevelCount <= 1) {\n\t\treturn;\n\t}\n\n\tlet previousSource: CanvasImageSource = source;\n\tlet previousWidth = width;\n\tlet previousHeight = height;\n\n\tfor (let level = 1; level < mipLevelCount; level += 1) {\n\t\tconst nextWidth = Math.max(1, Math.floor(previousWidth / 2));\n\t\tconst nextHeight = Math.max(1, Math.floor(previousHeight / 2));\n\t\tconst canvas = createMipmapCanvas(nextWidth, nextHeight);\n\t\tconst context = canvas.getContext('2d');\n\t\tif (!context) {\n\t\t\tthrow new Error('Unable to create 2D context for mipmap generation');\n\t\t}\n\n\t\tcontext.drawImage(\n\t\t\tpreviousSource,\n\t\t\t0,\n\t\t\t0,\n\t\t\tpreviousWidth,\n\t\t\tpreviousHeight,\n\t\t\t0,\n\t\t\t0,\n\t\t\tnextWidth,\n\t\t\tnextHeight\n\t\t);\n\n\t\tdevice.queue.copyExternalImageToTexture(\n\t\t\tcreateExternalCopySource(canvas, {\n\t\t\t\tpremultipliedAlpha: binding.premultipliedAlpha\n\t\t\t}),\n\t\t\t{ texture, mipLevel: level },\n\t\t\t{ width: nextWidth, height: nextHeight, depthOrArrayLayers: 1 }\n\t\t);\n\n\t\tpreviousSource = canvas;\n\t\tpreviousWidth = nextWidth;\n\t\tpreviousHeight = nextHeight;\n\t}\n}\n\n/**\n * Creates bind group layout entries for frame/uniform buffers plus texture bindings.\n */\nfunction createBindGroupLayoutEntries(\n\ttextureBindings: RuntimeTextureBinding[]\n): GPUBindGroupLayoutEntry[] {\n\tconst entries: GPUBindGroupLayoutEntry[] = [\n\t\t{\n\t\t\tbinding: FRAME_BINDING,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\tbuffer: { type: 'uniform', minBindingSize: 16 }\n\t\t},\n\t\t{\n\t\t\tbinding: UNIFORM_BINDING,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\tbuffer: { type: 'uniform' }\n\t\t}\n\t];\n\n\tfor (const binding of textureBindings) {\n\t\tentries.push({\n\t\t\tbinding: binding.samplerBinding,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\tsampler: { type: 'filtering' }\n\t\t});\n\n\t\tentries.push({\n\t\t\tbinding: binding.textureBinding,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\ttexture: {\n\t\t\t\tsampleType: 'float',\n\t\t\t\tviewDimension: '2d',\n\t\t\t\tmultisampled: false\n\t\t\t}\n\t\t});\n\t}\n\n\treturn entries;\n}\n\n/**\n * Maximum gap (in floats) between two dirty ranges that triggers merge.\n *\n * Set to 4 (16 bytes) which covers one vec4f alignment slot.\n */\nconst DIRTY_RANGE_MERGE_GAP = 4;\n\n/**\n * Computes dirty float ranges between two uniform snapshots.\n *\n * Adjacent dirty ranges separated by a gap smaller than or equal to\n * {@link DIRTY_RANGE_MERGE_GAP} are merged to reduce `writeBuffer` calls.\n */\nexport function findDirtyFloatRanges(\n\tprevious: Float32Array,\n\tnext: Float32Array,\n\tmergeGapThreshold = DIRTY_RANGE_MERGE_GAP\n): Array<{ start: number; count: number }> {\n\tconst ranges: Array<{ start: number; count: number }> = [];\n\tlet start = -1;\n\n\tfor (let index = 0; index < next.length; index += 1) {\n\t\tif (previous[index] !== next[index]) {\n\t\t\tif (start === -1) {\n\t\t\t\tstart = index;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (start !== -1) {\n\t\t\tranges.push({ start, count: index - start });\n\t\t\tstart = -1;\n\t\t}\n\t}\n\n\tif (start !== -1) {\n\t\tranges.push({ start, count: next.length - start });\n\t}\n\n\tif (ranges.length <= 1) {\n\t\treturn ranges;\n\t}\n\n\tconst merged: Array<{ start: number; count: number }> = [ranges[0]!];\n\tfor (let index = 1; index < ranges.length; index += 1) {\n\t\tconst prev = merged[merged.length - 1]!;\n\t\tconst curr = ranges[index]!;\n\t\tconst gap = curr.start - (prev.start + prev.count);\n\n\t\tif (gap <= mergeGapThreshold) {\n\t\t\tprev.count = curr.start + curr.count - prev.start;\n\t\t} else {\n\t\t\tmerged.push(curr);\n\t\t}\n\t}\n\n\treturn merged;\n}\n\n/**\n * Determines whether shader output should perform linear-to-sRGB conversion.\n */\nfunction shouldConvertLinearToSrgb(\n\toutputColorSpace: 'srgb' | 'linear',\n\tcanvasFormat: GPUTextureFormat\n): boolean {\n\tif (outputColorSpace !== 'srgb') {\n\t\treturn false;\n\t}\n\n\treturn !canvasFormat.endsWith('-srgb');\n}\n\n/**\n * WGSL shader used to blit an offscreen texture to the canvas.\n */\nfunction createFullscreenBlitShader(): string {\n\treturn `\nstruct MotionGPUVertexOut {\n\t@builtin(position) position: vec4f,\n\t@location(0) uv: vec2f,\n};\n\n@group(0) @binding(0) var motiongpuBlitSampler: sampler;\n@group(0) @binding(1) var motiongpuBlitTexture: texture_2d<f32>;\n\n@vertex\nfn motiongpuBlitVertex(@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@fragment\nfn motiongpuBlitFragment(in: MotionGPUVertexOut) -> @location(0) vec4f {\n\treturn textureSample(motiongpuBlitTexture, motiongpuBlitSampler, in.uv);\n}\n`;\n}\n\n/**\n * Allocates a render target texture with usage flags suitable for passes/blits.\n */\nfunction createRenderTexture(\n\tdevice: GPUDevice,\n\twidth: number,\n\theight: number,\n\tformat: GPUTextureFormat\n): RuntimeRenderTarget {\n\tconst texture = device.createTexture({\n\t\tsize: { width, height, depthOrArrayLayers: 1 },\n\t\tformat,\n\t\tusage:\n\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\tGPUTextureUsage.RENDER_ATTACHMENT |\n\t\t\tGPUTextureUsage.COPY_DST |\n\t\t\tGPUTextureUsage.COPY_SRC\n\t});\n\n\treturn {\n\t\ttexture,\n\t\tview: texture.createView(),\n\t\twidth,\n\t\theight,\n\t\tformat\n\t};\n}\n\n/**\n * Destroys a render target texture if present.\n */\nfunction destroyRenderTexture(target: RuntimeRenderTarget | null): void {\n\ttarget?.texture.destroy();\n}\n\n/**\n * Creates the WebGPU renderer used by `FragCanvas`.\n *\n * @param options - Renderer creation options resolved from material/context state.\n * @returns Renderer instance with `render` and `destroy`.\n * @throws {Error} On WebGPU unavailability, shader compilation issues, or runtime setup failures.\n */\nexport async function createRenderer(options: RendererOptions): Promise<Renderer> {\n\tif (!navigator.gpu) {\n\t\tthrow new Error('WebGPU is not available in this browser');\n\t}\n\n\tconst context = options.canvas.getContext('webgpu') as GPUCanvasContext | null;\n\tif (!context) {\n\t\tthrow new Error('Canvas does not support webgpu context');\n\t}\n\n\tconst format = navigator.gpu.getPreferredCanvasFormat();\n\tconst adapter = await navigator.gpu.requestAdapter(options.adapterOptions);\n\tif (!adapter) {\n\t\tthrow new Error('Unable to acquire WebGPU adapter');\n\t}\n\n\tconst device = await adapter.requestDevice(options.deviceDescriptor);\n\tlet isDestroyed = false;\n\tlet deviceLostMessage: string | null = null;\n\tlet uncapturedErrorMessage: string | null = null;\n\tconst initializationCleanups: Array<() => void> = [];\n\tlet acceptInitializationCleanups = true;\n\n\tconst registerInitializationCleanup = (cleanup: () => void): void => {\n\t\tif (!acceptInitializationCleanups) {\n\t\t\treturn;\n\t\t}\n\t\toptions.__onInitializationCleanupRegistered?.();\n\t\tinitializationCleanups.push(cleanup);\n\t};\n\n\tconst runInitializationCleanups = (): void => {\n\t\tfor (let index = initializationCleanups.length - 1; index >= 0; index -= 1) {\n\t\t\ttry {\n\t\t\t\tinitializationCleanups[index]?.();\n\t\t\t} catch {\n\t\t\t\t// Best-effort cleanup on failed renderer initialization.\n\t\t\t}\n\t\t}\n\t\tinitializationCleanups.length = 0;\n\t};\n\n\tvoid device.lost.then((info) => {\n\t\tif (isDestroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst reason = info.reason ? ` (${info.reason})` : '';\n\t\tconst details = info.message?.trim();\n\t\tdeviceLostMessage = details\n\t\t\t? `WebGPU device lost: ${details}${reason}`\n\t\t\t: `WebGPU device lost${reason}`;\n\t});\n\n\tconst handleUncapturedError = (event: GPUUncapturedErrorEvent): void => {\n\t\tif (isDestroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst message =\n\t\t\tevent.error instanceof Error\n\t\t\t\t? event.error.message\n\t\t\t\t: String((event.error as { message?: string })?.message ?? event.error);\n\t\tuncapturedErrorMessage = `WebGPU uncaptured error: ${message}`;\n\t};\n\n\tdevice.addEventListener('uncapturederror', handleUncapturedError);\n\ttry {\n\t\tconst runtimeContext = buildShaderCompilationRuntimeContext(options);\n\t\tconst convertLinearToSrgb = shouldConvertLinearToSrgb(options.outputColorSpace, format);\n\t\tconst builtShader = buildShaderSourceWithMap(\n\t\t\toptions.fragmentWgsl,\n\t\t\toptions.uniformLayout,\n\t\t\toptions.textureKeys,\n\t\t\t{\n\t\t\t\tconvertLinearToSrgb,\n\t\t\t\tfragmentLineMap: options.fragmentLineMap,\n\t\t\t\t...(options.storageBufferKeys !== undefined\n\t\t\t\t\t? { storageBufferKeys: options.storageBufferKeys }\n\t\t\t\t\t: {}),\n\t\t\t\t...(options.storageBufferDefinitions !== undefined\n\t\t\t\t\t? { storageBufferDefinitions: options.storageBufferDefinitions }\n\t\t\t\t\t: {})\n\t\t\t}\n\t\t);\n\t\tconst shaderModule = device.createShaderModule({ code: builtShader.code });\n\t\tawait assertCompilation(shaderModule, {\n\t\t\tlineMap: builtShader.lineMap,\n\t\t\tfragmentSource: options.fragmentSource,\n\t\t\tincludeSources: options.includeSources,\n\t\t\t...(options.defineBlockSource !== undefined\n\t\t\t\t? { defineBlockSource: options.defineBlockSource }\n\t\t\t\t: {}),\n\t\t\tmaterialSource: options.materialSource ?? null,\n\t\t\truntimeContext\n\t\t});\n\n\t\tconst normalizedTextureDefinitions = normalizeTextureDefinitions(\n\t\t\toptions.textureDefinitions,\n\t\t\toptions.textureKeys\n\t\t);\n\t\tconst storageBufferKeys = options.storageBufferKeys ?? [];\n\t\tconst storageBufferDefinitions = options.storageBufferDefinitions ?? {};\n\t\tconst storageTextureKeys = options.storageTextureKeys ?? [];\n\t\tconst storageTextureKeySet = new Set(storageTextureKeys);\n\t\tconst textureBindings = options.textureKeys.map((key, index): RuntimeTextureBinding => {\n\t\t\tconst config = normalizedTextureDefinitions[key];\n\t\t\tif (!config) {\n\t\t\t\tthrow new Error(`Missing texture definition for \"${key}\"`);\n\t\t\t}\n\n\t\t\tconst { samplerBinding, textureBinding } = getTextureBindings(index);\n\t\t\tconst sampler = device.createSampler({\n\t\t\t\tmagFilter: config.filter,\n\t\t\t\tminFilter: config.filter,\n\t\t\t\tmipmapFilter: config.generateMipmaps ? config.filter : 'nearest',\n\t\t\t\taddressModeU: config.addressModeU,\n\t\t\t\taddressModeV: config.addressModeV,\n\t\t\t\tmaxAnisotropy: config.filter === 'linear' ? config.anisotropy : 1\n\t\t\t});\n\t\t\t// Storage textures use a safe fallback format — the fallback is never\n\t\t\t// sampled because storage textures are eagerly allocated with their\n\t\t\t// real format/dimensions. Non-storage textures use their own format.\n\t\t\tconst fallbackFormat = config.storage ? 'rgba8unorm' : config.format;\n\t\t\tconst fallbackTexture = createFallbackTexture(device, fallbackFormat);\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\tfallbackTexture.destroy();\n\t\t\t});\n\t\t\tconst fallbackView = fallbackTexture.createView();\n\n\t\t\tconst runtimeBinding: RuntimeTextureBinding = {\n\t\t\t\tkey,\n\t\t\t\tsamplerBinding,\n\t\t\t\ttextureBinding,\n\t\t\t\tsampler,\n\t\t\t\tfallbackTexture,\n\t\t\t\tfallbackView,\n\t\t\t\ttexture: null,\n\t\t\t\tview: fallbackView,\n\t\t\t\tsource: null,\n\t\t\t\twidth: undefined,\n\t\t\t\theight: undefined,\n\t\t\t\tmipLevelCount: 1,\n\t\t\t\tformat: config.format,\n\t\t\t\tcolorSpace: config.colorSpace,\n\t\t\t\tdefaultColorSpace: config.colorSpace,\n\t\t\t\tflipY: config.flipY,\n\t\t\t\tdefaultFlipY: config.flipY,\n\t\t\t\tgenerateMipmaps: config.generateMipmaps,\n\t\t\t\tdefaultGenerateMipmaps: config.generateMipmaps,\n\t\t\t\tpremultipliedAlpha: config.premultipliedAlpha,\n\t\t\t\tdefaultPremultipliedAlpha: config.premultipliedAlpha,\n\t\t\t\tupdate: config.update ?? 'once',\n\t\t\t\tlastToken: null\n\t\t\t};\n\n\t\t\tif (config.update !== undefined) {\n\t\t\t\truntimeBinding.defaultUpdate = config.update;\n\t\t\t}\n\n\t\t\t// Storage textures: eagerly create GPU texture with explicit dimensions\n\t\t\tif (config.storage && config.width && config.height) {\n\t\t\t\tconst storageUsage =\n\t\t\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\t\t\tGPUTextureUsage.STORAGE_BINDING |\n\t\t\t\t\tGPUTextureUsage.COPY_DST;\n\t\t\t\tconst storageTexture = device.createTexture({\n\t\t\t\t\tsize: { width: config.width, height: config.height, depthOrArrayLayers: 1 },\n\t\t\t\t\tformat: config.format,\n\t\t\t\t\tusage: storageUsage\n\t\t\t\t});\n\t\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\t\tstorageTexture.destroy();\n\t\t\t\t});\n\t\t\t\truntimeBinding.texture = storageTexture as unknown as GPUTexture;\n\t\t\t\truntimeBinding.view = storageTexture.createView();\n\t\t\t\truntimeBinding.width = config.width;\n\t\t\t\truntimeBinding.height = config.height;\n\t\t\t}\n\n\t\t\treturn runtimeBinding;\n\t\t});\n\n\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: createBindGroupLayoutEntries(textureBindings)\n\t\t});\n\t\tconst fragmentStorageBindGroupLayout =\n\t\t\tstorageBufferKeys.length > 0\n\t\t\t\t? device.createBindGroupLayout({\n\t\t\t\t\t\tentries: storageBufferKeys.map((_, index) => ({\n\t\t\t\t\t\t\tbinding: index,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\t\t\t\tbuffer: { type: 'read-only-storage' as GPUBufferBindingType }\n\t\t\t\t\t\t}))\n\t\t\t\t\t})\n\t\t\t\t: null;\n\t\tconst pipelineLayout = device.createPipelineLayout({\n\t\t\tbindGroupLayouts: fragmentStorageBindGroupLayout\n\t\t\t\t? [bindGroupLayout, fragmentStorageBindGroupLayout]\n\t\t\t\t: [bindGroupLayout]\n\t\t});\n\n\t\tconst pipeline = device.createRenderPipeline({\n\t\t\tlayout: pipelineLayout,\n\t\t\tvertex: {\n\t\t\t\tmodule: shaderModule,\n\t\t\t\tentryPoint: 'motiongpuVertex'\n\t\t\t},\n\t\t\tfragment: {\n\t\t\t\tmodule: shaderModule,\n\t\t\t\tentryPoint: 'motiongpuFragment',\n\t\t\t\ttargets: [{ format }]\n\t\t\t},\n\t\t\tprimitive: {\n\t\t\t\ttopology: 'triangle-list'\n\t\t\t}\n\t\t});\n\n\t\tconst blitShaderModule = device.createShaderModule({\n\t\t\tcode: createFullscreenBlitShader()\n\t\t});\n\t\tawait assertCompilation(blitShaderModule);\n\n\t\tconst blitBindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: [\n\t\t\t\t{\n\t\t\t\t\tbinding: 0,\n\t\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\t\tsampler: { type: 'filtering' }\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 1,\n\t\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\t\ttexture: {\n\t\t\t\t\t\tsampleType: 'float',\n\t\t\t\t\t\tviewDimension: '2d',\n\t\t\t\t\t\tmultisampled: false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t});\n\t\tconst blitPipelineLayout = device.createPipelineLayout({\n\t\t\tbindGroupLayouts: [blitBindGroupLayout]\n\t\t});\n\t\tconst blitPipeline = device.createRenderPipeline({\n\t\t\tlayout: blitPipelineLayout,\n\t\t\tvertex: { module: blitShaderModule, entryPoint: 'motiongpuBlitVertex' },\n\t\t\tfragment: {\n\t\t\t\tmodule: blitShaderModule,\n\t\t\t\tentryPoint: 'motiongpuBlitFragment',\n\t\t\t\ttargets: [{ format }]\n\t\t\t},\n\t\t\tprimitive: {\n\t\t\t\ttopology: 'triangle-list'\n\t\t\t}\n\t\t});\n\t\tconst blitSampler = device.createSampler({\n\t\t\tmagFilter: 'linear',\n\t\t\tminFilter: 'linear',\n\t\t\taddressModeU: 'clamp-to-edge',\n\t\t\taddressModeV: 'clamp-to-edge'\n\t\t});\n\t\tlet blitBindGroupByView = new WeakMap<GPUTextureView, GPUBindGroup>();\n\n\t\t// ── Storage buffer allocation ────────────────────────────────────────\n\t\tconst storageBufferMap = new Map<string, GPUBuffer>();\n\t\tconst pingPongTexturePairs = new Map<string, PingPongTexturePair>();\n\n\t\tfor (const key of storageBufferKeys) {\n\t\t\tconst definition = storageBufferDefinitions[key];\n\t\t\tif (!definition) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst normalized = normalizeStorageBufferDefinition(definition);\n\t\t\tconst buffer = device.createBuffer({\n\t\t\t\tsize: normalized.size,\n\t\t\t\tusage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\tbuffer.destroy();\n\t\t\t});\n\t\t\tif (definition.initialData) {\n\t\t\t\tconst data = definition.initialData;\n\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\tbuffer,\n\t\t\t\t\t0,\n\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\tdata.byteLength\n\t\t\t\t);\n\t\t\t}\n\t\t\tstorageBufferMap.set(key, buffer);\n\t\t}\n\t\tconst fragmentStorageBindGroup =\n\t\t\tfragmentStorageBindGroupLayout && storageBufferKeys.length > 0\n\t\t\t\t? device.createBindGroup({\n\t\t\t\t\t\tlayout: fragmentStorageBindGroupLayout,\n\t\t\t\t\t\tentries: storageBufferKeys.map((key, index) => {\n\t\t\t\t\t\t\tconst buffer = storageBufferMap.get(key);\n\t\t\t\t\t\t\tif (!buffer) {\n\t\t\t\t\t\t\t\tthrow new Error(`Storage buffer \"${key}\" not allocated.`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn { binding: index, resource: { buffer } };\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t: null;\n\n\t\tconst ensurePingPongTexturePair = (target: string): PingPongTexturePair => {\n\t\t\tconst existing = pingPongTexturePairs.get(target);\n\t\t\tif (existing) {\n\t\t\t\treturn existing;\n\t\t\t}\n\n\t\t\tconst config = normalizedTextureDefinitions[target];\n\t\t\tif (!config || !config.storage) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`PingPongComputePass target \"${target}\" must reference a texture declared with storage:true.`\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!config.width || !config.height) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`PingPongComputePass target \"${target}\" requires explicit texture width and height.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst usage =\n\t\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\t\tGPUTextureUsage.STORAGE_BINDING |\n\t\t\t\tGPUTextureUsage.COPY_DST;\n\t\t\tconst textureA = device.createTexture({\n\t\t\t\tsize: { width: config.width, height: config.height, depthOrArrayLayers: 1 },\n\t\t\t\tformat: config.format,\n\t\t\t\tusage\n\t\t\t});\n\t\t\tconst textureB = device.createTexture({\n\t\t\t\tsize: { width: config.width, height: config.height, depthOrArrayLayers: 1 },\n\t\t\t\tformat: config.format,\n\t\t\t\tusage\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\ttextureA.destroy();\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\ttextureB.destroy();\n\t\t\t});\n\n\t\t\tconst sampleScalarType = storageTextureSampleScalarType(config.format);\n\t\t\tconst sampleType = toGpuTextureSampleType(sampleScalarType);\n\t\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\t\tentries: [\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: 0,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\ttexture: {\n\t\t\t\t\t\t\tsampleType,\n\t\t\t\t\t\t\tviewDimension: '2d',\n\t\t\t\t\t\t\tmultisampled: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: 1,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\t\tformat: config.format as GPUTextureFormat,\n\t\t\t\t\t\t\tviewDimension: '2d'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tconst pair: PingPongTexturePair = {\n\t\t\t\ttarget,\n\t\t\t\tformat: config.format as GPUTextureFormat,\n\t\t\t\twidth: config.width,\n\t\t\t\theight: config.height,\n\t\t\t\ttextureA,\n\t\t\t\tviewA: textureA.createView(),\n\t\t\t\ttextureB,\n\t\t\t\tviewB: textureB.createView(),\n\t\t\t\tbindGroupLayout\n\t\t\t};\n\t\t\tpingPongTexturePairs.set(target, pair);\n\t\t\treturn pair;\n\t\t};\n\n\t\t// ── Compute pipeline setup ──────────────────────────────────────────\n\t\tinterface ComputePipelineEntry {\n\t\t\tpipeline: GPUComputePipeline;\n\t\t\tbindGroup: GPUBindGroup;\n\t\t\tworkgroupSize: [number, number, number];\n\t\t\tcomputeSource: string;\n\t\t}\n\t\tconst computePipelineCache = new Map<string, ComputePipelineEntry>();\n\n\t\tconst buildComputePipelineEntry = (buildOptions: {\n\t\t\tcomputeSource: string;\n\t\t\tpingPongTarget?: string;\n\t\t\tpingPongFormat?: GPUTextureFormat;\n\t\t}): ComputePipelineEntry => {\n\t\t\tconst cacheKey =\n\t\t\t\tbuildOptions.pingPongTarget && buildOptions.pingPongFormat\n\t\t\t\t\t? `pingpong:${buildOptions.pingPongTarget}:${buildOptions.pingPongFormat}:${buildOptions.computeSource}`\n\t\t\t\t\t: `compute:${buildOptions.computeSource}`;\n\t\t\tconst cached = computePipelineCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tconst storageBufferDefs: Record<\n\t\t\t\tstring,\n\t\t\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t\t\t> = {};\n\t\t\tfor (const key of storageBufferKeys) {\n\t\t\t\tconst def = storageBufferDefinitions[key];\n\t\t\t\tif (def) {\n\t\t\t\t\tconst norm = normalizeStorageBufferDefinition(def);\n\t\t\t\t\tstorageBufferDefs[key] = { type: norm.type, access: norm.access };\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst storageTextureDefs: Record<string, { format: GPUTextureFormat }> = {};\n\t\t\tfor (const key of storageTextureKeys) {\n\t\t\t\tconst texDef = options.textureDefinitions[key];\n\t\t\t\tif (texDef?.format) {\n\t\t\t\t\tstorageTextureDefs[key] = { format: texDef.format };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst isPingPongPipeline = Boolean(\n\t\t\t\tbuildOptions.pingPongTarget && buildOptions.pingPongFormat\n\t\t\t);\n\t\t\tconst shaderCode = isPingPongPipeline\n\t\t\t\t? buildPingPongComputeShaderSource({\n\t\t\t\t\t\tcompute: buildOptions.computeSource,\n\t\t\t\t\t\tuniformLayout: options.uniformLayout,\n\t\t\t\t\t\tstorageBufferKeys,\n\t\t\t\t\t\tstorageBufferDefinitions: storageBufferDefs,\n\t\t\t\t\t\ttarget: buildOptions.pingPongTarget!,\n\t\t\t\t\t\ttargetFormat: buildOptions.pingPongFormat!\n\t\t\t\t\t})\n\t\t\t\t: buildComputeShaderSource({\n\t\t\t\t\t\tcompute: buildOptions.computeSource,\n\t\t\t\t\t\tuniformLayout: options.uniformLayout,\n\t\t\t\t\t\tstorageBufferKeys,\n\t\t\t\t\t\tstorageBufferDefinitions: storageBufferDefs,\n\t\t\t\t\t\tstorageTextureKeys,\n\t\t\t\t\t\tstorageTextureDefinitions: storageTextureDefs\n\t\t\t\t\t});\n\n\t\t\tconst computeShaderModule = device.createShaderModule({ code: shaderCode });\n\t\t\tconst workgroupSize = extractWorkgroupSize(buildOptions.computeSource);\n\n\t\t\t// Compute bind group layout: group(0)=uniforms, group(1)=storage buffers, group(2)=storage textures\n\t\t\tconst computeUniformBGL = device.createBindGroupLayout({\n\t\t\t\tentries: [\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: FRAME_BINDING,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\tbuffer: { type: 'uniform', minBindingSize: 16 }\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: UNIFORM_BINDING,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\tbuffer: { type: 'uniform' }\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tconst storageBGLEntries: GPUBindGroupLayoutEntry[] = storageBufferKeys.map((key, index) => {\n\t\t\t\tconst def = storageBufferDefinitions[key];\n\t\t\t\tconst access = def?.access ?? 'read-write';\n\t\t\t\tconst bufferType: GPUBufferBindingType =\n\t\t\t\t\taccess === 'read' ? 'read-only-storage' : 'storage';\n\t\t\t\treturn {\n\t\t\t\t\tbinding: index,\n\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\tbuffer: { type: bufferType }\n\t\t\t\t};\n\t\t\t});\n\t\t\tconst storageBGL =\n\t\t\t\tstorageBGLEntries.length > 0\n\t\t\t\t\t? device.createBindGroupLayout({ entries: storageBGLEntries })\n\t\t\t\t\t: null;\n\n\t\t\tconst storageTextureBGLEntries: GPUBindGroupLayoutEntry[] = isPingPongPipeline\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbinding: 0,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\t\ttexture: {\n\t\t\t\t\t\t\t\tsampleType: toGpuTextureSampleType(\n\t\t\t\t\t\t\t\t\tstorageTextureSampleScalarType(buildOptions.pingPongFormat!)\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tviewDimension: '2d',\n\t\t\t\t\t\t\t\tmultisampled: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbinding: 1,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\t\t\tformat: buildOptions.pingPongFormat!,\n\t\t\t\t\t\t\t\tviewDimension: '2d'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t: storageTextureKeys.map((key, index) => {\n\t\t\t\t\t\tconst texDef = options.textureDefinitions[key];\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tbinding: index,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\t\t\tformat: (texDef?.format ?? 'rgba8unorm') as GPUTextureFormat,\n\t\t\t\t\t\t\t\tviewDimension: '2d'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t});\n\t\t\tconst storageTextureBGL =\n\t\t\t\tstorageTextureBGLEntries.length > 0\n\t\t\t\t\t? device.createBindGroupLayout({ entries: storageTextureBGLEntries })\n\t\t\t\t\t: null;\n\n\t\t\t// Bind group layout indices must match shader @group() indices:\n\t\t\t// group(0) = uniforms, group(1) = storage buffers, group(2) = storage textures.\n\t\t\t// When a group is unused, insert an empty placeholder to keep indices aligned.\n\t\t\tconst bindGroupLayouts: GPUBindGroupLayout[] = [computeUniformBGL];\n\t\t\tif (storageBGL || storageTextureBGL) {\n\t\t\t\tbindGroupLayouts.push(storageBGL ?? device.createBindGroupLayout({ entries: [] }));\n\t\t\t}\n\t\t\tif (storageTextureBGL) {\n\t\t\t\tbindGroupLayouts.push(storageTextureBGL);\n\t\t\t}\n\n\t\t\tconst computePipelineLayout = device.createPipelineLayout({ bindGroupLayouts });\n\t\t\tconst pipeline = device.createComputePipeline({\n\t\t\t\tlayout: computePipelineLayout,\n\t\t\t\tcompute: {\n\t\t\t\t\tmodule: computeShaderModule,\n\t\t\t\t\tentryPoint: 'compute'\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Build uniform bind group for compute (group 0)\n\t\t\tconst computeUniformBindGroup = device.createBindGroup({\n\t\t\t\tlayout: computeUniformBGL,\n\t\t\t\tentries: [\n\t\t\t\t\t{ binding: FRAME_BINDING, resource: { buffer: frameBuffer } },\n\t\t\t\t\t{ binding: UNIFORM_BINDING, resource: { buffer: uniformBuffer } }\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tconst entry: ComputePipelineEntry = {\n\t\t\t\tpipeline,\n\t\t\t\tbindGroup: computeUniformBindGroup,\n\t\t\t\tworkgroupSize,\n\t\t\t\tcomputeSource: buildOptions.computeSource\n\t\t\t};\n\t\t\tcomputePipelineCache.set(cacheKey, entry);\n\t\t\treturn entry;\n\t\t};\n\n\t\t// Helper to get the storage bind group for dispatch\n\t\tconst getComputeStorageBindGroup = (): GPUBindGroup | null => {\n\t\t\tif (storageBufferKeys.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\t// Rebuild bind group with current storage buffers\n\t\t\tconst storageBGLEntries: GPUBindGroupLayoutEntry[] = storageBufferKeys.map((key, index) => {\n\t\t\t\tconst def = storageBufferDefinitions[key];\n\t\t\t\tconst access = def?.access ?? 'read-write';\n\t\t\t\tconst bufferType: GPUBufferBindingType =\n\t\t\t\t\taccess === 'read' ? 'read-only-storage' : 'storage';\n\t\t\t\treturn {\n\t\t\t\t\tbinding: index,\n\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\tbuffer: { type: bufferType }\n\t\t\t\t};\n\t\t\t});\n\t\t\tconst storageBGL = device.createBindGroupLayout({ entries: storageBGLEntries });\n\t\t\tconst storageEntries: GPUBindGroupEntry[] = storageBufferKeys.map((key, index) => {\n\t\t\t\tconst buffer = storageBufferMap.get(key);\n\t\t\t\tif (!buffer) {\n\t\t\t\t\tthrow new Error(`Storage buffer \"${key}\" not allocated.`);\n\t\t\t\t}\n\t\t\t\treturn { binding: index, resource: { buffer } };\n\t\t\t});\n\t\t\treturn device.createBindGroup({\n\t\t\t\tlayout: storageBGL,\n\t\t\t\tentries: storageEntries\n\t\t\t});\n\t\t};\n\n\t\t// Helper to get the storage texture bind group for compute dispatch (group 2)\n\t\tconst getComputeStorageTextureBindGroup = (): GPUBindGroup | null => {\n\t\t\tif (storageTextureKeys.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst entries: GPUBindGroupLayoutEntry[] = storageTextureKeys.map((key, index) => {\n\t\t\t\tconst texDef = options.textureDefinitions[key];\n\t\t\t\treturn {\n\t\t\t\t\tbinding: index,\n\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\tformat: (texDef?.format ?? 'rgba8unorm') as GPUTextureFormat,\n\t\t\t\t\t\tviewDimension: '2d' as GPUTextureViewDimension\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t});\n\t\t\tconst bgl = device.createBindGroupLayout({ entries });\n\n\t\t\tconst bgEntries: GPUBindGroupEntry[] = storageTextureKeys.map((key, index) => {\n\t\t\t\tconst binding = textureBindings.find((b) => b.key === key);\n\t\t\t\tif (!binding || !binding.texture) {\n\t\t\t\t\tthrow new Error(`Storage texture \"${key}\" not allocated.`);\n\t\t\t\t}\n\t\t\t\treturn { binding: index, resource: binding.view };\n\t\t\t});\n\n\t\t\treturn device.createBindGroup({ layout: bgl, entries: bgEntries });\n\t\t};\n\n\t\t// Helper to get ping-pong storage texture bind group for compute dispatch (group 2)\n\t\tconst getPingPongStorageTextureBindGroup = (\n\t\t\ttarget: string,\n\t\t\treadFromA: boolean\n\t\t): GPUBindGroup => {\n\t\t\tconst pair = ensurePingPongTexturePair(target);\n\t\t\tconst readView = readFromA ? pair.viewA : pair.viewB;\n\t\t\tconst writeView = readFromA ? pair.viewB : pair.viewA;\n\t\t\treturn device.createBindGroup({\n\t\t\t\tlayout: pair.bindGroupLayout,\n\t\t\t\tentries: [\n\t\t\t\t\t{ binding: 0, resource: readView },\n\t\t\t\t\t{ binding: 1, resource: writeView }\n\t\t\t\t]\n\t\t\t});\n\t\t};\n\n\t\tconst frameBuffer = device.createBuffer({\n\t\t\tsize: 16,\n\t\t\tusage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n\t\t});\n\t\tregisterInitializationCleanup(() => {\n\t\t\tframeBuffer.destroy();\n\t\t});\n\n\t\tconst uniformBuffer = device.createBuffer({\n\t\t\tsize: options.uniformLayout.byteLength,\n\t\t\tusage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n\t\t});\n\t\tregisterInitializationCleanup(() => {\n\t\t\tuniformBuffer.destroy();\n\t\t});\n\t\tconst frameScratch = new Float32Array(4);\n\t\tconst uniformScratch = new Float32Array(options.uniformLayout.byteLength / 4);\n\t\tconst uniformPrevious = new Float32Array(options.uniformLayout.byteLength / 4);\n\t\tlet hasUniformSnapshot = false;\n\n\t\t/**\n\t\t * Rebuilds bind group using current texture views.\n\t\t */\n\t\tconst createBindGroup = (): GPUBindGroup => {\n\t\t\tconst entries: GPUBindGroupEntry[] = [\n\t\t\t\t{ binding: FRAME_BINDING, resource: { buffer: frameBuffer } },\n\t\t\t\t{ binding: UNIFORM_BINDING, resource: { buffer: uniformBuffer } }\n\t\t\t];\n\n\t\t\tfor (const binding of textureBindings) {\n\t\t\t\tentries.push({\n\t\t\t\t\tbinding: binding.samplerBinding,\n\t\t\t\t\tresource: binding.sampler\n\t\t\t\t});\n\t\t\t\tentries.push({\n\t\t\t\t\tbinding: binding.textureBinding,\n\t\t\t\t\tresource: binding.view\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn device.createBindGroup({\n\t\t\t\tlayout: bindGroupLayout,\n\t\t\t\tentries\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Synchronizes one runtime texture binding with incoming texture value.\n\t\t *\n\t\t * @returns `true` when bind group must be rebuilt.\n\t\t */\n\t\tconst updateTextureBinding = (\n\t\t\tbinding: RuntimeTextureBinding,\n\t\t\tvalue: TextureValue,\n\t\t\trenderMode: RenderMode\n\t\t): boolean => {\n\t\t\tconst nextData = toTextureData(value);\n\n\t\t\tif (!nextData) {\n\t\t\t\tif (binding.source === null && binding.texture === null) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tbinding.texture?.destroy();\n\t\t\t\tbinding.texture = null;\n\t\t\t\tbinding.view = binding.fallbackView;\n\t\t\t\tbinding.source = null;\n\t\t\t\tbinding.width = undefined;\n\t\t\t\tbinding.height = undefined;\n\t\t\t\tbinding.lastToken = null;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst source = nextData.source;\n\t\t\tconst colorSpace = nextData.colorSpace ?? binding.defaultColorSpace;\n\t\t\tconst format = colorSpace === 'linear' ? 'rgba8unorm' : 'rgba8unorm-srgb';\n\t\t\tconst flipY = nextData.flipY ?? binding.defaultFlipY;\n\t\t\tconst premultipliedAlpha = nextData.premultipliedAlpha ?? binding.defaultPremultipliedAlpha;\n\t\t\tconst generateMipmaps = nextData.generateMipmaps ?? binding.defaultGenerateMipmaps;\n\t\t\tconst update = resolveTextureUpdateMode({\n\t\t\t\tsource,\n\t\t\t\t...(nextData.update !== undefined ? { override: nextData.update } : {}),\n\t\t\t\t...(binding.defaultUpdate !== undefined ? { defaultMode: binding.defaultUpdate } : {})\n\t\t\t});\n\t\t\tconst { width, height } = resolveTextureSize(nextData);\n\t\t\tconst mipLevelCount = generateMipmaps ? getTextureMipLevelCount(width, height) : 1;\n\t\t\tconst sourceChanged = binding.source !== source;\n\t\t\tconst tokenChanged = binding.lastToken !== value;\n\t\t\tconst requiresReallocation =\n\t\t\t\tbinding.texture === null ||\n\t\t\t\tbinding.width !== width ||\n\t\t\t\tbinding.height !== height ||\n\t\t\t\tbinding.mipLevelCount !== mipLevelCount ||\n\t\t\t\tbinding.format !== format;\n\n\t\t\tif (!requiresReallocation) {\n\t\t\t\tconst shouldUpload =\n\t\t\t\t\tsourceChanged ||\n\t\t\t\t\tupdate === 'perFrame' ||\n\t\t\t\t\t(update === 'onInvalidate' && (renderMode !== 'always' || tokenChanged));\n\n\t\t\t\tif (shouldUpload && binding.texture) {\n\t\t\t\t\tbinding.flipY = flipY;\n\t\t\t\t\tbinding.generateMipmaps = generateMipmaps;\n\t\t\t\t\tbinding.premultipliedAlpha = premultipliedAlpha;\n\t\t\t\t\tbinding.colorSpace = colorSpace;\n\t\t\t\t\tuploadTexture(device, binding.texture, binding, source, width, height, mipLevelCount);\n\t\t\t\t}\n\n\t\t\t\tbinding.source = source;\n\t\t\t\tbinding.width = width;\n\t\t\t\tbinding.height = height;\n\t\t\t\tbinding.mipLevelCount = mipLevelCount;\n\t\t\t\tbinding.update = update;\n\t\t\t\tbinding.lastToken = value;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tlet textureUsage =\n\t\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\t\tGPUTextureUsage.COPY_DST |\n\t\t\t\tGPUTextureUsage.RENDER_ATTACHMENT;\n\t\t\tif (storageTextureKeySet.has(binding.key)) {\n\t\t\t\ttextureUsage |= GPUTextureUsage.STORAGE_BINDING;\n\t\t\t}\n\t\t\tconst texture = device.createTexture({\n\t\t\t\tsize: { width, height, depthOrArrayLayers: 1 },\n\t\t\t\tformat,\n\t\t\t\tmipLevelCount,\n\t\t\t\tusage: textureUsage\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\ttexture.destroy();\n\t\t\t});\n\n\t\t\tbinding.flipY = flipY;\n\t\t\tbinding.generateMipmaps = generateMipmaps;\n\t\t\tbinding.premultipliedAlpha = premultipliedAlpha;\n\t\t\tbinding.colorSpace = colorSpace;\n\t\t\tbinding.format = format;\n\t\t\tuploadTexture(device, texture, binding, source, width, height, mipLevelCount);\n\n\t\t\tbinding.texture?.destroy();\n\t\t\tbinding.texture = texture;\n\t\t\tbinding.view = texture.createView();\n\t\t\tbinding.source = source;\n\t\t\tbinding.width = width;\n\t\t\tbinding.height = height;\n\t\t\tbinding.mipLevelCount = mipLevelCount;\n\t\t\tbinding.update = update;\n\t\t\tbinding.lastToken = value;\n\t\t\treturn true;\n\t\t};\n\n\t\tfor (const binding of textureBindings) {\n\t\t\t// Skip storage textures — they are eagerly allocated and not source-driven\n\t\t\tif (storageTextureKeySet.has(binding.key)) continue;\n\t\t\tconst defaultSource = normalizedTextureDefinitions[binding.key]?.source ?? null;\n\t\t\tupdateTextureBinding(binding, defaultSource, 'always');\n\t\t}\n\n\t\tlet bindGroup = createBindGroup();\n\t\tlet sourceSlotTarget: RuntimeRenderTarget | null = null;\n\t\tlet targetSlotTarget: RuntimeRenderTarget | null = null;\n\t\tlet renderTargetSignature = '';\n\t\tlet renderTargetSnapshot: Readonly<Record<string, RenderTarget>> = {};\n\t\tlet renderTargetKeys: string[] = [];\n\t\tlet cachedGraphPlan: RenderGraphPlan | null = null;\n\t\tlet cachedGraphRenderTargetSignature = '';\n\t\tconst cachedGraphClearColor: [number, number, number, number] = [NaN, NaN, NaN, NaN];\n\t\tconst cachedGraphPasses: RenderGraphPassSnapshot[] = [];\n\t\tlet contextConfigured = false;\n\t\tlet configuredWidth = 0;\n\t\tlet configuredHeight = 0;\n\t\tconst runtimeRenderTargets = new Map<string, RuntimeRenderTarget>();\n\t\tconst activePasses: AnyPass[] = [];\n\t\tconst lifecyclePreviousSet = new Set<AnyPass>();\n\t\tconst lifecycleNextSet = new Set<AnyPass>();\n\t\tconst lifecycleUniquePasses: AnyPass[] = [];\n\t\tlet lifecyclePassesRef: AnyPass[] | null = null;\n\t\tlet passWidth = 0;\n\t\tlet passHeight = 0;\n\n\t\t/**\n\t\t * Resolves active render pass list for current frame.\n\t\t */\n\t\tconst resolvePasses = (): AnyPass[] => {\n\t\t\treturn options.getPasses?.() ?? options.passes ?? [];\n\t\t};\n\n\t\t/**\n\t\t * Resolves active render target declarations for current frame.\n\t\t */\n\t\tconst resolveRenderTargets = () => {\n\t\t\treturn options.getRenderTargets?.() ?? options.renderTargets;\n\t\t};\n\n\t\t/**\n\t\t * Checks whether cached render-graph plan can be reused for this frame.\n\t\t */\n\t\tconst isGraphPlanCacheValid = (\n\t\t\tpasses: AnyPass[],\n\t\t\tclearColor: [number, number, number, number]\n\t\t): boolean => {\n\t\t\tif (!cachedGraphPlan) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (cachedGraphRenderTargetSignature !== renderTargetSignature) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tcachedGraphClearColor[0] !== clearColor[0] ||\n\t\t\t\tcachedGraphClearColor[1] !== clearColor[1] ||\n\t\t\t\tcachedGraphClearColor[2] !== clearColor[2] ||\n\t\t\t\tcachedGraphClearColor[3] !== clearColor[3]\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (cachedGraphPasses.length !== passes.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor (let index = 0; index < passes.length; index += 1) {\n\t\t\t\tconst pass = passes[index];\n\t\t\t\tconst rp = pass as Partial<RenderPass>;\n\t\t\t\tconst snapshot = cachedGraphPasses[index];\n\t\t\t\tif (!pass || !snapshot || snapshot.pass !== pass) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tsnapshot.enabled !== pass.enabled ||\n\t\t\t\t\tsnapshot.needsSwap !== rp.needsSwap ||\n\t\t\t\t\tsnapshot.input !== rp.input ||\n\t\t\t\t\tsnapshot.output !== rp.output ||\n\t\t\t\t\tsnapshot.clear !== rp.clear ||\n\t\t\t\t\tsnapshot.preserve !== rp.preserve\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tconst passClearColor = rp.clearColor;\n\t\t\t\tconst hasPassClearColor = passClearColor !== undefined;\n\t\t\t\tif (snapshot.hasClearColor !== hasPassClearColor) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (passClearColor) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tsnapshot.clearColor0 !== passClearColor[0] ||\n\t\t\t\t\t\tsnapshot.clearColor1 !== passClearColor[1] ||\n\t\t\t\t\t\tsnapshot.clearColor2 !== passClearColor[2] ||\n\t\t\t\t\t\tsnapshot.clearColor3 !== passClearColor[3]\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * Updates render-graph cache with current pass set.\n\t\t */\n\t\tconst updateGraphPlanCache = (\n\t\t\tpasses: AnyPass[],\n\t\t\tclearColor: [number, number, number, number],\n\t\t\tgraphPlan: RenderGraphPlan\n\t\t): void => {\n\t\t\tcachedGraphPlan = graphPlan;\n\t\t\tcachedGraphRenderTargetSignature = renderTargetSignature;\n\t\t\tcachedGraphClearColor[0] = clearColor[0];\n\t\t\tcachedGraphClearColor[1] = clearColor[1];\n\t\t\tcachedGraphClearColor[2] = clearColor[2];\n\t\t\tcachedGraphClearColor[3] = clearColor[3];\n\t\t\tcachedGraphPasses.length = passes.length;\n\n\t\t\tlet index = 0;\n\t\t\tfor (const pass of passes) {\n\t\t\t\tconst rp = pass as Partial<RenderPass>;\n\t\t\t\tconst passClearColor = rp.clearColor;\n\t\t\t\tconst hasPassClearColor = passClearColor !== undefined;\n\t\t\t\tconst snapshot = cachedGraphPasses[index];\n\t\t\t\tif (!snapshot) {\n\t\t\t\t\tcachedGraphPasses[index] = {\n\t\t\t\t\t\tpass,\n\t\t\t\t\t\tenabled: pass.enabled,\n\t\t\t\t\t\tneedsSwap: rp.needsSwap,\n\t\t\t\t\t\tinput: rp.input,\n\t\t\t\t\t\toutput: rp.output,\n\t\t\t\t\t\tclear: rp.clear,\n\t\t\t\t\t\tpreserve: rp.preserve,\n\t\t\t\t\t\thasClearColor: hasPassClearColor,\n\t\t\t\t\t\tclearColor0: passClearColor?.[0] ?? 0,\n\t\t\t\t\t\tclearColor1: passClearColor?.[1] ?? 0,\n\t\t\t\t\t\tclearColor2: passClearColor?.[2] ?? 0,\n\t\t\t\t\t\tclearColor3: passClearColor?.[3] ?? 0\n\t\t\t\t\t};\n\t\t\t\t\tindex += 1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tsnapshot.pass = pass;\n\t\t\t\tsnapshot.enabled = pass.enabled;\n\t\t\t\tsnapshot.needsSwap = rp.needsSwap;\n\t\t\t\tsnapshot.input = rp.input;\n\t\t\t\tsnapshot.output = rp.output;\n\t\t\t\tsnapshot.clear = rp.clear;\n\t\t\t\tsnapshot.preserve = rp.preserve;\n\t\t\t\tsnapshot.hasClearColor = hasPassClearColor;\n\t\t\t\tsnapshot.clearColor0 = passClearColor?.[0] ?? 0;\n\t\t\t\tsnapshot.clearColor1 = passClearColor?.[1] ?? 0;\n\t\t\t\tsnapshot.clearColor2 = passClearColor?.[2] ?? 0;\n\t\t\t\tsnapshot.clearColor3 = passClearColor?.[3] ?? 0;\n\t\t\t\tindex += 1;\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Synchronizes pass lifecycle callbacks and resize notifications.\n\t\t */\n\t\tconst syncPassLifecycle = (passes: AnyPass[], width: number, height: number): void => {\n\t\t\tconst resized = passWidth !== width || passHeight !== height;\n\t\t\tif (!resized && lifecyclePassesRef === passes && passes.length === activePasses.length) {\n\t\t\t\tlet isSameOrder = true;\n\t\t\t\tfor (let index = 0; index < passes.length; index += 1) {\n\t\t\t\t\tif (activePasses[index] !== passes[index]) {\n\t\t\t\t\t\tisSameOrder = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isSameOrder) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlifecycleNextSet.clear();\n\t\t\tlifecycleUniquePasses.length = 0;\n\t\t\tfor (const pass of passes) {\n\t\t\t\tif (lifecycleNextSet.has(pass)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlifecycleNextSet.add(pass);\n\t\t\t\tlifecycleUniquePasses.push(pass);\n\t\t\t}\n\t\t\tlifecyclePreviousSet.clear();\n\t\t\tfor (const pass of activePasses) {\n\t\t\t\tlifecyclePreviousSet.add(pass);\n\t\t\t}\n\n\t\t\tfor (const pass of activePasses) {\n\t\t\t\tif (!lifecycleNextSet.has(pass)) {\n\t\t\t\t\tpass.dispose?.();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const pass of lifecycleUniquePasses) {\n\t\t\t\tif (resized || !lifecyclePreviousSet.has(pass)) {\n\t\t\t\t\tpass.setSize?.(width, height);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tactivePasses.length = 0;\n\t\t\tfor (const pass of lifecycleUniquePasses) {\n\t\t\t\tactivePasses.push(pass);\n\t\t\t}\n\t\t\tlifecyclePassesRef = passes;\n\t\t\tpassWidth = width;\n\t\t\tpassHeight = height;\n\t\t};\n\n\t\t/**\n\t\t * Ensures internal ping-pong slot texture matches current canvas size/format.\n\t\t */\n\t\tconst ensureSlotTarget = (\n\t\t\tslot: RenderPassInputSlot,\n\t\t\twidth: number,\n\t\t\theight: number\n\t\t): RuntimeRenderTarget => {\n\t\t\tconst current = slot === 'source' ? sourceSlotTarget : targetSlotTarget;\n\t\t\tif (\n\t\t\t\tcurrent &&\n\t\t\t\tcurrent.width === width &&\n\t\t\t\tcurrent.height === height &&\n\t\t\t\tcurrent.format === format\n\t\t\t) {\n\t\t\t\treturn current;\n\t\t\t}\n\n\t\t\tdestroyRenderTexture(current);\n\t\t\tconst next = createRenderTexture(device, width, height, format);\n\t\t\tif (slot === 'source') {\n\t\t\t\tsourceSlotTarget = next;\n\t\t\t} else {\n\t\t\t\ttargetSlotTarget = next;\n\t\t\t}\n\n\t\t\treturn next;\n\t\t};\n\n\t\t/**\n\t\t * Creates/updates runtime render targets and returns immutable pass snapshot.\n\t\t */\n\t\tconst syncRenderTargets = (\n\t\t\tcanvasWidth: number,\n\t\t\tcanvasHeight: number\n\t\t): Readonly<Record<string, RenderTarget>> => {\n\t\t\tconst resolvedDefinitions = resolveRenderTargetDefinitions(\n\t\t\t\tresolveRenderTargets(),\n\t\t\t\tcanvasWidth,\n\t\t\t\tcanvasHeight,\n\t\t\t\tformat\n\t\t\t);\n\t\t\tconst nextSignature = buildRenderTargetSignature(resolvedDefinitions);\n\n\t\t\tif (nextSignature !== renderTargetSignature) {\n\t\t\t\tconst activeKeys = new Set(resolvedDefinitions.map((definition) => definition.key));\n\n\t\t\t\tfor (const [key, target] of runtimeRenderTargets.entries()) {\n\t\t\t\t\tif (!activeKeys.has(key)) {\n\t\t\t\t\t\ttarget.texture.destroy();\n\t\t\t\t\t\truntimeRenderTargets.delete(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const definition of resolvedDefinitions) {\n\t\t\t\t\tconst current = runtimeRenderTargets.get(definition.key);\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrent &&\n\t\t\t\t\t\tcurrent.width === definition.width &&\n\t\t\t\t\t\tcurrent.height === definition.height &&\n\t\t\t\t\t\tcurrent.format === definition.format\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrent?.texture.destroy();\n\t\t\t\t\truntimeRenderTargets.set(\n\t\t\t\t\t\tdefinition.key,\n\t\t\t\t\t\tcreateRenderTexture(device, definition.width, definition.height, definition.format)\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\trenderTargetSignature = nextSignature;\n\t\t\t\tconst nextSnapshot: Record<string, RenderTarget> = {};\n\t\t\t\tconst nextKeys: string[] = [];\n\t\t\t\tfor (const definition of resolvedDefinitions) {\n\t\t\t\t\tconst target = runtimeRenderTargets.get(definition.key);\n\t\t\t\t\tif (!target) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tnextKeys.push(definition.key);\n\t\t\t\t\tnextSnapshot[definition.key] = {\n\t\t\t\t\t\ttexture: target.texture,\n\t\t\t\t\t\tview: target.view,\n\t\t\t\t\t\twidth: target.width,\n\t\t\t\t\t\theight: target.height,\n\t\t\t\t\t\tformat: target.format\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\trenderTargetSnapshot = nextSnapshot;\n\t\t\t\trenderTargetKeys = nextKeys;\n\t\t\t}\n\n\t\t\treturn renderTargetSnapshot;\n\t\t};\n\n\t\t/**\n\t\t * Blits a texture view to the current canvas texture.\n\t\t */\n\t\tconst blitToCanvas = (\n\t\t\tcommandEncoder: GPUCommandEncoder,\n\t\t\tsourceView: GPUTextureView,\n\t\t\tcanvasView: GPUTextureView,\n\t\t\tclearColor: [number, number, number, number]\n\t\t): void => {\n\t\t\tlet bindGroup = blitBindGroupByView.get(sourceView);\n\t\t\tif (!bindGroup) {\n\t\t\t\tbindGroup = device.createBindGroup({\n\t\t\t\t\tlayout: blitBindGroupLayout,\n\t\t\t\t\tentries: [\n\t\t\t\t\t\t{ binding: 0, resource: blitSampler },\n\t\t\t\t\t\t{ binding: 1, resource: sourceView }\n\t\t\t\t\t]\n\t\t\t\t});\n\t\t\t\tblitBindGroupByView.set(sourceView, bindGroup);\n\t\t\t}\n\n\t\t\tconst pass = commandEncoder.beginRenderPass({\n\t\t\t\tcolorAttachments: [\n\t\t\t\t\t{\n\t\t\t\t\t\tview: canvasView,\n\t\t\t\t\t\tclearValue: {\n\t\t\t\t\t\t\tr: clearColor[0],\n\t\t\t\t\t\t\tg: clearColor[1],\n\t\t\t\t\t\t\tb: clearColor[2],\n\t\t\t\t\t\t\ta: clearColor[3]\n\t\t\t\t\t\t},\n\t\t\t\t\t\tloadOp: 'clear',\n\t\t\t\t\t\tstoreOp: 'store'\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tpass.setPipeline(blitPipeline);\n\t\t\tpass.setBindGroup(0, bindGroup);\n\t\t\tpass.draw(3);\n\t\t\tpass.end();\n\t\t};\n\n\t\t/**\n\t\t * Executes a full frame render.\n\t\t */\n\t\tconst render: Renderer['render'] = ({\n\t\t\ttime,\n\t\t\tdelta,\n\t\t\trenderMode,\n\t\t\tuniforms,\n\t\t\ttextures,\n\t\t\tcanvasSize,\n\t\t\tpendingStorageWrites\n\t\t}) => {\n\t\t\tif (deviceLostMessage) {\n\t\t\t\tthrow new Error(deviceLostMessage);\n\t\t\t}\n\n\t\t\tif (uncapturedErrorMessage) {\n\t\t\t\tconst message = uncapturedErrorMessage;\n\t\t\t\tuncapturedErrorMessage = null;\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\n\t\t\tconst { width, height } = resizeCanvas(options.canvas, options.getDpr(), canvasSize);\n\n\t\t\tif (!contextConfigured || configuredWidth !== width || configuredHeight !== height) {\n\t\t\t\tcontext.configure({\n\t\t\t\t\tdevice,\n\t\t\t\t\tformat,\n\t\t\t\t\talphaMode: 'premultiplied'\n\t\t\t\t});\n\t\t\t\tcontextConfigured = true;\n\t\t\t\tconfiguredWidth = width;\n\t\t\t\tconfiguredHeight = height;\n\t\t\t}\n\n\t\t\tframeScratch[0] = time;\n\t\t\tframeScratch[1] = delta;\n\t\t\tframeScratch[2] = width;\n\t\t\tframeScratch[3] = height;\n\t\t\tdevice.queue.writeBuffer(\n\t\t\t\tframeBuffer,\n\t\t\t\t0,\n\t\t\t\tframeScratch.buffer as ArrayBuffer,\n\t\t\t\tframeScratch.byteOffset,\n\t\t\t\tframeScratch.byteLength\n\t\t\t);\n\n\t\t\tpackUniformsInto(uniforms, options.uniformLayout, uniformScratch);\n\t\t\tif (!hasUniformSnapshot) {\n\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\tuniformBuffer,\n\t\t\t\t\t0,\n\t\t\t\t\tuniformScratch.buffer as ArrayBuffer,\n\t\t\t\t\tuniformScratch.byteOffset,\n\t\t\t\t\tuniformScratch.byteLength\n\t\t\t\t);\n\t\t\t\tuniformPrevious.set(uniformScratch);\n\t\t\t\thasUniformSnapshot = true;\n\t\t\t} else {\n\t\t\t\tconst dirtyRanges = findDirtyFloatRanges(uniformPrevious, uniformScratch);\n\t\t\t\tfor (const range of dirtyRanges) {\n\t\t\t\t\tconst byteOffset = range.start * 4;\n\t\t\t\t\tconst byteLength = range.count * 4;\n\t\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\t\tuniformBuffer,\n\t\t\t\t\t\tbyteOffset,\n\t\t\t\t\t\tuniformScratch.buffer as ArrayBuffer,\n\t\t\t\t\t\tuniformScratch.byteOffset + byteOffset,\n\t\t\t\t\t\tbyteLength\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (dirtyRanges.length > 0) {\n\t\t\t\t\tuniformPrevious.set(uniformScratch);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet bindGroupDirty = false;\n\t\t\tfor (const binding of textureBindings) {\n\t\t\t\t// Storage textures are managed by compute passes, skip source-driven updates\n\t\t\t\tif (storageTextureKeySet.has(binding.key)) continue;\n\t\t\t\tconst nextTexture =\n\t\t\t\t\ttextures[binding.key] ?? normalizedTextureDefinitions[binding.key]?.source ?? null;\n\t\t\t\tif (updateTextureBinding(binding, nextTexture, renderMode)) {\n\t\t\t\t\tbindGroupDirty = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bindGroupDirty) {\n\t\t\t\tbindGroup = createBindGroup();\n\t\t\t}\n\n\t\t\t// Apply pending storage buffer writes\n\t\t\tif (pendingStorageWrites) {\n\t\t\t\tfor (const write of pendingStorageWrites) {\n\t\t\t\t\tconst buffer = storageBufferMap.get(write.name);\n\t\t\t\t\tif (buffer) {\n\t\t\t\t\t\tconst data = write.data;\n\t\t\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\t\t\tbuffer,\n\t\t\t\t\t\t\twrite.offset,\n\t\t\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\t\t\tdata.byteLength\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst commandEncoder = device.createCommandEncoder();\n\t\t\tconst passes = resolvePasses();\n\t\t\tconst clearColor = options.getClearColor();\n\t\t\tsyncPassLifecycle(passes, width, height);\n\t\t\tconst runtimeTargets = syncRenderTargets(width, height);\n\t\t\tconst graphPlan = isGraphPlanCacheValid(passes, clearColor)\n\t\t\t\t? cachedGraphPlan!\n\t\t\t\t: (() => {\n\t\t\t\t\t\tconst nextPlan = planRenderGraph(passes, clearColor, renderTargetKeys);\n\t\t\t\t\t\tupdateGraphPlanCache(passes, clearColor, nextPlan);\n\t\t\t\t\t\treturn nextPlan;\n\t\t\t\t\t})();\n\t\t\tconst canvasTexture = context.getCurrentTexture();\n\t\t\tconst canvasSurface: RenderTarget = {\n\t\t\t\ttexture: canvasTexture,\n\t\t\t\tview: canvasTexture.createView(),\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tformat\n\t\t\t};\n\t\t\tconst slots =\n\t\t\t\tgraphPlan.steps.length > 0\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tsource: ensureSlotTarget('source', width, height),\n\t\t\t\t\t\t\ttarget: ensureSlotTarget('target', width, height),\n\t\t\t\t\t\t\tcanvas: canvasSurface\n\t\t\t\t\t\t}\n\t\t\t\t\t: null;\n\t\t\tconst sceneOutput = slots ? slots.source : canvasSurface;\n\n\t\t\t// Dispatch compute passes BEFORE scene render so storage textures\n\t\t\t// and buffers are up-to-date when the fragment shader samples them.\n\t\t\tif (slots) {\n\t\t\t\tfor (const step of graphPlan.steps) {\n\t\t\t\t\tif (step.kind !== 'compute') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst computePass = step.pass as {\n\t\t\t\t\t\tisCompute?: boolean;\n\t\t\t\t\t\tgetCompute?: () => string;\n\t\t\t\t\t\tresolveDispatch?: (ctx: {\n\t\t\t\t\t\t\twidth: number;\n\t\t\t\t\t\t\theight: number;\n\t\t\t\t\t\t\ttime: number;\n\t\t\t\t\t\t\tdelta: number;\n\t\t\t\t\t\t\tworkgroupSize: [number, number, number];\n\t\t\t\t\t\t}) => [number, number, number];\n\t\t\t\t\t\tgetWorkgroupSize?: () => [number, number, number];\n\t\t\t\t\t\tisPingPong?: boolean;\n\t\t\t\t\t\tgetTarget?: () => string;\n\t\t\t\t\t\tgetCurrentOutput?: () => string;\n\t\t\t\t\t\tgetIterations?: () => number;\n\t\t\t\t\t\tadvanceFrame?: () => void;\n\t\t\t\t\t};\n\t\t\t\t\tif (\n\t\t\t\t\t\tcomputePass.getCompute &&\n\t\t\t\t\t\tcomputePass.resolveDispatch &&\n\t\t\t\t\t\tcomputePass.getWorkgroupSize\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst computeSource = computePass.getCompute();\n\t\t\t\t\t\tconst pingPongTarget =\n\t\t\t\t\t\t\tcomputePass.isPingPong && computePass.getTarget ? computePass.getTarget() : undefined;\n\t\t\t\t\t\tif (computePass.isPingPong && !pingPongTarget) {\n\t\t\t\t\t\t\tthrow new Error('PingPongComputePass must provide a target texture key.');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst pingPongPair = pingPongTarget ? ensurePingPongTexturePair(pingPongTarget) : null;\n\t\t\t\t\t\tconst pipelineEntry = buildComputePipelineEntry({\n\t\t\t\t\t\t\tcomputeSource,\n\t\t\t\t\t\t\t...(pingPongPair\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tpingPongTarget: pingPongPair.target,\n\t\t\t\t\t\t\t\t\t\tpingPongFormat: pingPongPair.format\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {})\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst workgroupSize = computePass.getWorkgroupSize();\n\t\t\t\t\t\tconst storageBindGroup = getComputeStorageBindGroup();\n\t\t\t\t\t\tconst storageTextureBindGroup = getComputeStorageTextureBindGroup();\n\t\t\t\t\t\tconst iterations =\n\t\t\t\t\t\t\tcomputePass.isPingPong && computePass.getIterations ? computePass.getIterations() : 1;\n\t\t\t\t\t\tconst currentOutput =\n\t\t\t\t\t\t\tcomputePass.isPingPong && computePass.getCurrentOutput\n\t\t\t\t\t\t\t\t? computePass.getCurrentOutput()\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\tconst readFromAAtIterationZero =\n\t\t\t\t\t\t\tpingPongPair && currentOutput ? currentOutput !== `${pingPongPair.target}B` : true;\n\n\t\t\t\t\t\tfor (let iter = 0; iter < iterations; iter += 1) {\n\t\t\t\t\t\t\tconst dispatch = computePass.resolveDispatch({\n\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\t\ttime,\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tworkgroupSize\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst cPass = commandEncoder.beginComputePass();\n\t\t\t\t\t\t\tcPass.setPipeline(pipelineEntry.pipeline);\n\t\t\t\t\t\t\tcPass.setBindGroup(0, pipelineEntry.bindGroup);\n\t\t\t\t\t\t\tif (storageBindGroup) {\n\t\t\t\t\t\t\t\tcPass.setBindGroup(1, storageBindGroup);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (pingPongPair) {\n\t\t\t\t\t\t\t\tconst readFromA =\n\t\t\t\t\t\t\t\t\titer % 2 === 0 ? readFromAAtIterationZero : !readFromAAtIterationZero;\n\t\t\t\t\t\t\t\tcPass.setBindGroup(\n\t\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t\t\tgetPingPongStorageTextureBindGroup(pingPongPair.target, readFromA)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else if (storageTextureBindGroup) {\n\t\t\t\t\t\t\t\tcPass.setBindGroup(2, storageTextureBindGroup);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcPass.dispatchWorkgroups(dispatch[0], dispatch[1], dispatch[2]);\n\t\t\t\t\t\t\tcPass.end();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (computePass.isPingPong && computePass.advanceFrame) {\n\t\t\t\t\t\t\tcomputePass.advanceFrame();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst scenePass = commandEncoder.beginRenderPass({\n\t\t\t\tcolorAttachments: [\n\t\t\t\t\t{\n\t\t\t\t\t\tview: sceneOutput.view,\n\t\t\t\t\t\tclearValue: {\n\t\t\t\t\t\t\tr: clearColor[0],\n\t\t\t\t\t\t\tg: clearColor[1],\n\t\t\t\t\t\t\tb: clearColor[2],\n\t\t\t\t\t\t\ta: clearColor[3]\n\t\t\t\t\t\t},\n\t\t\t\t\t\tloadOp: 'clear',\n\t\t\t\t\t\tstoreOp: 'store'\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tscenePass.setPipeline(pipeline);\n\t\t\tscenePass.setBindGroup(0, bindGroup);\n\t\t\tif (fragmentStorageBindGroup) {\n\t\t\t\tscenePass.setBindGroup(1, fragmentStorageBindGroup);\n\t\t\t}\n\t\t\tscenePass.draw(3);\n\t\t\tscenePass.end();\n\n\t\t\tif (slots) {\n\t\t\t\tconst resolveStepSurface = (\n\t\t\t\t\tslot: RenderPassInputSlot | RenderPassOutputSlot\n\t\t\t\t): RenderTarget => {\n\t\t\t\t\tif (slot === 'source') {\n\t\t\t\t\t\treturn slots.source;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (slot === 'target') {\n\t\t\t\t\t\treturn slots.target;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (slot === 'canvas') {\n\t\t\t\t\t\treturn slots.canvas;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst named = runtimeTargets[slot];\n\t\t\t\t\tif (!named) {\n\t\t\t\t\t\tthrow new Error(`Render graph references unknown runtime target \"${slot}\".`);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn named;\n\t\t\t\t};\n\n\t\t\t\tfor (const step of graphPlan.steps) {\n\t\t\t\t\t// Compute passes already dispatched above\n\t\t\t\t\tif (step.kind === 'compute') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst input = resolveStepSurface(step.input);\n\t\t\t\t\tconst output = resolveStepSurface(step.output);\n\n\t\t\t\t\t(step.pass as RenderPass).render({\n\t\t\t\t\t\tdevice,\n\t\t\t\t\t\tcommandEncoder,\n\t\t\t\t\t\tsource: slots.source,\n\t\t\t\t\t\ttarget: slots.target,\n\t\t\t\t\t\tcanvas: slots.canvas,\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\toutput,\n\t\t\t\t\t\ttargets: runtimeTargets,\n\t\t\t\t\t\ttime,\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tclear: step.clear,\n\t\t\t\t\t\tclearColor: step.clearColor,\n\t\t\t\t\t\tpreserve: step.preserve,\n\t\t\t\t\t\tbeginRenderPass: (passOptions?: {\n\t\t\t\t\t\t\tclear?: boolean;\n\t\t\t\t\t\t\tclearColor?: [number, number, number, number];\n\t\t\t\t\t\t\tpreserve?: boolean;\n\t\t\t\t\t\t\tview?: GPUTextureView;\n\t\t\t\t\t\t}) => {\n\t\t\t\t\t\t\tconst clear = passOptions?.clear ?? step.clear;\n\t\t\t\t\t\t\tconst clearColor = passOptions?.clearColor ?? step.clearColor;\n\t\t\t\t\t\t\tconst preserve = passOptions?.preserve ?? step.preserve;\n\n\t\t\t\t\t\t\treturn commandEncoder.beginRenderPass({\n\t\t\t\t\t\t\t\tcolorAttachments: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tview: passOptions?.view ?? output.view,\n\t\t\t\t\t\t\t\t\t\tclearValue: {\n\t\t\t\t\t\t\t\t\t\t\tr: clearColor[0],\n\t\t\t\t\t\t\t\t\t\t\tg: clearColor[1],\n\t\t\t\t\t\t\t\t\t\t\tb: clearColor[2],\n\t\t\t\t\t\t\t\t\t\t\ta: clearColor[3]\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tloadOp: clear ? 'clear' : 'load',\n\t\t\t\t\t\t\t\t\t\tstoreOp: preserve ? 'store' : 'discard'\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (step.needsSwap) {\n\t\t\t\t\t\tconst previousSource = slots.source;\n\t\t\t\t\t\tslots.source = slots.target;\n\t\t\t\t\t\tslots.target = previousSource;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (graphPlan.finalOutput !== 'canvas') {\n\t\t\t\t\tconst finalSurface = resolveStepSurface(graphPlan.finalOutput);\n\t\t\t\t\tblitToCanvas(commandEncoder, finalSurface.view, slots.canvas.view, clearColor);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdevice.queue.submit([commandEncoder.finish()]);\n\t\t};\n\n\t\tacceptInitializationCleanups = false;\n\t\tinitializationCleanups.length = 0;\n\t\treturn {\n\t\t\trender,\n\t\t\tgetStorageBuffer: (name: string): GPUBuffer | undefined => {\n\t\t\t\treturn storageBufferMap.get(name);\n\t\t\t},\n\t\t\tgetDevice: (): GPUDevice => {\n\t\t\t\treturn device;\n\t\t\t},\n\t\t\tdestroy: () => {\n\t\t\t\tisDestroyed = true;\n\t\t\t\tdevice.removeEventListener('uncapturederror', handleUncapturedError);\n\t\t\t\tframeBuffer.destroy();\n\t\t\t\tuniformBuffer.destroy();\n\t\t\t\tfor (const buffer of storageBufferMap.values()) {\n\t\t\t\t\tbuffer.destroy();\n\t\t\t\t}\n\t\t\t\tstorageBufferMap.clear();\n\t\t\t\tfor (const pair of pingPongTexturePairs.values()) {\n\t\t\t\t\tpair.textureA.destroy();\n\t\t\t\t\tpair.textureB.destroy();\n\t\t\t\t}\n\t\t\t\tpingPongTexturePairs.clear();\n\t\t\t\tcomputePipelineCache.clear();\n\t\t\t\tdestroyRenderTexture(sourceSlotTarget);\n\t\t\t\tdestroyRenderTexture(targetSlotTarget);\n\t\t\t\tfor (const target of runtimeRenderTargets.values()) {\n\t\t\t\t\ttarget.texture.destroy();\n\t\t\t\t}\n\t\t\t\truntimeRenderTargets.clear();\n\t\t\t\tfor (const pass of activePasses) {\n\t\t\t\t\tpass.dispose?.();\n\t\t\t\t}\n\t\t\t\tactivePasses.length = 0;\n\t\t\t\tlifecyclePassesRef = null;\n\t\t\t\tfor (const binding of textureBindings) {\n\t\t\t\t\tbinding.texture?.destroy();\n\t\t\t\t\tbinding.fallbackTexture.destroy();\n\t\t\t\t}\n\t\t\t\tblitBindGroupByView = new WeakMap();\n\t\t\t\tcachedGraphPlan = null;\n\t\t\t\tcachedGraphPasses.length = 0;\n\t\t\t\trenderTargetSnapshot = {};\n\t\t\t\trenderTargetKeys = [];\n\t\t\t}\n\t\t};\n\t} catch (error) {\n\t\tisDestroyed = true;\n\t\tacceptInitializationCleanups = false;\n\t\tdevice.removeEventListener('uncapturederror', handleUncapturedError);\n\t\trunInitializationCleanups();\n\t\tthrow error;\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"renderer.js","names":[],"sources":["../../src/lib/core/renderer.ts"],"sourcesContent":["import { buildRenderTargetSignature, resolveRenderTargetDefinitions } from './render-targets.js';\nimport { planRenderGraph, type RenderGraphPlan } from './render-graph.js';\nimport {\n\tbuildShaderSourceWithMap,\n\tformatShaderSourceLocation,\n\ttype ShaderLineMap\n} from './shader.js';\nimport {\n\tattachShaderCompilationDiagnostics,\n\ttype ShaderCompilationRuntimeContext\n} from './error-diagnostics.js';\nimport {\n\tgetTextureMipLevelCount,\n\tnormalizeTextureDefinitions,\n\tresolveTextureUpdateMode,\n\tresolveTextureSize,\n\ttoTextureData\n} from './textures.js';\nimport { packUniformsInto } from './uniforms.js';\nimport {\n\tbuildComputeShaderSourceWithMap,\n\tbuildPingPongComputeShaderSourceWithMap,\n\textractWorkgroupSize,\n\tstorageTextureSampleScalarType\n} from './compute-shader.js';\nimport { createComputeStorageBindGroupCache } from './compute-bindgroup-cache.js';\nimport { normalizeStorageBufferDefinition } from './storage-buffers.js';\nimport type {\n\tAnyPass,\n\tRenderPass,\n\tRenderPassInputSlot,\n\tRenderPassOutputSlot,\n\tRenderMode,\n\tRenderTarget,\n\tRenderer,\n\tRendererOptions,\n\tStorageBufferAccess,\n\tStorageBufferType,\n\tTextureSource,\n\tTextureUpdateMode,\n\tTextureValue\n} from './types.js';\n\n/**\n * Binding index for frame uniforms (`time`, `delta`, `resolution`).\n */\nconst FRAME_BINDING = 0;\n\n/**\n * Binding index for material uniform buffer.\n */\nconst UNIFORM_BINDING = 1;\n\n/**\n * First binding index used for texture sampler/texture pairs.\n */\nconst FIRST_TEXTURE_BINDING = 2;\n\n/**\n * Runtime texture binding state associated with a single texture key.\n */\ninterface RuntimeTextureBinding {\n\tkey: string;\n\tsamplerBinding: number;\n\ttextureBinding: number;\n\tfragmentVisible: boolean;\n\tsampler: GPUSampler;\n\tfallbackTexture: GPUTexture;\n\tfallbackView: GPUTextureView;\n\ttexture: GPUTexture | null;\n\tview: GPUTextureView;\n\tsource: TextureSource | null;\n\twidth: number | undefined;\n\theight: number | undefined;\n\tmipLevelCount: number;\n\tformat: GPUTextureFormat;\n\tcolorSpace: 'srgb' | 'linear';\n\tdefaultColorSpace: 'srgb' | 'linear';\n\tflipY: boolean;\n\tdefaultFlipY: boolean;\n\tgenerateMipmaps: boolean;\n\tdefaultGenerateMipmaps: boolean;\n\tpremultipliedAlpha: boolean;\n\tdefaultPremultipliedAlpha: boolean;\n\tupdate: TextureUpdateMode;\n\tdefaultUpdate?: TextureUpdateMode;\n\tlastToken: TextureValue;\n}\n\n/**\n * Runtime render target allocation metadata.\n */\ninterface RuntimeRenderTarget {\n\ttexture: GPUTexture;\n\tview: GPUTextureView;\n\twidth: number;\n\theight: number;\n\tformat: GPUTextureFormat;\n}\n\n/**\n * Runtime ping-pong storage textures for a single logical target key.\n */\ninterface PingPongTexturePair {\n\ttarget: string;\n\tformat: GPUTextureFormat;\n\twidth: number;\n\theight: number;\n\ttextureA: GPUTexture;\n\tviewA: GPUTextureView;\n\ttextureB: GPUTexture;\n\tviewB: GPUTextureView;\n\tbindGroupLayout: GPUBindGroupLayout;\n\treadAWriteBBindGroup: GPUBindGroup | null;\n\treadBWriteABindGroup: GPUBindGroup | null;\n}\n\n/**\n * Cached pass properties used to validate render-graph cache correctness.\n */\ninterface RenderGraphPassSnapshot {\n\tpass: AnyPass;\n\tenabled: RenderPass['enabled'];\n\tneedsSwap: RenderPass['needsSwap'];\n\tinput: RenderPass['input'];\n\toutput: RenderPass['output'];\n\tclear: RenderPass['clear'];\n\tpreserve: RenderPass['preserve'];\n\thasClearColor: boolean;\n\tclearColor0: number;\n\tclearColor1: number;\n\tclearColor2: number;\n\tclearColor3: number;\n}\n\n/**\n * Returns sampler/texture binding slots for a texture index.\n */\nfunction getTextureBindings(index: number): {\n\tsamplerBinding: number;\n\ttextureBinding: number;\n} {\n\tconst samplerBinding = FIRST_TEXTURE_BINDING + index * 2;\n\treturn {\n\t\tsamplerBinding,\n\t\ttextureBinding: samplerBinding + 1\n\t};\n}\n\n/**\n * Maps WGSL scalar texture type to WebGPU sampled texture bind-group sample type.\n */\nfunction toGpuTextureSampleType(type: 'f32' | 'u32' | 'i32'): GPUTextureSampleType {\n\tif (type === 'u32') {\n\t\treturn 'uint';\n\t}\n\tif (type === 'i32') {\n\t\treturn 'sint';\n\t}\n\treturn 'float';\n}\n\n/**\n * Resizes canvas backing store to match client size and DPR.\n */\nfunction resizeCanvas(\n\tcanvas: HTMLCanvasElement,\n\tdprInput: number,\n\tcssSize?: { width: number; height: number }\n): { width: number; height: number } {\n\tconst dpr = Number.isFinite(dprInput) && dprInput > 0 ? dprInput : 1;\n\tconst rect = cssSize ? null : canvas.getBoundingClientRect();\n\tconst cssWidth = Math.max(0, cssSize?.width ?? rect?.width ?? 0);\n\tconst cssHeight = Math.max(0, cssSize?.height ?? rect?.height ?? 0);\n\tconst width = Math.max(1, Math.floor((cssWidth || 1) * dpr));\n\tconst height = Math.max(1, Math.floor((cssHeight || 1) * dpr));\n\n\tif (canvas.width !== width || canvas.height !== height) {\n\t\tcanvas.width = width;\n\t\tcanvas.height = height;\n\t}\n\n\treturn { width, height };\n}\n\n/**\n * Throws when a shader module contains WGSL compilation errors.\n */\nasync function assertCompilation(\n\tmodule: GPUShaderModule,\n\toptions?: {\n\t\tlineMap?: ShaderLineMap;\n\t\tfragmentSource?: string;\n\t\tcomputeSource?: string;\n\t\tincludeSources?: Record<string, string>;\n\t\tdefineBlockSource?: string;\n\t\tmaterialSource?: {\n\t\t\tcomponent?: string;\n\t\t\tfile?: string;\n\t\t\tline?: number;\n\t\t\tcolumn?: number;\n\t\t\tfunctionName?: string;\n\t\t} | null;\n\t\truntimeContext?: ShaderCompilationRuntimeContext;\n\t\terrorPrefix?: string;\n\t\tshaderStage?: 'fragment' | 'compute';\n\t}\n): Promise<void> {\n\tconst info = await module.getCompilationInfo();\n\tconst errors = info.messages.filter((message: GPUCompilationMessage) => message.type === 'error');\n\n\tif (errors.length === 0) {\n\t\treturn;\n\t}\n\n\tconst diagnostics = errors.map((message: GPUCompilationMessage) => ({\n\t\tgeneratedLine: message.lineNum,\n\t\tmessage: message.message,\n\t\tlinePos: message.linePos,\n\t\tlineLength: message.length,\n\t\tsourceLocation: options?.lineMap?.[message.lineNum] ?? null\n\t}));\n\n\tconst summary = diagnostics\n\t\t.map((diagnostic) => {\n\t\t\tconst sourceLabel = formatShaderSourceLocation(diagnostic.sourceLocation);\n\t\t\tconst generatedLineLabel =\n\t\t\t\tdiagnostic.generatedLine > 0 ? `generated WGSL line ${diagnostic.generatedLine}` : null;\n\t\t\tconst contextLabel = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\t\t\tif (contextLabel.length === 0) {\n\t\t\t\treturn diagnostic.message;\n\t\t\t}\n\n\t\t\treturn `[${contextLabel.join(' | ')}] ${diagnostic.message}`;\n\t\t})\n\t\t.join('\\n');\n\tconst prefix = options?.errorPrefix ?? 'WGSL compilation failed';\n\tconst error = new Error(`${prefix}:\\n${summary}`);\n\tthrow attachShaderCompilationDiagnostics(error, {\n\t\tkind: 'shader-compilation',\n\t\t...(options?.shaderStage !== undefined ? { shaderStage: options.shaderStage } : {}),\n\t\tdiagnostics,\n\t\tfragmentSource: options?.fragmentSource ?? '',\n\t\t...(options?.computeSource !== undefined ? { computeSource: options.computeSource } : {}),\n\t\tincludeSources: options?.includeSources ?? {},\n\t\t...(options?.defineBlockSource !== undefined\n\t\t\t? { defineBlockSource: options.defineBlockSource }\n\t\t\t: {}),\n\t\tmaterialSource: options?.materialSource ?? null,\n\t\t...(options?.runtimeContext !== undefined ? { runtimeContext: options.runtimeContext } : {})\n\t});\n}\n\nfunction toSortedUniqueStrings(values: string[]): string[] {\n\treturn Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));\n}\n\nfunction extractGeneratedLineFromComputeError(message: string): number | null {\n\tconst lineMatch = message.match(/\\bline\\s+(\\d+)\\b/i);\n\tif (lineMatch) {\n\t\tconst parsed = Number.parseInt(lineMatch[1] ?? '', 10);\n\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\treturn parsed;\n\t\t}\n\t}\n\n\tconst colonMatch = message.match(/:(\\d+):\\d+/);\n\tif (colonMatch) {\n\t\tconst parsed = Number.parseInt(colonMatch[1] ?? '', 10);\n\t\tif (Number.isFinite(parsed) && parsed > 0) {\n\t\t\treturn parsed;\n\t\t}\n\t}\n\n\treturn null;\n}\n\nfunction toComputeCompilationError(input: {\n\terror: unknown;\n\tlineMap: ShaderLineMap;\n\tcomputeSource: string;\n\truntimeContext: ShaderCompilationRuntimeContext;\n}): Error {\n\tconst baseError =\n\t\tinput.error instanceof Error ? input.error : new Error(String(input.error ?? 'Unknown error'));\n\tconst generatedLine = extractGeneratedLineFromComputeError(baseError.message) ?? 0;\n\tconst sourceLocation = generatedLine > 0 ? (input.lineMap[generatedLine] ?? null) : null;\n\tconst diagnostics = [\n\t\t{\n\t\t\tgeneratedLine,\n\t\t\tmessage: baseError.message,\n\t\t\tsourceLocation\n\t\t}\n\t];\n\tconst sourceLabel = formatShaderSourceLocation(sourceLocation);\n\tconst generatedLineLabel = generatedLine > 0 ? `generated WGSL line ${generatedLine}` : null;\n\tconst contextLabel = [sourceLabel, generatedLineLabel].filter((value) => Boolean(value));\n\tconst summary =\n\t\tcontextLabel.length > 0\n\t\t\t? `[${contextLabel.join(' | ')}] ${baseError.message}`\n\t\t\t: baseError.message;\n\tconst wrapped = new Error(`Compute shader compilation failed:\\n${summary}`);\n\n\treturn attachShaderCompilationDiagnostics(wrapped, {\n\t\tkind: 'shader-compilation',\n\t\tshaderStage: 'compute',\n\t\tdiagnostics,\n\t\tfragmentSource: '',\n\t\tcomputeSource: input.computeSource,\n\t\tincludeSources: {},\n\t\tmaterialSource: null,\n\t\truntimeContext: input.runtimeContext\n\t});\n}\n\nfunction buildPassGraphSnapshot(\n\tpasses: AnyPass[] | undefined\n): NonNullable<ShaderCompilationRuntimeContext['passGraph']> {\n\tconst declaredPasses = passes ?? [];\n\tlet enabledPassCount = 0;\n\tconst inputs: string[] = [];\n\tconst outputs: string[] = [];\n\n\tfor (const pass of declaredPasses) {\n\t\tif (pass.enabled === false) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tenabledPassCount += 1;\n\t\tif ('isCompute' in pass && (pass as { isCompute?: boolean }).isCompute === true) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst rp = pass as RenderPass;\n\t\tconst needsSwap = rp.needsSwap ?? true;\n\t\tconst input = rp.input ?? 'source';\n\t\tconst output = rp.output ?? (needsSwap ? 'target' : 'source');\n\t\tinputs.push(input);\n\t\toutputs.push(output);\n\t}\n\n\treturn {\n\t\tpassCount: declaredPasses.length,\n\t\tenabledPassCount,\n\t\tinputs: toSortedUniqueStrings(inputs),\n\t\toutputs: toSortedUniqueStrings(outputs)\n\t};\n}\n\nfunction buildShaderCompilationRuntimeContext(\n\toptions: RendererOptions\n): ShaderCompilationRuntimeContext {\n\tconst passList = options.getPasses?.() ?? options.passes;\n\tconst renderTargetMap = options.getRenderTargets?.() ?? options.renderTargets;\n\n\treturn {\n\t\t...(options.materialSignature ? { materialSignature: options.materialSignature } : {}),\n\t\tpassGraph: buildPassGraphSnapshot(passList),\n\t\tactiveRenderTargets: Object.keys(renderTargetMap ?? {}).sort((a, b) => a.localeCompare(b))\n\t};\n}\n\n/**\n * Creates a 1x1 white fallback texture used before user textures become available.\n */\nfunction createFallbackTexture(device: GPUDevice, format: GPUTextureFormat): GPUTexture {\n\tconst texture = device.createTexture({\n\t\tsize: { width: 1, height: 1, depthOrArrayLayers: 1 },\n\t\tformat,\n\t\tusage:\n\t\t\tGPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT\n\t});\n\n\tconst pixel = new Uint8Array([255, 255, 255, 255]);\n\tdevice.queue.writeTexture(\n\t\t{ texture },\n\t\tpixel,\n\t\t{ offset: 0, bytesPerRow: 4, rowsPerImage: 1 },\n\t\t{ width: 1, height: 1, depthOrArrayLayers: 1 }\n\t);\n\n\treturn texture;\n}\n\n/**\n * Creates an offscreen canvas used for CPU mipmap generation.\n */\nfunction createMipmapCanvas(width: number, height: number): OffscreenCanvas | HTMLCanvasElement {\n\tif (typeof OffscreenCanvas !== 'undefined') {\n\t\treturn new OffscreenCanvas(width, height);\n\t}\n\n\tconst canvas = document.createElement('canvas');\n\tcanvas.width = width;\n\tcanvas.height = height;\n\treturn canvas;\n}\n\n/**\n * Creates typed descriptor for `copyExternalImageToTexture`.\n */\nfunction createExternalCopySource(\n\tsource: CanvasImageSource,\n\toptions: { flipY?: boolean; premultipliedAlpha?: boolean }\n): GPUCopyExternalImageSourceInfo {\n\tconst descriptor = {\n\t\tsource,\n\t\t...(options.flipY ? { flipY: true } : {}),\n\t\t...(options.premultipliedAlpha ? { premultipliedAlpha: true } : {})\n\t};\n\n\treturn descriptor as GPUCopyExternalImageSourceInfo;\n}\n\n/**\n * Uploads source content to a GPU texture and optionally generates mip chain on CPU.\n */\nfunction uploadTexture(\n\tdevice: GPUDevice,\n\ttexture: GPUTexture,\n\tbinding: Pick<RuntimeTextureBinding, 'flipY' | 'premultipliedAlpha' | 'generateMipmaps'>,\n\tsource: TextureSource,\n\twidth: number,\n\theight: number,\n\tmipLevelCount: number\n): void {\n\tdevice.queue.copyExternalImageToTexture(\n\t\tcreateExternalCopySource(source, {\n\t\t\tflipY: binding.flipY,\n\t\t\tpremultipliedAlpha: binding.premultipliedAlpha\n\t\t}),\n\t\t{ texture, mipLevel: 0 },\n\t\t{ width, height, depthOrArrayLayers: 1 }\n\t);\n\n\tif (!binding.generateMipmaps || mipLevelCount <= 1) {\n\t\treturn;\n\t}\n\n\tlet previousSource: CanvasImageSource = source;\n\tlet previousWidth = width;\n\tlet previousHeight = height;\n\n\tfor (let level = 1; level < mipLevelCount; level += 1) {\n\t\tconst nextWidth = Math.max(1, Math.floor(previousWidth / 2));\n\t\tconst nextHeight = Math.max(1, Math.floor(previousHeight / 2));\n\t\tconst canvas = createMipmapCanvas(nextWidth, nextHeight);\n\t\tconst context = canvas.getContext('2d');\n\t\tif (!context) {\n\t\t\tthrow new Error('Unable to create 2D context for mipmap generation');\n\t\t}\n\n\t\tcontext.drawImage(\n\t\t\tpreviousSource,\n\t\t\t0,\n\t\t\t0,\n\t\t\tpreviousWidth,\n\t\t\tpreviousHeight,\n\t\t\t0,\n\t\t\t0,\n\t\t\tnextWidth,\n\t\t\tnextHeight\n\t\t);\n\n\t\tdevice.queue.copyExternalImageToTexture(\n\t\t\tcreateExternalCopySource(canvas, {\n\t\t\t\tpremultipliedAlpha: binding.premultipliedAlpha\n\t\t\t}),\n\t\t\t{ texture, mipLevel: level },\n\t\t\t{ width: nextWidth, height: nextHeight, depthOrArrayLayers: 1 }\n\t\t);\n\n\t\tpreviousSource = canvas;\n\t\tpreviousWidth = nextWidth;\n\t\tpreviousHeight = nextHeight;\n\t}\n}\n\n/**\n * Creates bind group layout entries for frame/uniform buffers plus texture bindings.\n */\nfunction createBindGroupLayoutEntries(\n\ttextureBindings: RuntimeTextureBinding[]\n): GPUBindGroupLayoutEntry[] {\n\tconst entries: GPUBindGroupLayoutEntry[] = [\n\t\t{\n\t\t\tbinding: FRAME_BINDING,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\tbuffer: { type: 'uniform', minBindingSize: 16 }\n\t\t},\n\t\t{\n\t\t\tbinding: UNIFORM_BINDING,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\tbuffer: { type: 'uniform' }\n\t\t}\n\t];\n\n\tfor (const binding of textureBindings) {\n\t\tentries.push({\n\t\t\tbinding: binding.samplerBinding,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\tsampler: { type: 'filtering' }\n\t\t});\n\n\t\tentries.push({\n\t\t\tbinding: binding.textureBinding,\n\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\ttexture: {\n\t\t\t\tsampleType: 'float',\n\t\t\t\tviewDimension: '2d',\n\t\t\t\tmultisampled: false\n\t\t\t}\n\t\t});\n\t}\n\n\treturn entries;\n}\n\n/**\n * Maximum gap (in floats) between two dirty ranges that triggers merge.\n *\n * Set to 4 (16 bytes) which covers one vec4f alignment slot.\n */\nconst DIRTY_RANGE_MERGE_GAP = 4;\n\n/**\n * Computes dirty float ranges between two uniform snapshots.\n *\n * Adjacent dirty ranges separated by a gap smaller than or equal to\n * {@link DIRTY_RANGE_MERGE_GAP} are merged to reduce `writeBuffer` calls.\n */\nexport function findDirtyFloatRanges(\n\tprevious: Float32Array,\n\tnext: Float32Array,\n\tmergeGapThreshold = DIRTY_RANGE_MERGE_GAP\n): Array<{ start: number; count: number }> {\n\tconst ranges: Array<{ start: number; count: number }> = [];\n\tlet start = -1;\n\n\tfor (let index = 0; index < next.length; index += 1) {\n\t\tif (previous[index] !== next[index]) {\n\t\t\tif (start === -1) {\n\t\t\t\tstart = index;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (start !== -1) {\n\t\t\tranges.push({ start, count: index - start });\n\t\t\tstart = -1;\n\t\t}\n\t}\n\n\tif (start !== -1) {\n\t\tranges.push({ start, count: next.length - start });\n\t}\n\n\tif (ranges.length <= 1) {\n\t\treturn ranges;\n\t}\n\n\tconst merged: Array<{ start: number; count: number }> = [ranges[0]!];\n\tfor (let index = 1; index < ranges.length; index += 1) {\n\t\tconst prev = merged[merged.length - 1]!;\n\t\tconst curr = ranges[index]!;\n\t\tconst gap = curr.start - (prev.start + prev.count);\n\n\t\tif (gap <= mergeGapThreshold) {\n\t\t\tprev.count = curr.start + curr.count - prev.start;\n\t\t} else {\n\t\t\tmerged.push(curr);\n\t\t}\n\t}\n\n\treturn merged;\n}\n\n/**\n * Determines whether shader output should perform linear-to-sRGB conversion.\n */\nfunction shouldConvertLinearToSrgb(\n\toutputColorSpace: 'srgb' | 'linear',\n\tcanvasFormat: GPUTextureFormat\n): boolean {\n\tif (outputColorSpace !== 'srgb') {\n\t\treturn false;\n\t}\n\n\treturn !canvasFormat.endsWith('-srgb');\n}\n\n/**\n * WGSL shader used to blit an offscreen texture to the canvas.\n */\nfunction createFullscreenBlitShader(): string {\n\treturn `\nstruct MotionGPUVertexOut {\n\t@builtin(position) position: vec4f,\n\t@location(0) uv: vec2f,\n};\n\n@group(0) @binding(0) var motiongpuBlitSampler: sampler;\n@group(0) @binding(1) var motiongpuBlitTexture: texture_2d<f32>;\n\n@vertex\nfn motiongpuBlitVertex(@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@fragment\nfn motiongpuBlitFragment(in: MotionGPUVertexOut) -> @location(0) vec4f {\n\treturn textureSample(motiongpuBlitTexture, motiongpuBlitSampler, in.uv);\n}\n`;\n}\n\n/**\n * Allocates a render target texture with usage flags suitable for passes/blits.\n */\nfunction createRenderTexture(\n\tdevice: GPUDevice,\n\twidth: number,\n\theight: number,\n\tformat: GPUTextureFormat\n): RuntimeRenderTarget {\n\tconst texture = device.createTexture({\n\t\tsize: { width, height, depthOrArrayLayers: 1 },\n\t\tformat,\n\t\tusage:\n\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\tGPUTextureUsage.RENDER_ATTACHMENT |\n\t\t\tGPUTextureUsage.COPY_DST |\n\t\t\tGPUTextureUsage.COPY_SRC\n\t});\n\n\treturn {\n\t\ttexture,\n\t\tview: texture.createView(),\n\t\twidth,\n\t\theight,\n\t\tformat\n\t};\n}\n\n/**\n * Destroys a render target texture if present.\n */\nfunction destroyRenderTexture(target: RuntimeRenderTarget | null): void {\n\ttarget?.texture.destroy();\n}\n\n/**\n * Creates the WebGPU renderer used by `FragCanvas`.\n *\n * @param options - Renderer creation options resolved from material/context state.\n * @returns Renderer instance with `render` and `destroy`.\n * @throws {Error} On WebGPU unavailability, shader compilation issues, or runtime setup failures.\n */\nexport async function createRenderer(options: RendererOptions): Promise<Renderer> {\n\tif (!navigator.gpu) {\n\t\tthrow new Error('WebGPU is not available in this browser');\n\t}\n\n\tconst context = options.canvas.getContext('webgpu') as GPUCanvasContext | null;\n\tif (!context) {\n\t\tthrow new Error('Canvas does not support webgpu context');\n\t}\n\n\tconst format = navigator.gpu.getPreferredCanvasFormat();\n\tconst adapter = await navigator.gpu.requestAdapter(options.adapterOptions);\n\tif (!adapter) {\n\t\tthrow new Error('Unable to acquire WebGPU adapter');\n\t}\n\n\tconst device = await adapter.requestDevice(options.deviceDescriptor);\n\tlet isDestroyed = false;\n\tlet deviceLostMessage: string | null = null;\n\tlet uncapturedErrorMessage: string | null = null;\n\tconst initializationCleanups: Array<() => void> = [];\n\tlet acceptInitializationCleanups = true;\n\n\tconst registerInitializationCleanup = (cleanup: () => void): void => {\n\t\tif (!acceptInitializationCleanups) {\n\t\t\treturn;\n\t\t}\n\t\toptions.__onInitializationCleanupRegistered?.();\n\t\tinitializationCleanups.push(cleanup);\n\t};\n\n\tconst runInitializationCleanups = (): void => {\n\t\tfor (let index = initializationCleanups.length - 1; index >= 0; index -= 1) {\n\t\t\ttry {\n\t\t\t\tinitializationCleanups[index]?.();\n\t\t\t} catch {\n\t\t\t\t// Best-effort cleanup on failed renderer initialization.\n\t\t\t}\n\t\t}\n\t\tinitializationCleanups.length = 0;\n\t};\n\n\tvoid device.lost.then((info) => {\n\t\tif (isDestroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst reason = info.reason ? ` (${info.reason})` : '';\n\t\tconst details = info.message?.trim();\n\t\tdeviceLostMessage = details\n\t\t\t? `WebGPU device lost: ${details}${reason}`\n\t\t\t: `WebGPU device lost${reason}`;\n\t});\n\n\tconst handleUncapturedError = (event: GPUUncapturedErrorEvent): void => {\n\t\tif (isDestroyed) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst message =\n\t\t\tevent.error instanceof Error\n\t\t\t\t? event.error.message\n\t\t\t\t: String((event.error as { message?: string })?.message ?? event.error);\n\t\tuncapturedErrorMessage = `WebGPU uncaptured error: ${message}`;\n\t};\n\n\tdevice.addEventListener('uncapturederror', handleUncapturedError);\n\ttry {\n\t\tconst runtimeContext = buildShaderCompilationRuntimeContext(options);\n\t\tconst convertLinearToSrgb = shouldConvertLinearToSrgb(options.outputColorSpace, format);\n\t\tconst fragmentTextureKeys = options.textureKeys.filter(\n\t\t\t(key) => options.textureDefinitions[key]?.fragmentVisible !== false\n\t\t);\n\t\tconst builtShader = buildShaderSourceWithMap(\n\t\t\toptions.fragmentWgsl,\n\t\t\toptions.uniformLayout,\n\t\t\tfragmentTextureKeys,\n\t\t\t{\n\t\t\t\tconvertLinearToSrgb,\n\t\t\t\tfragmentLineMap: options.fragmentLineMap,\n\t\t\t\t...(options.storageBufferKeys !== undefined\n\t\t\t\t\t? { storageBufferKeys: options.storageBufferKeys }\n\t\t\t\t\t: {}),\n\t\t\t\t...(options.storageBufferDefinitions !== undefined\n\t\t\t\t\t? { storageBufferDefinitions: options.storageBufferDefinitions }\n\t\t\t\t\t: {})\n\t\t\t}\n\t\t);\n\t\tconst shaderModule = device.createShaderModule({ code: builtShader.code });\n\t\tawait assertCompilation(shaderModule, {\n\t\t\tlineMap: builtShader.lineMap,\n\t\t\tfragmentSource: options.fragmentSource,\n\t\t\tincludeSources: options.includeSources,\n\t\t\t...(options.defineBlockSource !== undefined\n\t\t\t\t? { defineBlockSource: options.defineBlockSource }\n\t\t\t\t: {}),\n\t\t\tmaterialSource: options.materialSource ?? null,\n\t\t\truntimeContext\n\t\t});\n\n\t\tconst normalizedTextureDefinitions = normalizeTextureDefinitions(\n\t\t\toptions.textureDefinitions,\n\t\t\toptions.textureKeys\n\t\t);\n\t\tconst storageBufferKeys = options.storageBufferKeys ?? [];\n\t\tconst storageBufferDefinitions = options.storageBufferDefinitions ?? {};\n\t\tconst storageTextureKeys = options.storageTextureKeys ?? [];\n\t\tconst storageTextureKeySet = new Set(storageTextureKeys);\n\t\tconst fragmentTextureIndexByKey = new Map(\n\t\t\tfragmentTextureKeys.map((key, index) => [key, index] as const)\n\t\t);\n\t\tconst textureBindings = options.textureKeys.map((key): RuntimeTextureBinding => {\n\t\t\tconst config = normalizedTextureDefinitions[key];\n\t\t\tif (!config) {\n\t\t\t\tthrow new Error(`Missing texture definition for \"${key}\"`);\n\t\t\t}\n\n\t\t\tconst fragmentTextureIndex = fragmentTextureIndexByKey.get(key);\n\t\t\tconst fragmentVisible = fragmentTextureIndex !== undefined;\n\t\t\tconst { samplerBinding, textureBinding } = getTextureBindings(fragmentTextureIndex ?? 0);\n\t\t\tconst sampler = device.createSampler({\n\t\t\t\tmagFilter: config.filter,\n\t\t\t\tminFilter: config.filter,\n\t\t\t\tmipmapFilter: config.generateMipmaps ? config.filter : 'nearest',\n\t\t\t\taddressModeU: config.addressModeU,\n\t\t\t\taddressModeV: config.addressModeV,\n\t\t\t\tmaxAnisotropy: config.filter === 'linear' ? config.anisotropy : 1\n\t\t\t});\n\t\t\t// Storage textures use a safe fallback format — the fallback is never\n\t\t\t// sampled because storage textures are eagerly allocated with their\n\t\t\t// real format/dimensions. Non-storage textures use their own format.\n\t\t\tconst fallbackFormat = config.storage ? 'rgba8unorm' : config.format;\n\t\t\tconst fallbackTexture = createFallbackTexture(device, fallbackFormat);\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\tfallbackTexture.destroy();\n\t\t\t});\n\t\t\tconst fallbackView = fallbackTexture.createView();\n\n\t\t\tconst runtimeBinding: RuntimeTextureBinding = {\n\t\t\t\tkey,\n\t\t\t\tsamplerBinding,\n\t\t\t\ttextureBinding,\n\t\t\t\tfragmentVisible,\n\t\t\t\tsampler,\n\t\t\t\tfallbackTexture,\n\t\t\t\tfallbackView,\n\t\t\t\ttexture: null,\n\t\t\t\tview: fallbackView,\n\t\t\t\tsource: null,\n\t\t\t\twidth: undefined,\n\t\t\t\theight: undefined,\n\t\t\t\tmipLevelCount: 1,\n\t\t\t\tformat: config.format,\n\t\t\t\tcolorSpace: config.colorSpace,\n\t\t\t\tdefaultColorSpace: config.colorSpace,\n\t\t\t\tflipY: config.flipY,\n\t\t\t\tdefaultFlipY: config.flipY,\n\t\t\t\tgenerateMipmaps: config.generateMipmaps,\n\t\t\t\tdefaultGenerateMipmaps: config.generateMipmaps,\n\t\t\t\tpremultipliedAlpha: config.premultipliedAlpha,\n\t\t\t\tdefaultPremultipliedAlpha: config.premultipliedAlpha,\n\t\t\t\tupdate: config.update ?? 'once',\n\t\t\t\tlastToken: null\n\t\t\t};\n\n\t\t\tif (config.update !== undefined) {\n\t\t\t\truntimeBinding.defaultUpdate = config.update;\n\t\t\t}\n\n\t\t\t// Storage textures: eagerly create GPU texture with explicit dimensions\n\t\t\tif (config.storage && config.width && config.height) {\n\t\t\t\tconst storageUsage =\n\t\t\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\t\t\tGPUTextureUsage.STORAGE_BINDING |\n\t\t\t\t\tGPUTextureUsage.COPY_DST;\n\t\t\t\tconst storageTexture = device.createTexture({\n\t\t\t\t\tsize: { width: config.width, height: config.height, depthOrArrayLayers: 1 },\n\t\t\t\t\tformat: config.format,\n\t\t\t\t\tusage: storageUsage\n\t\t\t\t});\n\t\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\t\tstorageTexture.destroy();\n\t\t\t\t});\n\t\t\t\truntimeBinding.texture = storageTexture as unknown as GPUTexture;\n\t\t\t\truntimeBinding.view = storageTexture.createView();\n\t\t\t\truntimeBinding.width = config.width;\n\t\t\t\truntimeBinding.height = config.height;\n\t\t\t}\n\n\t\t\treturn runtimeBinding;\n\t\t});\n\t\tconst textureBindingByKey = new Map(textureBindings.map((binding) => [binding.key, binding]));\n\t\tconst fragmentTextureBindings = textureBindings.filter((binding) => binding.fragmentVisible);\n\n\t\tconst computeStorageBufferLayoutEntries: GPUBindGroupLayoutEntry[] = storageBufferKeys.map(\n\t\t\t(key, index) => {\n\t\t\t\tconst def = storageBufferDefinitions[key];\n\t\t\t\tconst access = def?.access ?? 'read-write';\n\t\t\t\tconst bufferType: GPUBufferBindingType =\n\t\t\t\t\taccess === 'read' ? 'read-only-storage' : 'storage';\n\t\t\t\treturn {\n\t\t\t\t\tbinding: index,\n\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\tbuffer: { type: bufferType }\n\t\t\t\t};\n\t\t\t}\n\t\t);\n\t\tconst computeStorageBufferTopologyKey = storageBufferKeys\n\t\t\t.map((key) => `${key}:${storageBufferDefinitions[key]?.access ?? 'read-write'}`)\n\t\t\t.join('|');\n\n\t\tconst computeStorageTextureLayoutEntries: GPUBindGroupLayoutEntry[] = storageTextureKeys.map(\n\t\t\t(key, index) => {\n\t\t\t\tconst config = normalizedTextureDefinitions[key];\n\t\t\t\treturn {\n\t\t\t\t\tbinding: index,\n\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\tformat: (config?.format ?? 'rgba8unorm') as GPUTextureFormat,\n\t\t\t\t\t\tviewDimension: '2d'\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\t\t);\n\t\tconst computeStorageTextureTopologyKey = storageTextureKeys\n\t\t\t.map((key) => `${key}:${normalizedTextureDefinitions[key]?.format ?? 'rgba8unorm'}`)\n\t\t\t.join('|');\n\n\t\tconst computeStorageBufferBindGroupCache = createComputeStorageBindGroupCache(device);\n\t\tconst computeStorageTextureBindGroupCache = createComputeStorageBindGroupCache(device);\n\n\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: createBindGroupLayoutEntries(fragmentTextureBindings)\n\t\t});\n\t\tconst fragmentStorageBindGroupLayout =\n\t\t\tstorageBufferKeys.length > 0\n\t\t\t\t? device.createBindGroupLayout({\n\t\t\t\t\t\tentries: storageBufferKeys.map((_, index) => ({\n\t\t\t\t\t\t\tbinding: index,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\t\t\t\tbuffer: { type: 'read-only-storage' as GPUBufferBindingType }\n\t\t\t\t\t\t}))\n\t\t\t\t\t})\n\t\t\t\t: null;\n\t\tconst pipelineLayout = device.createPipelineLayout({\n\t\t\tbindGroupLayouts: fragmentStorageBindGroupLayout\n\t\t\t\t? [bindGroupLayout, fragmentStorageBindGroupLayout]\n\t\t\t\t: [bindGroupLayout]\n\t\t});\n\n\t\tconst pipeline = device.createRenderPipeline({\n\t\t\tlayout: pipelineLayout,\n\t\t\tvertex: {\n\t\t\t\tmodule: shaderModule,\n\t\t\t\tentryPoint: 'motiongpuVertex'\n\t\t\t},\n\t\t\tfragment: {\n\t\t\t\tmodule: shaderModule,\n\t\t\t\tentryPoint: 'motiongpuFragment',\n\t\t\t\ttargets: [{ format }]\n\t\t\t},\n\t\t\tprimitive: {\n\t\t\t\ttopology: 'triangle-list'\n\t\t\t}\n\t\t});\n\n\t\tconst blitShaderModule = device.createShaderModule({\n\t\t\tcode: createFullscreenBlitShader()\n\t\t});\n\t\tawait assertCompilation(blitShaderModule);\n\n\t\tconst blitBindGroupLayout = device.createBindGroupLayout({\n\t\t\tentries: [\n\t\t\t\t{\n\t\t\t\t\tbinding: 0,\n\t\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\t\tsampler: { type: 'filtering' }\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tbinding: 1,\n\t\t\t\t\tvisibility: GPUShaderStage.FRAGMENT,\n\t\t\t\t\ttexture: {\n\t\t\t\t\t\tsampleType: 'float',\n\t\t\t\t\t\tviewDimension: '2d',\n\t\t\t\t\t\tmultisampled: false\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t});\n\t\tconst blitPipelineLayout = device.createPipelineLayout({\n\t\t\tbindGroupLayouts: [blitBindGroupLayout]\n\t\t});\n\t\tconst blitPipeline = device.createRenderPipeline({\n\t\t\tlayout: blitPipelineLayout,\n\t\t\tvertex: { module: blitShaderModule, entryPoint: 'motiongpuBlitVertex' },\n\t\t\tfragment: {\n\t\t\t\tmodule: blitShaderModule,\n\t\t\t\tentryPoint: 'motiongpuBlitFragment',\n\t\t\t\ttargets: [{ format }]\n\t\t\t},\n\t\t\tprimitive: {\n\t\t\t\ttopology: 'triangle-list'\n\t\t\t}\n\t\t});\n\t\tconst blitSampler = device.createSampler({\n\t\t\tmagFilter: 'linear',\n\t\t\tminFilter: 'linear',\n\t\t\taddressModeU: 'clamp-to-edge',\n\t\t\taddressModeV: 'clamp-to-edge'\n\t\t});\n\t\tlet blitBindGroupByView = new WeakMap<GPUTextureView, GPUBindGroup>();\n\n\t\t// ── Storage buffer allocation ────────────────────────────────────────\n\t\tconst storageBufferMap = new Map<string, GPUBuffer>();\n\t\tconst pingPongTexturePairs = new Map<string, PingPongTexturePair>();\n\n\t\tfor (const key of storageBufferKeys) {\n\t\t\tconst definition = storageBufferDefinitions[key];\n\t\t\tif (!definition) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst normalized = normalizeStorageBufferDefinition(definition);\n\t\t\tconst buffer = device.createBuffer({\n\t\t\t\tsize: normalized.size,\n\t\t\t\tusage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\tbuffer.destroy();\n\t\t\t});\n\t\t\tif (definition.initialData) {\n\t\t\t\tconst data = definition.initialData;\n\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\tbuffer,\n\t\t\t\t\t0,\n\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\tdata.byteLength\n\t\t\t\t);\n\t\t\t}\n\t\t\tstorageBufferMap.set(key, buffer);\n\t\t}\n\t\tconst fragmentStorageBindGroup =\n\t\t\tfragmentStorageBindGroupLayout && storageBufferKeys.length > 0\n\t\t\t\t? device.createBindGroup({\n\t\t\t\t\t\tlayout: fragmentStorageBindGroupLayout,\n\t\t\t\t\t\tentries: storageBufferKeys.map((key, index) => {\n\t\t\t\t\t\t\tconst buffer = storageBufferMap.get(key);\n\t\t\t\t\t\t\tif (!buffer) {\n\t\t\t\t\t\t\t\tthrow new Error(`Storage buffer \"${key}\" not allocated.`);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn { binding: index, resource: { buffer } };\n\t\t\t\t\t\t})\n\t\t\t\t\t})\n\t\t\t\t: null;\n\n\t\tconst ensurePingPongTexturePair = (target: string): PingPongTexturePair => {\n\t\t\tconst existing = pingPongTexturePairs.get(target);\n\t\t\tif (existing) {\n\t\t\t\treturn existing;\n\t\t\t}\n\n\t\t\tconst config = normalizedTextureDefinitions[target];\n\t\t\tif (!config || !config.storage) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`PingPongComputePass target \"${target}\" must reference a texture declared with storage:true.`\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!config.width || !config.height) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`PingPongComputePass target \"${target}\" requires explicit texture width and height.`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst usage =\n\t\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\t\tGPUTextureUsage.STORAGE_BINDING |\n\t\t\t\tGPUTextureUsage.COPY_DST;\n\t\t\tconst textureA = device.createTexture({\n\t\t\t\tsize: { width: config.width, height: config.height, depthOrArrayLayers: 1 },\n\t\t\t\tformat: config.format,\n\t\t\t\tusage\n\t\t\t});\n\t\t\tconst textureB = device.createTexture({\n\t\t\t\tsize: { width: config.width, height: config.height, depthOrArrayLayers: 1 },\n\t\t\t\tformat: config.format,\n\t\t\t\tusage\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\ttextureA.destroy();\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\ttextureB.destroy();\n\t\t\t});\n\n\t\t\tconst sampleScalarType = storageTextureSampleScalarType(config.format);\n\t\t\tconst sampleType = toGpuTextureSampleType(sampleScalarType);\n\t\t\tconst bindGroupLayout = device.createBindGroupLayout({\n\t\t\t\tentries: [\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: 0,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\ttexture: {\n\t\t\t\t\t\t\tsampleType,\n\t\t\t\t\t\t\tviewDimension: '2d',\n\t\t\t\t\t\t\tmultisampled: false\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: 1,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\t\tformat: config.format as GPUTextureFormat,\n\t\t\t\t\t\t\tviewDimension: '2d'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tconst pair: PingPongTexturePair = {\n\t\t\t\ttarget,\n\t\t\t\tformat: config.format as GPUTextureFormat,\n\t\t\t\twidth: config.width,\n\t\t\t\theight: config.height,\n\t\t\t\ttextureA,\n\t\t\t\tviewA: textureA.createView(),\n\t\t\t\ttextureB,\n\t\t\t\tviewB: textureB.createView(),\n\t\t\t\tbindGroupLayout,\n\t\t\t\treadAWriteBBindGroup: null,\n\t\t\t\treadBWriteABindGroup: null\n\t\t\t};\n\t\t\tpingPongTexturePairs.set(target, pair);\n\t\t\treturn pair;\n\t\t};\n\n\t\t// ── Compute pipeline setup ──────────────────────────────────────────\n\t\tinterface ComputePipelineEntry {\n\t\t\tpipeline: GPUComputePipeline;\n\t\t\tbindGroup: GPUBindGroup;\n\t\t\tworkgroupSize: [number, number, number];\n\t\t\tcomputeSource: string;\n\t\t}\n\t\tconst computePipelineCache = new Map<string, ComputePipelineEntry>();\n\n\t\tconst buildComputePipelineEntry = (buildOptions: {\n\t\t\tcomputeSource: string;\n\t\t\tpingPongTarget?: string;\n\t\t\tpingPongFormat?: GPUTextureFormat;\n\t\t}): ComputePipelineEntry => {\n\t\t\tconst cacheKey =\n\t\t\t\tbuildOptions.pingPongTarget && buildOptions.pingPongFormat\n\t\t\t\t\t? `pingpong:${buildOptions.pingPongTarget}:${buildOptions.pingPongFormat}:${buildOptions.computeSource}`\n\t\t\t\t\t: `compute:${buildOptions.computeSource}`;\n\t\t\tconst cached = computePipelineCache.get(cacheKey);\n\t\t\tif (cached) {\n\t\t\t\treturn cached;\n\t\t\t}\n\n\t\t\tconst storageBufferDefs: Record<\n\t\t\t\tstring,\n\t\t\t\t{ type: StorageBufferType; access: StorageBufferAccess }\n\t\t\t> = {};\n\t\t\tfor (const key of storageBufferKeys) {\n\t\t\t\tconst def = storageBufferDefinitions[key];\n\t\t\t\tif (def) {\n\t\t\t\t\tconst norm = normalizeStorageBufferDefinition(def);\n\t\t\t\t\tstorageBufferDefs[key] = { type: norm.type, access: norm.access };\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst storageTextureDefs: Record<string, { format: GPUTextureFormat }> = {};\n\t\t\tfor (const key of storageTextureKeys) {\n\t\t\t\tconst texDef = options.textureDefinitions[key];\n\t\t\t\tif (texDef?.format) {\n\t\t\t\t\tstorageTextureDefs[key] = { format: texDef.format };\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst isPingPongPipeline = Boolean(\n\t\t\t\tbuildOptions.pingPongTarget && buildOptions.pingPongFormat\n\t\t\t);\n\t\t\tconst builtComputeShader = isPingPongPipeline\n\t\t\t\t? buildPingPongComputeShaderSourceWithMap({\n\t\t\t\t\t\tcompute: buildOptions.computeSource,\n\t\t\t\t\t\tuniformLayout: options.uniformLayout,\n\t\t\t\t\t\tstorageBufferKeys,\n\t\t\t\t\t\tstorageBufferDefinitions: storageBufferDefs,\n\t\t\t\t\t\ttarget: buildOptions.pingPongTarget!,\n\t\t\t\t\t\ttargetFormat: buildOptions.pingPongFormat!\n\t\t\t\t\t})\n\t\t\t\t: buildComputeShaderSourceWithMap({\n\t\t\t\t\t\tcompute: buildOptions.computeSource,\n\t\t\t\t\t\tuniformLayout: options.uniformLayout,\n\t\t\t\t\t\tstorageBufferKeys,\n\t\t\t\t\t\tstorageBufferDefinitions: storageBufferDefs,\n\t\t\t\t\t\tstorageTextureKeys,\n\t\t\t\t\t\tstorageTextureDefinitions: storageTextureDefs\n\t\t\t\t\t});\n\n\t\t\tconst computeShaderModule = device.createShaderModule({ code: builtComputeShader.code });\n\t\t\tconst workgroupSize = extractWorkgroupSize(buildOptions.computeSource);\n\n\t\t\t// Compute bind group layout: group(0)=uniforms, group(1)=storage buffers, group(2)=storage textures\n\t\t\tconst computeUniformBGL = device.createBindGroupLayout({\n\t\t\t\tentries: [\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: FRAME_BINDING,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\tbuffer: { type: 'uniform', minBindingSize: 16 }\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tbinding: UNIFORM_BINDING,\n\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\tbuffer: { type: 'uniform' }\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tconst storageBGL =\n\t\t\t\tcomputeStorageBufferLayoutEntries.length > 0\n\t\t\t\t\t? device.createBindGroupLayout({ entries: computeStorageBufferLayoutEntries })\n\t\t\t\t\t: null;\n\n\t\t\tconst storageTextureBGLEntries: GPUBindGroupLayoutEntry[] = isPingPongPipeline\n\t\t\t\t? [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbinding: 0,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\t\ttexture: {\n\t\t\t\t\t\t\t\tsampleType: toGpuTextureSampleType(\n\t\t\t\t\t\t\t\t\tstorageTextureSampleScalarType(buildOptions.pingPongFormat!)\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tviewDimension: '2d',\n\t\t\t\t\t\t\t\tmultisampled: false\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tbinding: 1,\n\t\t\t\t\t\t\tvisibility: GPUShaderStage.COMPUTE,\n\t\t\t\t\t\t\tstorageTexture: {\n\t\t\t\t\t\t\t\taccess: 'write-only' as GPUStorageTextureAccess,\n\t\t\t\t\t\t\t\tformat: buildOptions.pingPongFormat!,\n\t\t\t\t\t\t\t\tviewDimension: '2d'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t: computeStorageTextureLayoutEntries;\n\t\t\tconst storageTextureBGL =\n\t\t\t\tstorageTextureBGLEntries.length > 0\n\t\t\t\t\t? device.createBindGroupLayout({ entries: storageTextureBGLEntries })\n\t\t\t\t\t: null;\n\n\t\t\t// Bind group layout indices must match shader @group() indices:\n\t\t\t// group(0) = uniforms, group(1) = storage buffers, group(2) = storage textures.\n\t\t\t// When a group is unused, insert an empty placeholder to keep indices aligned.\n\t\t\tconst bindGroupLayouts: GPUBindGroupLayout[] = [computeUniformBGL];\n\t\t\tif (storageBGL || storageTextureBGL) {\n\t\t\t\tbindGroupLayouts.push(storageBGL ?? device.createBindGroupLayout({ entries: [] }));\n\t\t\t}\n\t\t\tif (storageTextureBGL) {\n\t\t\t\tbindGroupLayouts.push(storageTextureBGL);\n\t\t\t}\n\n\t\t\tconst computePipelineLayout = device.createPipelineLayout({ bindGroupLayouts });\n\t\t\tlet pipeline: GPUComputePipeline;\n\t\t\ttry {\n\t\t\t\tpipeline = device.createComputePipeline({\n\t\t\t\t\tlayout: computePipelineLayout,\n\t\t\t\t\tcompute: {\n\t\t\t\t\t\tmodule: computeShaderModule,\n\t\t\t\t\t\tentryPoint: 'compute'\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tthrow toComputeCompilationError({\n\t\t\t\t\terror,\n\t\t\t\t\tlineMap: builtComputeShader.lineMap,\n\t\t\t\t\tcomputeSource: buildOptions.computeSource,\n\t\t\t\t\truntimeContext\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Build uniform bind group for compute (group 0)\n\t\t\tconst computeUniformBindGroup = device.createBindGroup({\n\t\t\t\tlayout: computeUniformBGL,\n\t\t\t\tentries: [\n\t\t\t\t\t{ binding: FRAME_BINDING, resource: { buffer: frameBuffer } },\n\t\t\t\t\t{ binding: UNIFORM_BINDING, resource: { buffer: uniformBuffer } }\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tconst entry: ComputePipelineEntry = {\n\t\t\t\tpipeline,\n\t\t\t\tbindGroup: computeUniformBindGroup,\n\t\t\t\tworkgroupSize,\n\t\t\t\tcomputeSource: buildOptions.computeSource\n\t\t\t};\n\t\t\tcomputePipelineCache.set(cacheKey, entry);\n\t\t\treturn entry;\n\t\t};\n\n\t\t// Helper to get the storage bind group for dispatch\n\t\tconst getComputeStorageBindGroup = (): GPUBindGroup | null => {\n\t\t\tif (computeStorageBufferLayoutEntries.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst resources: GPUBuffer[] = storageBufferKeys.map((key) => {\n\t\t\t\tconst buffer = storageBufferMap.get(key);\n\t\t\t\tif (!buffer) {\n\t\t\t\t\tthrow new Error(`Storage buffer \"${key}\" not allocated.`);\n\t\t\t\t}\n\t\t\t\treturn buffer;\n\t\t\t});\n\t\t\tconst storageEntries: GPUBindGroupEntry[] = resources.map((buffer, index) => {\n\t\t\t\treturn { binding: index, resource: { buffer } };\n\t\t\t});\n\t\t\treturn computeStorageBufferBindGroupCache.getOrCreate({\n\t\t\t\ttopologyKey: computeStorageBufferTopologyKey,\n\t\t\t\tlayoutEntries: computeStorageBufferLayoutEntries,\n\t\t\t\tbindGroupEntries: storageEntries,\n\t\t\t\tresourceRefs: resources\n\t\t\t});\n\t\t};\n\n\t\t// Helper to get the storage texture bind group for compute dispatch (group 2)\n\t\tconst getComputeStorageTextureBindGroup = (): GPUBindGroup | null => {\n\t\t\tif (computeStorageTextureLayoutEntries.length === 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst resources: GPUTextureView[] = storageTextureKeys.map((key) => {\n\t\t\t\tconst binding = textureBindingByKey.get(key);\n\t\t\t\tif (!binding || !binding.texture) {\n\t\t\t\t\tthrow new Error(`Storage texture \"${key}\" not allocated.`);\n\t\t\t\t}\n\t\t\t\treturn binding.view;\n\t\t\t});\n\t\t\tconst bgEntries: GPUBindGroupEntry[] = resources.map((view, index) => {\n\t\t\t\treturn { binding: index, resource: view };\n\t\t\t});\n\n\t\t\treturn computeStorageTextureBindGroupCache.getOrCreate({\n\t\t\t\ttopologyKey: computeStorageTextureTopologyKey,\n\t\t\t\tlayoutEntries: computeStorageTextureLayoutEntries,\n\t\t\t\tbindGroupEntries: bgEntries,\n\t\t\t\tresourceRefs: resources\n\t\t\t});\n\t\t};\n\n\t\t// Helper to get ping-pong storage texture bind group for compute dispatch (group 2)\n\t\tconst getPingPongStorageTextureBindGroup = (\n\t\t\ttarget: string,\n\t\t\treadFromA: boolean\n\t\t): GPUBindGroup => {\n\t\t\tconst pair = ensurePingPongTexturePair(target);\n\t\t\tif (readFromA) {\n\t\t\t\tif (!pair.readAWriteBBindGroup) {\n\t\t\t\t\tpair.readAWriteBBindGroup = device.createBindGroup({\n\t\t\t\t\t\tlayout: pair.bindGroupLayout,\n\t\t\t\t\t\tentries: [\n\t\t\t\t\t\t\t{ binding: 0, resource: pair.viewA },\n\t\t\t\t\t\t\t{ binding: 1, resource: pair.viewB }\n\t\t\t\t\t\t]\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn pair.readAWriteBBindGroup;\n\t\t\t}\n\t\t\tif (!pair.readBWriteABindGroup) {\n\t\t\t\tpair.readBWriteABindGroup = device.createBindGroup({\n\t\t\t\t\tlayout: pair.bindGroupLayout,\n\t\t\t\t\tentries: [\n\t\t\t\t\t\t{ binding: 0, resource: pair.viewB },\n\t\t\t\t\t\t{ binding: 1, resource: pair.viewA }\n\t\t\t\t\t]\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn pair.readBWriteABindGroup;\n\t\t};\n\n\t\tconst frameBuffer = device.createBuffer({\n\t\t\tsize: 16,\n\t\t\tusage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n\t\t});\n\t\tregisterInitializationCleanup(() => {\n\t\t\tframeBuffer.destroy();\n\t\t});\n\n\t\tconst uniformBuffer = device.createBuffer({\n\t\t\tsize: options.uniformLayout.byteLength,\n\t\t\tusage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST\n\t\t});\n\t\tregisterInitializationCleanup(() => {\n\t\t\tuniformBuffer.destroy();\n\t\t});\n\t\tconst frameScratch = new Float32Array(4);\n\t\tconst uniformScratch = new Float32Array(options.uniformLayout.byteLength / 4);\n\t\tconst uniformPrevious = new Float32Array(options.uniformLayout.byteLength / 4);\n\t\tlet hasUniformSnapshot = false;\n\n\t\t/**\n\t\t * Rebuilds bind group using current texture views.\n\t\t */\n\t\tconst createBindGroup = (): GPUBindGroup => {\n\t\t\tconst entries: GPUBindGroupEntry[] = [\n\t\t\t\t{ binding: FRAME_BINDING, resource: { buffer: frameBuffer } },\n\t\t\t\t{ binding: UNIFORM_BINDING, resource: { buffer: uniformBuffer } }\n\t\t\t];\n\n\t\t\tfor (const binding of fragmentTextureBindings) {\n\t\t\t\tentries.push({\n\t\t\t\t\tbinding: binding.samplerBinding,\n\t\t\t\t\tresource: binding.sampler\n\t\t\t\t});\n\t\t\t\tentries.push({\n\t\t\t\t\tbinding: binding.textureBinding,\n\t\t\t\t\tresource: binding.view\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn device.createBindGroup({\n\t\t\t\tlayout: bindGroupLayout,\n\t\t\t\tentries\n\t\t\t});\n\t\t};\n\n\t\t/**\n\t\t * Synchronizes one runtime texture binding with incoming texture value.\n\t\t *\n\t\t * @returns `true` when bind group must be rebuilt.\n\t\t */\n\t\tconst updateTextureBinding = (\n\t\t\tbinding: RuntimeTextureBinding,\n\t\t\tvalue: TextureValue,\n\t\t\trenderMode: RenderMode\n\t\t): boolean => {\n\t\t\tconst nextData = toTextureData(value);\n\n\t\t\tif (!nextData) {\n\t\t\t\tif (binding.source === null && binding.texture === null) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tbinding.texture?.destroy();\n\t\t\t\tbinding.texture = null;\n\t\t\t\tbinding.view = binding.fallbackView;\n\t\t\t\tbinding.source = null;\n\t\t\t\tbinding.width = undefined;\n\t\t\t\tbinding.height = undefined;\n\t\t\t\tbinding.lastToken = null;\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst source = nextData.source;\n\t\t\tconst colorSpace = nextData.colorSpace ?? binding.defaultColorSpace;\n\t\t\tconst format = colorSpace === 'linear' ? 'rgba8unorm' : 'rgba8unorm-srgb';\n\t\t\tconst flipY = nextData.flipY ?? binding.defaultFlipY;\n\t\t\tconst premultipliedAlpha = nextData.premultipliedAlpha ?? binding.defaultPremultipliedAlpha;\n\t\t\tconst generateMipmaps = nextData.generateMipmaps ?? binding.defaultGenerateMipmaps;\n\t\t\tconst update = resolveTextureUpdateMode({\n\t\t\t\tsource,\n\t\t\t\t...(nextData.update !== undefined ? { override: nextData.update } : {}),\n\t\t\t\t...(binding.defaultUpdate !== undefined ? { defaultMode: binding.defaultUpdate } : {})\n\t\t\t});\n\t\t\tconst { width, height } = resolveTextureSize(nextData);\n\t\t\tconst mipLevelCount = generateMipmaps ? getTextureMipLevelCount(width, height) : 1;\n\t\t\tconst sourceChanged = binding.source !== source;\n\t\t\tconst tokenChanged = binding.lastToken !== value;\n\t\t\tconst requiresReallocation =\n\t\t\t\tbinding.texture === null ||\n\t\t\t\tbinding.width !== width ||\n\t\t\t\tbinding.height !== height ||\n\t\t\t\tbinding.mipLevelCount !== mipLevelCount ||\n\t\t\t\tbinding.format !== format;\n\n\t\t\tif (!requiresReallocation) {\n\t\t\t\tconst shouldUpload =\n\t\t\t\t\tsourceChanged ||\n\t\t\t\t\tupdate === 'perFrame' ||\n\t\t\t\t\t(update === 'onInvalidate' && (renderMode !== 'always' || tokenChanged));\n\n\t\t\t\tif (shouldUpload && binding.texture) {\n\t\t\t\t\tbinding.flipY = flipY;\n\t\t\t\t\tbinding.generateMipmaps = generateMipmaps;\n\t\t\t\t\tbinding.premultipliedAlpha = premultipliedAlpha;\n\t\t\t\t\tbinding.colorSpace = colorSpace;\n\t\t\t\t\tuploadTexture(device, binding.texture, binding, source, width, height, mipLevelCount);\n\t\t\t\t}\n\n\t\t\t\tbinding.source = source;\n\t\t\t\tbinding.width = width;\n\t\t\t\tbinding.height = height;\n\t\t\t\tbinding.mipLevelCount = mipLevelCount;\n\t\t\t\tbinding.update = update;\n\t\t\t\tbinding.lastToken = value;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tlet textureUsage =\n\t\t\t\tGPUTextureUsage.TEXTURE_BINDING |\n\t\t\t\tGPUTextureUsage.COPY_DST |\n\t\t\t\tGPUTextureUsage.RENDER_ATTACHMENT;\n\t\t\tif (storageTextureKeySet.has(binding.key)) {\n\t\t\t\ttextureUsage |= GPUTextureUsage.STORAGE_BINDING;\n\t\t\t}\n\t\t\tconst texture = device.createTexture({\n\t\t\t\tsize: { width, height, depthOrArrayLayers: 1 },\n\t\t\t\tformat,\n\t\t\t\tmipLevelCount,\n\t\t\t\tusage: textureUsage\n\t\t\t});\n\t\t\tregisterInitializationCleanup(() => {\n\t\t\t\ttexture.destroy();\n\t\t\t});\n\n\t\t\tbinding.flipY = flipY;\n\t\t\tbinding.generateMipmaps = generateMipmaps;\n\t\t\tbinding.premultipliedAlpha = premultipliedAlpha;\n\t\t\tbinding.colorSpace = colorSpace;\n\t\t\tbinding.format = format;\n\t\t\tuploadTexture(device, texture, binding, source, width, height, mipLevelCount);\n\n\t\t\tbinding.texture?.destroy();\n\t\t\tbinding.texture = texture;\n\t\t\tbinding.view = texture.createView();\n\t\t\tbinding.source = source;\n\t\t\tbinding.width = width;\n\t\t\tbinding.height = height;\n\t\t\tbinding.mipLevelCount = mipLevelCount;\n\t\t\tbinding.update = update;\n\t\t\tbinding.lastToken = value;\n\t\t\treturn true;\n\t\t};\n\n\t\tfor (const binding of textureBindings) {\n\t\t\t// Skip storage textures — they are eagerly allocated and not source-driven\n\t\t\tif (storageTextureKeySet.has(binding.key)) continue;\n\t\t\tconst defaultSource = normalizedTextureDefinitions[binding.key]?.source ?? null;\n\t\t\tupdateTextureBinding(binding, defaultSource, 'always');\n\t\t}\n\n\t\tlet bindGroup = createBindGroup();\n\t\tlet sourceSlotTarget: RuntimeRenderTarget | null = null;\n\t\tlet targetSlotTarget: RuntimeRenderTarget | null = null;\n\t\tlet renderTargetSignature = '';\n\t\tlet renderTargetSnapshot: Readonly<Record<string, RenderTarget>> = {};\n\t\tlet renderTargetKeys: string[] = [];\n\t\tlet cachedGraphPlan: RenderGraphPlan | null = null;\n\t\tlet cachedGraphRenderTargetSignature = '';\n\t\tconst cachedGraphClearColor: [number, number, number, number] = [NaN, NaN, NaN, NaN];\n\t\tconst cachedGraphPasses: RenderGraphPassSnapshot[] = [];\n\t\tlet contextConfigured = false;\n\t\tlet configuredWidth = 0;\n\t\tlet configuredHeight = 0;\n\t\tconst runtimeRenderTargets = new Map<string, RuntimeRenderTarget>();\n\t\tconst activePasses: AnyPass[] = [];\n\t\tconst lifecyclePreviousSet = new Set<AnyPass>();\n\t\tconst lifecycleNextSet = new Set<AnyPass>();\n\t\tconst lifecycleUniquePasses: AnyPass[] = [];\n\t\tlet lifecyclePassesRef: AnyPass[] | null = null;\n\t\tlet passWidth = 0;\n\t\tlet passHeight = 0;\n\n\t\t/**\n\t\t * Resolves active render pass list for current frame.\n\t\t */\n\t\tconst resolvePasses = (): AnyPass[] => {\n\t\t\treturn options.getPasses?.() ?? options.passes ?? [];\n\t\t};\n\n\t\t/**\n\t\t * Resolves active render target declarations for current frame.\n\t\t */\n\t\tconst resolveRenderTargets = () => {\n\t\t\treturn options.getRenderTargets?.() ?? options.renderTargets;\n\t\t};\n\n\t\t/**\n\t\t * Checks whether cached render-graph plan can be reused for this frame.\n\t\t */\n\t\tconst isGraphPlanCacheValid = (\n\t\t\tpasses: AnyPass[],\n\t\t\tclearColor: [number, number, number, number]\n\t\t): boolean => {\n\t\t\tif (!cachedGraphPlan) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (cachedGraphRenderTargetSignature !== renderTargetSignature) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tcachedGraphClearColor[0] !== clearColor[0] ||\n\t\t\t\tcachedGraphClearColor[1] !== clearColor[1] ||\n\t\t\t\tcachedGraphClearColor[2] !== clearColor[2] ||\n\t\t\t\tcachedGraphClearColor[3] !== clearColor[3]\n\t\t\t) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif (cachedGraphPasses.length !== passes.length) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor (let index = 0; index < passes.length; index += 1) {\n\t\t\t\tconst pass = passes[index];\n\t\t\t\tconst rp = pass as Partial<RenderPass>;\n\t\t\t\tconst snapshot = cachedGraphPasses[index];\n\t\t\t\tif (!pass || !snapshot || snapshot.pass !== pass) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tsnapshot.enabled !== pass.enabled ||\n\t\t\t\t\tsnapshot.needsSwap !== rp.needsSwap ||\n\t\t\t\t\tsnapshot.input !== rp.input ||\n\t\t\t\t\tsnapshot.output !== rp.output ||\n\t\t\t\t\tsnapshot.clear !== rp.clear ||\n\t\t\t\t\tsnapshot.preserve !== rp.preserve\n\t\t\t\t) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tconst passClearColor = rp.clearColor;\n\t\t\t\tconst hasPassClearColor = passClearColor !== undefined;\n\t\t\t\tif (snapshot.hasClearColor !== hasPassClearColor) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif (passClearColor) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tsnapshot.clearColor0 !== passClearColor[0] ||\n\t\t\t\t\t\tsnapshot.clearColor1 !== passClearColor[1] ||\n\t\t\t\t\t\tsnapshot.clearColor2 !== passClearColor[2] ||\n\t\t\t\t\t\tsnapshot.clearColor3 !== passClearColor[3]\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t};\n\n\t\t/**\n\t\t * Updates render-graph cache with current pass set.\n\t\t */\n\t\tconst updateGraphPlanCache = (\n\t\t\tpasses: AnyPass[],\n\t\t\tclearColor: [number, number, number, number],\n\t\t\tgraphPlan: RenderGraphPlan\n\t\t): void => {\n\t\t\tcachedGraphPlan = graphPlan;\n\t\t\tcachedGraphRenderTargetSignature = renderTargetSignature;\n\t\t\tcachedGraphClearColor[0] = clearColor[0];\n\t\t\tcachedGraphClearColor[1] = clearColor[1];\n\t\t\tcachedGraphClearColor[2] = clearColor[2];\n\t\t\tcachedGraphClearColor[3] = clearColor[3];\n\t\t\tcachedGraphPasses.length = passes.length;\n\n\t\t\tlet index = 0;\n\t\t\tfor (const pass of passes) {\n\t\t\t\tconst rp = pass as Partial<RenderPass>;\n\t\t\t\tconst passClearColor = rp.clearColor;\n\t\t\t\tconst hasPassClearColor = passClearColor !== undefined;\n\t\t\t\tconst snapshot = cachedGraphPasses[index];\n\t\t\t\tif (!snapshot) {\n\t\t\t\t\tcachedGraphPasses[index] = {\n\t\t\t\t\t\tpass,\n\t\t\t\t\t\tenabled: pass.enabled,\n\t\t\t\t\t\tneedsSwap: rp.needsSwap,\n\t\t\t\t\t\tinput: rp.input,\n\t\t\t\t\t\toutput: rp.output,\n\t\t\t\t\t\tclear: rp.clear,\n\t\t\t\t\t\tpreserve: rp.preserve,\n\t\t\t\t\t\thasClearColor: hasPassClearColor,\n\t\t\t\t\t\tclearColor0: passClearColor?.[0] ?? 0,\n\t\t\t\t\t\tclearColor1: passClearColor?.[1] ?? 0,\n\t\t\t\t\t\tclearColor2: passClearColor?.[2] ?? 0,\n\t\t\t\t\t\tclearColor3: passClearColor?.[3] ?? 0\n\t\t\t\t\t};\n\t\t\t\t\tindex += 1;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tsnapshot.pass = pass;\n\t\t\t\tsnapshot.enabled = pass.enabled;\n\t\t\t\tsnapshot.needsSwap = rp.needsSwap;\n\t\t\t\tsnapshot.input = rp.input;\n\t\t\t\tsnapshot.output = rp.output;\n\t\t\t\tsnapshot.clear = rp.clear;\n\t\t\t\tsnapshot.preserve = rp.preserve;\n\t\t\t\tsnapshot.hasClearColor = hasPassClearColor;\n\t\t\t\tsnapshot.clearColor0 = passClearColor?.[0] ?? 0;\n\t\t\t\tsnapshot.clearColor1 = passClearColor?.[1] ?? 0;\n\t\t\t\tsnapshot.clearColor2 = passClearColor?.[2] ?? 0;\n\t\t\t\tsnapshot.clearColor3 = passClearColor?.[3] ?? 0;\n\t\t\t\tindex += 1;\n\t\t\t}\n\t\t};\n\n\t\t/**\n\t\t * Synchronizes pass lifecycle callbacks and resize notifications.\n\t\t */\n\t\tconst syncPassLifecycle = (passes: AnyPass[], width: number, height: number): void => {\n\t\t\tconst resized = passWidth !== width || passHeight !== height;\n\t\t\tif (!resized && lifecyclePassesRef === passes && passes.length === activePasses.length) {\n\t\t\t\tlet isSameOrder = true;\n\t\t\t\tfor (let index = 0; index < passes.length; index += 1) {\n\t\t\t\t\tif (activePasses[index] !== passes[index]) {\n\t\t\t\t\t\tisSameOrder = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (isSameOrder) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlifecycleNextSet.clear();\n\t\t\tlifecycleUniquePasses.length = 0;\n\t\t\tfor (const pass of passes) {\n\t\t\t\tif (lifecycleNextSet.has(pass)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlifecycleNextSet.add(pass);\n\t\t\t\tlifecycleUniquePasses.push(pass);\n\t\t\t}\n\t\t\tlifecyclePreviousSet.clear();\n\t\t\tfor (const pass of activePasses) {\n\t\t\t\tlifecyclePreviousSet.add(pass);\n\t\t\t}\n\n\t\t\tfor (const pass of activePasses) {\n\t\t\t\tif (!lifecycleNextSet.has(pass)) {\n\t\t\t\t\tpass.dispose?.();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor (const pass of lifecycleUniquePasses) {\n\t\t\t\tif (resized || !lifecyclePreviousSet.has(pass)) {\n\t\t\t\t\tpass.setSize?.(width, height);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tactivePasses.length = 0;\n\t\t\tfor (const pass of lifecycleUniquePasses) {\n\t\t\t\tactivePasses.push(pass);\n\t\t\t}\n\t\t\tlifecyclePassesRef = passes;\n\t\t\tpassWidth = width;\n\t\t\tpassHeight = height;\n\t\t};\n\n\t\t/**\n\t\t * Ensures internal ping-pong slot texture matches current canvas size/format.\n\t\t */\n\t\tconst ensureSlotTarget = (\n\t\t\tslot: RenderPassInputSlot,\n\t\t\twidth: number,\n\t\t\theight: number\n\t\t): RuntimeRenderTarget => {\n\t\t\tconst current = slot === 'source' ? sourceSlotTarget : targetSlotTarget;\n\t\t\tif (\n\t\t\t\tcurrent &&\n\t\t\t\tcurrent.width === width &&\n\t\t\t\tcurrent.height === height &&\n\t\t\t\tcurrent.format === format\n\t\t\t) {\n\t\t\t\treturn current;\n\t\t\t}\n\n\t\t\tdestroyRenderTexture(current);\n\t\t\tconst next = createRenderTexture(device, width, height, format);\n\t\t\tif (slot === 'source') {\n\t\t\t\tsourceSlotTarget = next;\n\t\t\t} else {\n\t\t\t\ttargetSlotTarget = next;\n\t\t\t}\n\n\t\t\treturn next;\n\t\t};\n\n\t\t/**\n\t\t * Creates/updates runtime render targets and returns immutable pass snapshot.\n\t\t */\n\t\tconst syncRenderTargets = (\n\t\t\tcanvasWidth: number,\n\t\t\tcanvasHeight: number\n\t\t): Readonly<Record<string, RenderTarget>> => {\n\t\t\tconst resolvedDefinitions = resolveRenderTargetDefinitions(\n\t\t\t\tresolveRenderTargets(),\n\t\t\t\tcanvasWidth,\n\t\t\t\tcanvasHeight,\n\t\t\t\tformat\n\t\t\t);\n\t\t\tconst nextSignature = buildRenderTargetSignature(resolvedDefinitions);\n\n\t\t\tif (nextSignature !== renderTargetSignature) {\n\t\t\t\tconst activeKeys = new Set(resolvedDefinitions.map((definition) => definition.key));\n\n\t\t\t\tfor (const [key, target] of runtimeRenderTargets.entries()) {\n\t\t\t\t\tif (!activeKeys.has(key)) {\n\t\t\t\t\t\ttarget.texture.destroy();\n\t\t\t\t\t\truntimeRenderTargets.delete(key);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const definition of resolvedDefinitions) {\n\t\t\t\t\tconst current = runtimeRenderTargets.get(definition.key);\n\t\t\t\t\tif (\n\t\t\t\t\t\tcurrent &&\n\t\t\t\t\t\tcurrent.width === definition.width &&\n\t\t\t\t\t\tcurrent.height === definition.height &&\n\t\t\t\t\t\tcurrent.format === definition.format\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcurrent?.texture.destroy();\n\t\t\t\t\truntimeRenderTargets.set(\n\t\t\t\t\t\tdefinition.key,\n\t\t\t\t\t\tcreateRenderTexture(device, definition.width, definition.height, definition.format)\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\trenderTargetSignature = nextSignature;\n\t\t\t\tconst nextSnapshot: Record<string, RenderTarget> = {};\n\t\t\t\tconst nextKeys: string[] = [];\n\t\t\t\tfor (const definition of resolvedDefinitions) {\n\t\t\t\t\tconst target = runtimeRenderTargets.get(definition.key);\n\t\t\t\t\tif (!target) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tnextKeys.push(definition.key);\n\t\t\t\t\tnextSnapshot[definition.key] = {\n\t\t\t\t\t\ttexture: target.texture,\n\t\t\t\t\t\tview: target.view,\n\t\t\t\t\t\twidth: target.width,\n\t\t\t\t\t\theight: target.height,\n\t\t\t\t\t\tformat: target.format\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\trenderTargetSnapshot = nextSnapshot;\n\t\t\t\trenderTargetKeys = nextKeys;\n\t\t\t}\n\n\t\t\treturn renderTargetSnapshot;\n\t\t};\n\n\t\t/**\n\t\t * Blits a texture view to the current canvas texture.\n\t\t */\n\t\tconst blitToCanvas = (\n\t\t\tcommandEncoder: GPUCommandEncoder,\n\t\t\tsourceView: GPUTextureView,\n\t\t\tcanvasView: GPUTextureView,\n\t\t\tclearColor: [number, number, number, number]\n\t\t): void => {\n\t\t\tlet bindGroup = blitBindGroupByView.get(sourceView);\n\t\t\tif (!bindGroup) {\n\t\t\t\tbindGroup = device.createBindGroup({\n\t\t\t\t\tlayout: blitBindGroupLayout,\n\t\t\t\t\tentries: [\n\t\t\t\t\t\t{ binding: 0, resource: blitSampler },\n\t\t\t\t\t\t{ binding: 1, resource: sourceView }\n\t\t\t\t\t]\n\t\t\t\t});\n\t\t\t\tblitBindGroupByView.set(sourceView, bindGroup);\n\t\t\t}\n\n\t\t\tconst pass = commandEncoder.beginRenderPass({\n\t\t\t\tcolorAttachments: [\n\t\t\t\t\t{\n\t\t\t\t\t\tview: canvasView,\n\t\t\t\t\t\tclearValue: {\n\t\t\t\t\t\t\tr: clearColor[0],\n\t\t\t\t\t\t\tg: clearColor[1],\n\t\t\t\t\t\t\tb: clearColor[2],\n\t\t\t\t\t\t\ta: clearColor[3]\n\t\t\t\t\t\t},\n\t\t\t\t\t\tloadOp: 'clear',\n\t\t\t\t\t\tstoreOp: 'store'\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tpass.setPipeline(blitPipeline);\n\t\t\tpass.setBindGroup(0, bindGroup);\n\t\t\tpass.draw(3);\n\t\t\tpass.end();\n\t\t};\n\n\t\t/**\n\t\t * Executes a full frame render.\n\t\t */\n\t\tconst render: Renderer['render'] = ({\n\t\t\ttime,\n\t\t\tdelta,\n\t\t\trenderMode,\n\t\t\tuniforms,\n\t\t\ttextures,\n\t\t\tcanvasSize,\n\t\t\tpendingStorageWrites\n\t\t}) => {\n\t\t\tif (deviceLostMessage) {\n\t\t\t\tthrow new Error(deviceLostMessage);\n\t\t\t}\n\n\t\t\tif (uncapturedErrorMessage) {\n\t\t\t\tconst message = uncapturedErrorMessage;\n\t\t\t\tuncapturedErrorMessage = null;\n\t\t\t\tthrow new Error(message);\n\t\t\t}\n\n\t\t\tconst { width, height } = resizeCanvas(options.canvas, options.getDpr(), canvasSize);\n\n\t\t\tif (!contextConfigured || configuredWidth !== width || configuredHeight !== height) {\n\t\t\t\tcontext.configure({\n\t\t\t\t\tdevice,\n\t\t\t\t\tformat,\n\t\t\t\t\talphaMode: 'premultiplied'\n\t\t\t\t});\n\t\t\t\tcontextConfigured = true;\n\t\t\t\tconfiguredWidth = width;\n\t\t\t\tconfiguredHeight = height;\n\t\t\t}\n\n\t\t\tframeScratch[0] = time;\n\t\t\tframeScratch[1] = delta;\n\t\t\tframeScratch[2] = width;\n\t\t\tframeScratch[3] = height;\n\t\t\tdevice.queue.writeBuffer(\n\t\t\t\tframeBuffer,\n\t\t\t\t0,\n\t\t\t\tframeScratch.buffer as ArrayBuffer,\n\t\t\t\tframeScratch.byteOffset,\n\t\t\t\tframeScratch.byteLength\n\t\t\t);\n\n\t\t\tpackUniformsInto(uniforms, options.uniformLayout, uniformScratch);\n\t\t\tif (!hasUniformSnapshot) {\n\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\tuniformBuffer,\n\t\t\t\t\t0,\n\t\t\t\t\tuniformScratch.buffer as ArrayBuffer,\n\t\t\t\t\tuniformScratch.byteOffset,\n\t\t\t\t\tuniformScratch.byteLength\n\t\t\t\t);\n\t\t\t\tuniformPrevious.set(uniformScratch);\n\t\t\t\thasUniformSnapshot = true;\n\t\t\t} else {\n\t\t\t\tconst dirtyRanges = findDirtyFloatRanges(uniformPrevious, uniformScratch);\n\t\t\t\tfor (const range of dirtyRanges) {\n\t\t\t\t\tconst byteOffset = range.start * 4;\n\t\t\t\t\tconst byteLength = range.count * 4;\n\t\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\t\tuniformBuffer,\n\t\t\t\t\t\tbyteOffset,\n\t\t\t\t\t\tuniformScratch.buffer as ArrayBuffer,\n\t\t\t\t\t\tuniformScratch.byteOffset + byteOffset,\n\t\t\t\t\t\tbyteLength\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (dirtyRanges.length > 0) {\n\t\t\t\t\tuniformPrevious.set(uniformScratch);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlet bindGroupDirty = false;\n\t\t\tfor (const binding of textureBindings) {\n\t\t\t\t// Storage textures are managed by compute passes, skip source-driven updates\n\t\t\t\tif (storageTextureKeySet.has(binding.key)) continue;\n\t\t\t\tconst nextTexture =\n\t\t\t\t\ttextures[binding.key] ?? normalizedTextureDefinitions[binding.key]?.source ?? null;\n\t\t\t\tif (updateTextureBinding(binding, nextTexture, renderMode) && binding.fragmentVisible) {\n\t\t\t\t\tbindGroupDirty = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (bindGroupDirty) {\n\t\t\t\tbindGroup = createBindGroup();\n\t\t\t}\n\n\t\t\t// Apply pending storage buffer writes\n\t\t\tif (pendingStorageWrites) {\n\t\t\t\tfor (const write of pendingStorageWrites) {\n\t\t\t\t\tconst buffer = storageBufferMap.get(write.name);\n\t\t\t\t\tif (buffer) {\n\t\t\t\t\t\tconst data = write.data;\n\t\t\t\t\t\tdevice.queue.writeBuffer(\n\t\t\t\t\t\t\tbuffer,\n\t\t\t\t\t\t\twrite.offset,\n\t\t\t\t\t\t\tdata.buffer as ArrayBuffer,\n\t\t\t\t\t\t\tdata.byteOffset,\n\t\t\t\t\t\t\tdata.byteLength\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst commandEncoder = device.createCommandEncoder();\n\t\t\tconst passes = resolvePasses();\n\t\t\tconst clearColor = options.getClearColor();\n\t\t\tsyncPassLifecycle(passes, width, height);\n\t\t\tconst runtimeTargets = syncRenderTargets(width, height);\n\t\t\tconst graphPlan = isGraphPlanCacheValid(passes, clearColor)\n\t\t\t\t? cachedGraphPlan!\n\t\t\t\t: (() => {\n\t\t\t\t\t\tconst nextPlan = planRenderGraph(passes, clearColor, renderTargetKeys);\n\t\t\t\t\t\tupdateGraphPlanCache(passes, clearColor, nextPlan);\n\t\t\t\t\t\treturn nextPlan;\n\t\t\t\t\t})();\n\t\t\tconst canvasTexture = context.getCurrentTexture();\n\t\t\tconst canvasSurface: RenderTarget = {\n\t\t\t\ttexture: canvasTexture,\n\t\t\t\tview: canvasTexture.createView(),\n\t\t\t\twidth,\n\t\t\t\theight,\n\t\t\t\tformat\n\t\t\t};\n\t\t\tconst slots =\n\t\t\t\tgraphPlan.steps.length > 0\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tsource: ensureSlotTarget('source', width, height),\n\t\t\t\t\t\t\ttarget: ensureSlotTarget('target', width, height),\n\t\t\t\t\t\t\tcanvas: canvasSurface\n\t\t\t\t\t\t}\n\t\t\t\t\t: null;\n\t\t\tconst sceneOutput = slots ? slots.source : canvasSurface;\n\n\t\t\t// Dispatch compute passes BEFORE scene render so storage textures\n\t\t\t// and buffers are up-to-date when the fragment shader samples them.\n\t\t\tif (slots) {\n\t\t\t\tfor (const step of graphPlan.steps) {\n\t\t\t\t\tif (step.kind !== 'compute') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst computePass = step.pass as {\n\t\t\t\t\t\tisCompute?: boolean;\n\t\t\t\t\t\tgetCompute?: () => string;\n\t\t\t\t\t\tresolveDispatch?: (ctx: {\n\t\t\t\t\t\t\twidth: number;\n\t\t\t\t\t\t\theight: number;\n\t\t\t\t\t\t\ttime: number;\n\t\t\t\t\t\t\tdelta: number;\n\t\t\t\t\t\t\tworkgroupSize: [number, number, number];\n\t\t\t\t\t\t}) => [number, number, number];\n\t\t\t\t\t\tgetWorkgroupSize?: () => [number, number, number];\n\t\t\t\t\t\tisPingPong?: boolean;\n\t\t\t\t\t\tgetTarget?: () => string;\n\t\t\t\t\t\tgetCurrentOutput?: () => string;\n\t\t\t\t\t\tgetIterations?: () => number;\n\t\t\t\t\t\tadvanceFrame?: () => void;\n\t\t\t\t\t};\n\t\t\t\t\tif (\n\t\t\t\t\t\tcomputePass.getCompute &&\n\t\t\t\t\t\tcomputePass.resolveDispatch &&\n\t\t\t\t\t\tcomputePass.getWorkgroupSize\n\t\t\t\t\t) {\n\t\t\t\t\t\tconst computeSource = computePass.getCompute();\n\t\t\t\t\t\tconst pingPongTarget =\n\t\t\t\t\t\t\tcomputePass.isPingPong && computePass.getTarget ? computePass.getTarget() : undefined;\n\t\t\t\t\t\tif (computePass.isPingPong && !pingPongTarget) {\n\t\t\t\t\t\t\tthrow new Error('PingPongComputePass must provide a target texture key.');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst pingPongPair = pingPongTarget ? ensurePingPongTexturePair(pingPongTarget) : null;\n\t\t\t\t\t\tconst pipelineEntry = buildComputePipelineEntry({\n\t\t\t\t\t\t\tcomputeSource,\n\t\t\t\t\t\t\t...(pingPongPair\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\tpingPongTarget: pingPongPair.target,\n\t\t\t\t\t\t\t\t\t\tpingPongFormat: pingPongPair.format\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: {})\n\t\t\t\t\t\t});\n\t\t\t\t\t\tconst workgroupSize = computePass.getWorkgroupSize();\n\t\t\t\t\t\tconst storageBindGroup = getComputeStorageBindGroup();\n\t\t\t\t\t\tconst storageTextureBindGroup = getComputeStorageTextureBindGroup();\n\t\t\t\t\t\tconst iterations =\n\t\t\t\t\t\t\tcomputePass.isPingPong && computePass.getIterations ? computePass.getIterations() : 1;\n\t\t\t\t\t\tconst currentOutput =\n\t\t\t\t\t\t\tcomputePass.isPingPong && computePass.getCurrentOutput\n\t\t\t\t\t\t\t\t? computePass.getCurrentOutput()\n\t\t\t\t\t\t\t\t: null;\n\t\t\t\t\t\tconst readFromAAtIterationZero =\n\t\t\t\t\t\t\tpingPongPair && currentOutput ? currentOutput !== `${pingPongPair.target}B` : true;\n\n\t\t\t\t\t\tfor (let iter = 0; iter < iterations; iter += 1) {\n\t\t\t\t\t\t\tconst dispatch = computePass.resolveDispatch({\n\t\t\t\t\t\t\t\twidth,\n\t\t\t\t\t\t\t\theight,\n\t\t\t\t\t\t\t\ttime,\n\t\t\t\t\t\t\t\tdelta,\n\t\t\t\t\t\t\t\tworkgroupSize\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tconst cPass = commandEncoder.beginComputePass();\n\t\t\t\t\t\t\tcPass.setPipeline(pipelineEntry.pipeline);\n\t\t\t\t\t\t\tcPass.setBindGroup(0, pipelineEntry.bindGroup);\n\t\t\t\t\t\t\tif (storageBindGroup) {\n\t\t\t\t\t\t\t\tcPass.setBindGroup(1, storageBindGroup);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (pingPongPair) {\n\t\t\t\t\t\t\t\tconst readFromA =\n\t\t\t\t\t\t\t\t\titer % 2 === 0 ? readFromAAtIterationZero : !readFromAAtIterationZero;\n\t\t\t\t\t\t\t\tcPass.setBindGroup(\n\t\t\t\t\t\t\t\t\t2,\n\t\t\t\t\t\t\t\t\tgetPingPongStorageTextureBindGroup(pingPongPair.target, readFromA)\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else if (storageTextureBindGroup) {\n\t\t\t\t\t\t\t\tcPass.setBindGroup(2, storageTextureBindGroup);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcPass.dispatchWorkgroups(dispatch[0], dispatch[1], dispatch[2]);\n\t\t\t\t\t\t\tcPass.end();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (computePass.isPingPong && computePass.advanceFrame) {\n\t\t\t\t\t\t\tcomputePass.advanceFrame();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst scenePass = commandEncoder.beginRenderPass({\n\t\t\t\tcolorAttachments: [\n\t\t\t\t\t{\n\t\t\t\t\t\tview: sceneOutput.view,\n\t\t\t\t\t\tclearValue: {\n\t\t\t\t\t\t\tr: clearColor[0],\n\t\t\t\t\t\t\tg: clearColor[1],\n\t\t\t\t\t\t\tb: clearColor[2],\n\t\t\t\t\t\t\ta: clearColor[3]\n\t\t\t\t\t\t},\n\t\t\t\t\t\tloadOp: 'clear',\n\t\t\t\t\t\tstoreOp: 'store'\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t});\n\n\t\t\tscenePass.setPipeline(pipeline);\n\t\t\tscenePass.setBindGroup(0, bindGroup);\n\t\t\tif (fragmentStorageBindGroup) {\n\t\t\t\tscenePass.setBindGroup(1, fragmentStorageBindGroup);\n\t\t\t}\n\t\t\tscenePass.draw(3);\n\t\t\tscenePass.end();\n\n\t\t\tif (slots) {\n\t\t\t\tconst resolveStepSurface = (\n\t\t\t\t\tslot: RenderPassInputSlot | RenderPassOutputSlot\n\t\t\t\t): RenderTarget => {\n\t\t\t\t\tif (slot === 'source') {\n\t\t\t\t\t\treturn slots.source;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (slot === 'target') {\n\t\t\t\t\t\treturn slots.target;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (slot === 'canvas') {\n\t\t\t\t\t\treturn slots.canvas;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst named = runtimeTargets[slot];\n\t\t\t\t\tif (!named) {\n\t\t\t\t\t\tthrow new Error(`Render graph references unknown runtime target \"${slot}\".`);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn named;\n\t\t\t\t};\n\n\t\t\t\tfor (const step of graphPlan.steps) {\n\t\t\t\t\t// Compute passes already dispatched above\n\t\t\t\t\tif (step.kind === 'compute') {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst input = resolveStepSurface(step.input);\n\t\t\t\t\tconst output = resolveStepSurface(step.output);\n\n\t\t\t\t\t(step.pass as RenderPass).render({\n\t\t\t\t\t\tdevice,\n\t\t\t\t\t\tcommandEncoder,\n\t\t\t\t\t\tsource: slots.source,\n\t\t\t\t\t\ttarget: slots.target,\n\t\t\t\t\t\tcanvas: slots.canvas,\n\t\t\t\t\t\tinput,\n\t\t\t\t\t\toutput,\n\t\t\t\t\t\ttargets: runtimeTargets,\n\t\t\t\t\t\ttime,\n\t\t\t\t\t\tdelta,\n\t\t\t\t\t\twidth,\n\t\t\t\t\t\theight,\n\t\t\t\t\t\tclear: step.clear,\n\t\t\t\t\t\tclearColor: step.clearColor,\n\t\t\t\t\t\tpreserve: step.preserve,\n\t\t\t\t\t\tbeginRenderPass: (passOptions?: {\n\t\t\t\t\t\t\tclear?: boolean;\n\t\t\t\t\t\t\tclearColor?: [number, number, number, number];\n\t\t\t\t\t\t\tpreserve?: boolean;\n\t\t\t\t\t\t\tview?: GPUTextureView;\n\t\t\t\t\t\t}) => {\n\t\t\t\t\t\t\tconst clear = passOptions?.clear ?? step.clear;\n\t\t\t\t\t\t\tconst clearColor = passOptions?.clearColor ?? step.clearColor;\n\t\t\t\t\t\t\tconst preserve = passOptions?.preserve ?? step.preserve;\n\n\t\t\t\t\t\t\treturn commandEncoder.beginRenderPass({\n\t\t\t\t\t\t\t\tcolorAttachments: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tview: passOptions?.view ?? output.view,\n\t\t\t\t\t\t\t\t\t\tclearValue: {\n\t\t\t\t\t\t\t\t\t\t\tr: clearColor[0],\n\t\t\t\t\t\t\t\t\t\t\tg: clearColor[1],\n\t\t\t\t\t\t\t\t\t\t\tb: clearColor[2],\n\t\t\t\t\t\t\t\t\t\t\ta: clearColor[3]\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\tloadOp: clear ? 'clear' : 'load',\n\t\t\t\t\t\t\t\t\t\tstoreOp: preserve ? 'store' : 'discard'\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\tif (step.needsSwap) {\n\t\t\t\t\t\tconst previousSource = slots.source;\n\t\t\t\t\t\tslots.source = slots.target;\n\t\t\t\t\t\tslots.target = previousSource;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (graphPlan.finalOutput !== 'canvas') {\n\t\t\t\t\tconst finalSurface = resolveStepSurface(graphPlan.finalOutput);\n\t\t\t\t\tblitToCanvas(commandEncoder, finalSurface.view, slots.canvas.view, clearColor);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdevice.queue.submit([commandEncoder.finish()]);\n\t\t};\n\n\t\tacceptInitializationCleanups = false;\n\t\tinitializationCleanups.length = 0;\n\t\treturn {\n\t\t\trender,\n\t\t\tgetStorageBuffer: (name: string): GPUBuffer | undefined => {\n\t\t\t\treturn storageBufferMap.get(name);\n\t\t\t},\n\t\t\tgetDevice: (): GPUDevice => {\n\t\t\t\treturn device;\n\t\t\t},\n\t\t\tdestroy: () => {\n\t\t\t\tisDestroyed = true;\n\t\t\t\tdevice.removeEventListener('uncapturederror', handleUncapturedError);\n\t\t\t\tframeBuffer.destroy();\n\t\t\t\tuniformBuffer.destroy();\n\t\t\t\tfor (const buffer of storageBufferMap.values()) {\n\t\t\t\t\tbuffer.destroy();\n\t\t\t\t}\n\t\t\t\tstorageBufferMap.clear();\n\t\t\t\tfor (const pair of pingPongTexturePairs.values()) {\n\t\t\t\t\tpair.textureA.destroy();\n\t\t\t\t\tpair.textureB.destroy();\n\t\t\t\t}\n\t\t\t\tpingPongTexturePairs.clear();\n\t\t\t\tcomputePipelineCache.clear();\n\t\t\t\tdestroyRenderTexture(sourceSlotTarget);\n\t\t\t\tdestroyRenderTexture(targetSlotTarget);\n\t\t\t\tfor (const target of runtimeRenderTargets.values()) {\n\t\t\t\t\ttarget.texture.destroy();\n\t\t\t\t}\n\t\t\t\truntimeRenderTargets.clear();\n\t\t\t\tfor (const pass of activePasses) {\n\t\t\t\t\tpass.dispose?.();\n\t\t\t\t}\n\t\t\t\tactivePasses.length = 0;\n\t\t\t\tlifecyclePassesRef = null;\n\t\t\t\tfor (const binding of textureBindings) {\n\t\t\t\t\tbinding.texture?.destroy();\n\t\t\t\t\tbinding.fallbackTexture.destroy();\n\t\t\t\t}\n\t\t\t\tblitBindGroupByView = new WeakMap();\n\t\t\t\tcachedGraphPlan = null;\n\t\t\t\tcachedGraphPasses.length = 0;\n\t\t\t\trenderTargetSnapshot = {};\n\t\t\t\trenderTargetKeys = [];\n\t\t\t}\n\t\t};\n\t} catch (error) {\n\t\tisDestroyed = true;\n\t\tacceptInitializationCleanups = false;\n\t\tdevice.removeEventListener('uncapturederror', handleUncapturedError);\n\t\trunInitializationCleanups();\n\t\tthrow error;\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"runtime-loop.d.ts","sourceRoot":"","sources":["../../src/lib/core/runtime-loop.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAmB,KAAK,YAAY,EAAyB,MAAM,eAAe,CAAC;AAC1F,OAAO,EAGN,KAAK,oBAAoB,EACzB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACX,OAAO,EACP,sBAAsB,EACtB,gBAAgB,EAGhB,yBAAyB,EAMzB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,eAAe,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,YAAY,CAAC;IAChC,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;IAClD,SAAS,EAAE,MAAM,OAAO,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;IAC5C,iBAAiB,EAAE,MAAM,wBAAwB,GAAG,SAAS,CAAC;IAC9D,mBAAmB,EAAE,MAAM,mBAAmB,GAAG,SAAS,CAAC;IAC3D,UAAU,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACvE,WAAW,EAAE,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,oBAAoB,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAClF,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC;CAC/D;AAED,MAAM,WAAW,oBAAoB;IACpC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB;AAMD,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,2BAA2B,GAClC,oBAAoB,CA8dtB"}
1
+ {"version":3,"file":"runtime-loop.d.ts","sourceRoot":"","sources":["../../src/lib/core/runtime-loop.ts"],"names":[],"mappings":";AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAmB,KAAK,YAAY,EAAyB,MAAM,eAAe,CAAC;AAC1F,OAAO,EAGN,KAAK,oBAAoB,EACzB,MAAM,mBAAmB,CAAC;AAI3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EACX,OAAO,EACP,sBAAsB,EACtB,gBAAgB,EAGhB,yBAAyB,EAMzB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,2BAA2B;IAC3C,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,IAAI,EAAE,eAAe,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;IAClC,WAAW,EAAE,MAAM,YAAY,CAAC;IAChC,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;IAClD,SAAS,EAAE,MAAM,OAAO,EAAE,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;IAC5C,iBAAiB,EAAE,MAAM,wBAAwB,GAAG,SAAS,CAAC;IAC9D,mBAAmB,EAAE,MAAM,mBAAmB,GAAG,SAAS,CAAC;IAC3D,UAAU,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACvE,WAAW,EAAE,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,oBAAoB,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;IAChD,iBAAiB,CAAC,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IAClF,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,oBAAoB,EAAE,KAAK,IAAI,CAAC;CAC/D;AAED,MAAM,WAAW,oBAAoB;IACpC,YAAY,EAAE,MAAM,IAAI,CAAC;IACzB,UAAU,EAAE,CAAC,KAAK,CAAC,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;CACpB;AAQD,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,2BAA2B,GAClC,oBAAoB,CAiftB"}
@@ -7,6 +7,7 @@ import { buildRendererPipelineSignature } from "./recompile-policy.js";
7
7
  function getRendererRetryDelayMs(attempt) {
8
8
  return Math.min(8e3, 250 * 2 ** Math.max(0, attempt - 1));
9
9
  }
10
+ var ERROR_CLEAR_GRACE_MS = 750;
10
11
  function createMotionGPURuntimeLoop(options) {
11
12
  const { canvas: canvasElement, registry, size } = options;
12
13
  let frameId = null;
@@ -43,6 +44,12 @@ function createMotionGPURuntimeLoop(options) {
43
44
  let shouldContinueAfterFrame = false;
44
45
  let activeErrorKey = null;
45
46
  let errorHistory = [];
47
+ let errorClearReadyAtMs = 0;
48
+ let lastFrameTimestampMs = performance.now();
49
+ const resolveNowMs = (nowMs) => {
50
+ if (typeof nowMs === "number" && Number.isFinite(nowMs)) return nowMs;
51
+ return lastFrameTimestampMs;
52
+ };
46
53
  const getHistoryLimit = () => {
47
54
  const value = options.getErrorHistoryLimit?.() ?? 0;
48
55
  if (!Number.isFinite(value) || value <= 0) return 0;
@@ -65,11 +72,12 @@ function createMotionGPURuntimeLoop(options) {
65
72
  return;
66
73
  }
67
74
  if (errorHistory.length <= limit) return;
68
- errorHistory = errorHistory.slice(errorHistory.length - limit);
75
+ errorHistory.splice(0, errorHistory.length - limit);
69
76
  publishErrorHistory();
70
77
  };
71
- const setError = (error, phase) => {
78
+ const setError = (error, phase, nowMs) => {
72
79
  const report = toMotionGPUErrorReport(error, phase);
80
+ errorClearReadyAtMs = resolveNowMs(nowMs) + ERROR_CLEAR_GRACE_MS;
73
81
  const reportKey = JSON.stringify({
74
82
  phase: report.phase,
75
83
  title: report.title,
@@ -80,8 +88,8 @@ function createMotionGPURuntimeLoop(options) {
80
88
  activeErrorKey = reportKey;
81
89
  const historyLimit = getHistoryLimit();
82
90
  if (historyLimit > 0) {
83
- errorHistory = [...errorHistory, report];
84
- if (errorHistory.length > historyLimit) errorHistory = errorHistory.slice(errorHistory.length - historyLimit);
91
+ errorHistory.push(report);
92
+ if (errorHistory.length > historyLimit) errorHistory.splice(0, errorHistory.length - historyLimit);
85
93
  publishErrorHistory();
86
94
  }
87
95
  options.reportError(report);
@@ -91,9 +99,11 @@ function createMotionGPURuntimeLoop(options) {
91
99
  onError(report);
92
100
  } catch {}
93
101
  };
94
- const clearError = () => {
102
+ const maybeClearError = (nowMs) => {
95
103
  if (activeErrorKey === null) return;
104
+ if (resolveNowMs(nowMs) < errorClearReadyAtMs) return;
96
105
  activeErrorKey = null;
106
+ errorClearReadyAtMs = 0;
97
107
  options.reportError(null);
98
108
  };
99
109
  const scheduleFrame = () => {
@@ -112,12 +122,12 @@ function createMotionGPURuntimeLoop(options) {
112
122
  requestFrame();
113
123
  };
114
124
  const resetRuntimeMaps = () => {
115
- for (const key of Object.keys(runtimeUniforms)) if (!uniformKeySet.has(key)) Reflect.deleteProperty(runtimeUniforms, key);
116
- for (const key of Object.keys(runtimeTextures)) if (!textureKeySet.has(key)) Reflect.deleteProperty(runtimeTextures, key);
125
+ for (const key of Object.keys(runtimeUniforms)) if (!uniformKeySet.has(key)) delete runtimeUniforms[key];
126
+ for (const key of Object.keys(runtimeTextures)) if (!textureKeySet.has(key)) delete runtimeTextures[key];
117
127
  };
118
128
  const resetRenderPayloadMaps = () => {
119
- for (const key of Object.keys(renderUniforms)) if (!uniformKeySet.has(key)) Reflect.deleteProperty(renderUniforms, key);
120
- for (const key of Object.keys(renderTextures)) if (!textureKeySet.has(key)) Reflect.deleteProperty(renderTextures, key);
129
+ for (const key of Object.keys(renderUniforms)) if (!uniformKeySet.has(key)) delete renderUniforms[key];
130
+ for (const key of Object.keys(renderTextures)) if (!textureKeySet.has(key)) delete renderTextures[key];
121
131
  };
122
132
  const syncMaterialRuntimeState = (materialState) => {
123
133
  const signatureChanged = activeMaterialSignature !== materialState.signature;
@@ -190,12 +200,13 @@ function createMotionGPURuntimeLoop(options) {
190
200
  const renderFrame = (timestamp) => {
191
201
  frameId = null;
192
202
  if (isDisposed) return;
203
+ lastFrameTimestampMs = timestamp;
193
204
  syncErrorHistory();
194
205
  let materialState;
195
206
  try {
196
207
  materialState = resolveActiveMaterial();
197
208
  } catch (error) {
198
- setError(error, "initialization");
209
+ setError(error, "initialization", timestamp);
199
210
  scheduleFrame();
200
211
  return;
201
212
  }
@@ -251,7 +262,7 @@ function createMotionGPURuntimeLoop(options) {
251
262
  failedRendererSignature = null;
252
263
  failedRendererAttempts = 0;
253
264
  nextRendererRetryAt = 0;
254
- clearError();
265
+ maybeClearError(performance.now());
255
266
  } catch (error) {
256
267
  failedRendererSignature = rendererSignature;
257
268
  failedRendererAttempts += 1;
@@ -314,12 +325,13 @@ function createMotionGPURuntimeLoop(options) {
314
325
  uniforms: renderUniforms,
315
326
  textures: renderTextures,
316
327
  canvasSize,
317
- ...pendingStorageWrites.length > 0 ? { pendingStorageWrites: pendingStorageWrites.splice(0) } : {}
328
+ pendingStorageWrites: pendingStorageWrites.length > 0 ? pendingStorageWrites : void 0
318
329
  });
330
+ if (pendingStorageWrites.length > 0) pendingStorageWrites.length = 0;
319
331
  }
320
- clearError();
332
+ maybeClearError(timestamp);
321
333
  } catch (error) {
322
- setError(error, "render");
334
+ setError(error, "render", timestamp);
323
335
  } finally {
324
336
  registry.endFrame();
325
337
  }