@motion-core/motion-gpu 0.4.0 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/advanced.d.ts +1 -0
- package/dist/advanced.d.ts.map +1 -0
- package/dist/advanced.js +12 -6
- package/dist/core/advanced.d.ts +1 -0
- package/dist/core/advanced.d.ts.map +1 -0
- package/dist/core/advanced.js +12 -5
- package/dist/core/current-value.d.ts +1 -0
- package/dist/core/current-value.d.ts.map +1 -0
- package/dist/core/current-value.js +35 -34
- package/dist/core/current-value.js.map +1 -0
- package/dist/core/error-diagnostics.d.ts +1 -0
- package/dist/core/error-diagnostics.d.ts.map +1 -0
- package/dist/core/error-diagnostics.js +70 -137
- package/dist/core/error-diagnostics.js.map +1 -0
- package/dist/core/error-report.d.ts +1 -0
- package/dist/core/error-report.d.ts.map +1 -0
- package/dist/core/error-report.js +184 -233
- package/dist/core/error-report.js.map +1 -0
- package/dist/core/frame-registry.d.ts +1 -0
- package/dist/core/frame-registry.d.ts.map +1 -0
- package/dist/core/frame-registry.js +546 -662
- package/dist/core/frame-registry.js.map +1 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +11 -12
- package/dist/core/material-preprocess.d.ts +1 -0
- package/dist/core/material-preprocess.d.ts.map +1 -0
- package/dist/core/material-preprocess.js +128 -151
- package/dist/core/material-preprocess.js.map +1 -0
- package/dist/core/material.d.ts +1 -0
- package/dist/core/material.d.ts.map +1 -0
- package/dist/core/material.js +263 -317
- package/dist/core/material.js.map +1 -0
- package/dist/core/recompile-policy.d.ts +1 -0
- package/dist/core/recompile-policy.d.ts.map +1 -0
- package/dist/core/recompile-policy.js +18 -13
- package/dist/core/recompile-policy.js.map +1 -0
- package/dist/core/render-graph.d.ts +1 -0
- package/dist/core/render-graph.d.ts.map +1 -0
- package/dist/core/render-graph.js +61 -68
- package/dist/core/render-graph.js.map +1 -0
- package/dist/core/render-targets.d.ts +2 -0
- package/dist/core/render-targets.d.ts.map +1 -0
- package/dist/core/render-targets.js +52 -53
- package/dist/core/render-targets.js.map +1 -0
- package/dist/core/renderer.d.ts +1 -0
- package/dist/core/renderer.d.ts.map +1 -0
- package/dist/core/renderer.js +942 -1081
- package/dist/core/renderer.js.map +1 -0
- package/dist/core/runtime-loop.d.ts +2 -0
- package/dist/core/runtime-loop.d.ts.map +1 -0
- package/dist/core/runtime-loop.js +305 -362
- package/dist/core/runtime-loop.js.map +1 -0
- package/dist/core/scheduler-helpers.d.ts +1 -0
- package/dist/core/scheduler-helpers.d.ts.map +1 -0
- package/dist/core/scheduler-helpers.js +52 -51
- package/dist/core/scheduler-helpers.js.map +1 -0
- package/dist/core/shader.d.ts +1 -0
- package/dist/core/shader.d.ts.map +1 -0
- package/dist/core/shader.js +92 -117
- package/dist/core/shader.js.map +1 -0
- package/dist/core/texture-loader.d.ts +1 -0
- package/dist/core/texture-loader.d.ts.map +1 -0
- package/dist/core/texture-loader.js +205 -273
- package/dist/core/texture-loader.js.map +1 -0
- package/dist/core/textures.d.ts +2 -0
- package/dist/core/textures.d.ts.map +1 -0
- package/dist/core/textures.js +106 -116
- package/dist/core/textures.js.map +1 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +0 -4
- package/dist/core/uniforms.d.ts +1 -0
- package/dist/core/uniforms.d.ts.map +1 -0
- package/dist/core/uniforms.js +170 -191
- package/dist/core/uniforms.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -6
- package/dist/passes/BlitPass.d.ts +1 -0
- package/dist/passes/BlitPass.d.ts.map +1 -0
- package/dist/passes/BlitPass.js +23 -18
- package/dist/passes/BlitPass.js.map +1 -0
- package/dist/passes/CopyPass.d.ts +2 -0
- package/dist/passes/CopyPass.d.ts.map +1 -0
- package/dist/passes/CopyPass.js +58 -52
- package/dist/passes/CopyPass.js.map +1 -0
- package/dist/passes/FullscreenPass.d.ts +2 -0
- package/dist/passes/FullscreenPass.d.ts.map +1 -0
- package/dist/passes/FullscreenPass.js +127 -130
- package/dist/passes/FullscreenPass.js.map +1 -0
- package/dist/passes/ShaderPass.d.ts +1 -0
- package/dist/passes/ShaderPass.d.ts.map +1 -0
- package/dist/passes/ShaderPass.js +40 -37
- package/dist/passes/ShaderPass.js.map +1 -0
- package/dist/passes/index.d.ts +1 -0
- package/dist/passes/index.d.ts.map +1 -0
- package/dist/passes/index.js +4 -3
- package/dist/react/FragCanvas.d.ts +2 -0
- package/dist/react/FragCanvas.d.ts.map +1 -0
- package/dist/react/FragCanvas.js +234 -211
- package/dist/react/FragCanvas.js.map +1 -0
- package/dist/react/MotionGPUErrorOverlay.d.ts +1 -0
- package/dist/react/MotionGPUErrorOverlay.d.ts.map +1 -0
- package/dist/react/MotionGPUErrorOverlay.js +384 -48
- package/dist/react/MotionGPUErrorOverlay.js.map +1 -0
- package/dist/react/Portal.d.ts +1 -0
- package/dist/react/Portal.d.ts.map +1 -0
- package/dist/react/Portal.js +18 -21
- package/dist/react/Portal.js.map +1 -0
- package/dist/react/advanced.d.ts +1 -0
- package/dist/react/advanced.d.ts.map +1 -0
- package/dist/react/advanced.js +12 -6
- package/dist/react/frame-context.d.ts +1 -0
- package/dist/react/frame-context.d.ts.map +1 -0
- package/dist/react/frame-context.js +88 -94
- package/dist/react/frame-context.js.map +1 -0
- package/dist/react/index.d.ts +1 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +10 -9
- package/dist/react/motiongpu-context.d.ts +1 -0
- package/dist/react/motiongpu-context.d.ts.map +1 -0
- package/dist/react/motiongpu-context.js +18 -15
- package/dist/react/motiongpu-context.js.map +1 -0
- package/dist/react/use-motiongpu-user-context.d.ts +1 -0
- package/dist/react/use-motiongpu-user-context.d.ts.map +1 -0
- package/dist/react/use-motiongpu-user-context.js +83 -82
- package/dist/react/use-motiongpu-user-context.js.map +1 -0
- package/dist/react/use-texture.d.ts +1 -0
- package/dist/react/use-texture.d.ts.map +1 -0
- package/dist/react/use-texture.js +132 -152
- package/dist/react/use-texture.js.map +1 -0
- package/dist/svelte/FragCanvas.svelte.d.ts +2 -0
- package/dist/svelte/FragCanvas.svelte.d.ts.map +1 -0
- package/dist/svelte/MotionGPUErrorOverlay.svelte +17 -20
- package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts +1 -0
- package/dist/svelte/MotionGPUErrorOverlay.svelte.d.ts.map +1 -0
- package/dist/svelte/Portal.svelte.d.ts +1 -0
- package/dist/svelte/Portal.svelte.d.ts.map +1 -0
- package/dist/svelte/advanced.d.ts +1 -0
- package/dist/svelte/advanced.d.ts.map +1 -0
- package/dist/svelte/advanced.js +11 -6
- package/dist/svelte/frame-context.d.ts +1 -0
- package/dist/svelte/frame-context.d.ts.map +1 -0
- package/dist/svelte/frame-context.js +27 -27
- package/dist/svelte/frame-context.js.map +1 -0
- package/dist/svelte/index.d.ts +1 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +10 -9
- package/dist/svelte/motiongpu-context.d.ts +1 -0
- package/dist/svelte/motiongpu-context.d.ts.map +1 -0
- package/dist/svelte/motiongpu-context.js +24 -21
- package/dist/svelte/motiongpu-context.js.map +1 -0
- package/dist/svelte/use-motiongpu-user-context.d.ts +1 -0
- package/dist/svelte/use-motiongpu-user-context.d.ts.map +1 -0
- package/dist/svelte/use-motiongpu-user-context.js +69 -70
- package/dist/svelte/use-motiongpu-user-context.js.map +1 -0
- package/dist/svelte/use-texture.d.ts +1 -0
- package/dist/svelte/use-texture.d.ts.map +1 -0
- package/dist/svelte/use-texture.js +125 -147
- package/dist/svelte/use-texture.js.map +1 -0
- package/package.json +15 -7
- package/src/lib/advanced.ts +6 -0
- package/src/lib/core/advanced.ts +12 -0
- package/src/lib/core/current-value.ts +64 -0
- package/src/lib/core/error-diagnostics.ts +236 -0
- package/src/lib/core/error-report.ts +406 -0
- package/src/lib/core/frame-registry.ts +1189 -0
- package/src/lib/core/index.ts +77 -0
- package/src/lib/core/material-preprocess.ts +284 -0
- package/src/lib/core/material.ts +667 -0
- package/src/lib/core/recompile-policy.ts +31 -0
- package/src/lib/core/render-graph.ts +143 -0
- package/src/lib/core/render-targets.ts +107 -0
- package/src/lib/core/renderer.ts +1547 -0
- package/src/lib/core/runtime-loop.ts +458 -0
- package/src/lib/core/scheduler-helpers.ts +136 -0
- package/src/lib/core/shader.ts +258 -0
- package/src/lib/core/texture-loader.ts +476 -0
- package/src/lib/core/textures.ts +235 -0
- package/src/lib/core/types.ts +582 -0
- package/src/lib/core/uniforms.ts +282 -0
- package/src/lib/index.ts +6 -0
- package/src/lib/passes/BlitPass.ts +54 -0
- package/src/lib/passes/CopyPass.ts +80 -0
- package/src/lib/passes/FullscreenPass.ts +173 -0
- package/src/lib/passes/ShaderPass.ts +88 -0
- package/src/lib/passes/index.ts +3 -0
- package/src/lib/react/MotionGPUErrorOverlay.tsx +392 -0
- package/src/lib/react/advanced.ts +36 -0
- package/src/lib/react/frame-context.ts +169 -0
- package/src/lib/react/index.ts +51 -0
- package/src/lib/react/motiongpu-context.ts +88 -0
- package/src/lib/react/use-motiongpu-user-context.ts +186 -0
- package/src/lib/react/use-texture.ts +233 -0
- package/src/lib/svelte/FragCanvas.svelte +249 -0
- package/src/lib/svelte/MotionGPUErrorOverlay.svelte +382 -0
- package/src/lib/svelte/Portal.svelte +31 -0
- package/src/lib/svelte/advanced.ts +32 -0
- package/src/lib/svelte/frame-context.ts +87 -0
- package/src/lib/svelte/index.ts +51 -0
- package/src/lib/svelte/motiongpu-context.ts +97 -0
- package/src/lib/svelte/use-motiongpu-user-context.ts +145 -0
- package/src/lib/svelte/use-texture.ts +232 -0
- package/dist/react/MotionGPUErrorOverlay.tsx +0 -129
- /package/{dist → src/lib}/react/FragCanvas.tsx +0 -0
- /package/{dist → src/lib}/react/Portal.tsx +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"material.js","names":[],"sources":["../../src/lib/core/material.ts"],"sourcesContent":["import { normalizeTextureDefinition } from './textures.js';\nimport type { MaterialSourceMetadata } from './error-diagnostics.js';\nimport {\n\tassertUniformName,\n\tassertUniformValueForType,\n\tinferUniformType,\n\tresolveUniformLayout\n} from './uniforms.js';\nimport {\n\tnormalizeDefines,\n\tnormalizeIncludes,\n\tpreprocessMaterialFragment,\n\ttoDefineLine,\n\ttype MaterialLineMap,\n\ttype PreprocessedMaterialFragment\n} from './material-preprocess.js';\nimport type {\n\tTextureData,\n\tTextureDefinition,\n\tTextureDefinitionMap,\n\tTextureValue,\n\tTypedUniform,\n\tUniformMap,\n\tUniformValue\n} from './types.js';\n\n/**\n * Typed compile-time define declaration.\n */\nexport type TypedMaterialDefineValue =\n\t| {\n\t\t\t/**\n\t\t\t * WGSL scalar type.\n\t\t\t */\n\t\t\ttype: 'bool';\n\t\t\t/**\n\t\t\t * Literal value for the selected WGSL type.\n\t\t\t */\n\t\t\tvalue: boolean;\n\t }\n\t| {\n\t\t\t/**\n\t\t\t * WGSL scalar type.\n\t\t\t */\n\t\t\ttype: 'f32' | 'i32' | 'u32';\n\t\t\t/**\n\t\t\t * Literal value for the selected WGSL type.\n\t\t\t */\n\t\t\tvalue: number;\n\t };\n\n/**\n * Allowed value types for WGSL `const` define injection.\n */\nexport type MaterialDefineValue = boolean | number | TypedMaterialDefineValue;\n\n/**\n * Define map keyed by uniform-compatible identifier names.\n */\nexport type MaterialDefines<TKey extends string = string> = Record<TKey, MaterialDefineValue>;\n\n/**\n * Include map keyed by include identifier used in `#include <name>` directives.\n */\nexport type MaterialIncludes<TKey extends string = string> = Record<TKey, string>;\n\n/**\n * External material input accepted by {@link defineMaterial}.\n */\nexport interface FragMaterialInput<\n\tTUniformKey extends string = string,\n\tTTextureKey extends string = string,\n\tTDefineKey extends string = string,\n\tTIncludeKey extends string = string\n> {\n\t/**\n\t * User WGSL source containing `frag(uv: vec2f) -> vec4f`.\n\t */\n\tfragment: string;\n\t/**\n\t * Initial uniform values.\n\t */\n\tuniforms?: UniformMap<TUniformKey>;\n\t/**\n\t * Texture definitions keyed by texture uniform name.\n\t */\n\ttextures?: TextureDefinitionMap<TTextureKey>;\n\t/**\n\t * Optional compile-time define constants injected into WGSL.\n\t */\n\tdefines?: MaterialDefines<TDefineKey>;\n\t/**\n\t * Optional WGSL include chunks used by `#include <name>` directives.\n\t */\n\tincludes?: MaterialIncludes<TIncludeKey>;\n}\n\n/**\n * Normalized and immutable material declaration consumed by `FragCanvas`.\n */\nexport interface FragMaterial<\n\tTUniformKey extends string = string,\n\tTTextureKey extends string = string,\n\tTDefineKey extends string = string,\n\tTIncludeKey extends string = string\n> {\n\t/**\n\t * User WGSL source containing `frag(uv: vec2f) -> vec4f`.\n\t */\n\treadonly fragment: string;\n\t/**\n\t * Initial uniform values.\n\t */\n\treadonly uniforms: Readonly<UniformMap<TUniformKey>>;\n\t/**\n\t * Texture definitions keyed by texture uniform name.\n\t */\n\treadonly textures: Readonly<TextureDefinitionMap<TTextureKey>>;\n\t/**\n\t * Optional compile-time define constants injected into WGSL.\n\t */\n\treadonly defines: Readonly<MaterialDefines<TDefineKey>>;\n\t/**\n\t * Optional WGSL include chunks used by `#include <name>` directives.\n\t */\n\treadonly includes: Readonly<MaterialIncludes<TIncludeKey>>;\n}\n\n/**\n * Fully resolved, immutable material snapshot used for renderer creation/caching.\n */\nexport interface ResolvedMaterial<\n\tTUniformKey extends string = string,\n\tTTextureKey extends string = string,\n\tTIncludeKey extends string = string\n> {\n\t/**\n\t * Final fragment WGSL after define injection.\n\t */\n\tfragmentWgsl: string;\n\t/**\n\t * 1-based map from generated fragment lines to user source lines.\n\t */\n\tfragmentLineMap: MaterialLineMap;\n\t/**\n\t * Cloned uniforms.\n\t */\n\tuniforms: UniformMap<TUniformKey>;\n\t/**\n\t * Cloned texture definitions.\n\t */\n\ttextures: TextureDefinitionMap<TTextureKey>;\n\t/**\n\t * Resolved packed uniform layout.\n\t */\n\tuniformLayout: ReturnType<typeof resolveUniformLayout>;\n\t/**\n\t * Sorted texture keys.\n\t */\n\ttextureKeys: TTextureKey[];\n\t/**\n\t * Deterministic JSON signature for cache invalidation.\n\t */\n\tsignature: string;\n\t/**\n\t * Original user fragment source before preprocessing.\n\t */\n\tfragmentSource: string;\n\t/**\n\t * Normalized include sources map.\n\t */\n\tincludeSources: MaterialIncludes<TIncludeKey>;\n\t/**\n\t * Deterministic define block source used for diagnostics mapping.\n\t */\n\tdefineBlockSource: string;\n\t/**\n\t * Source metadata used for diagnostics.\n\t */\n\tsource: Readonly<MaterialSourceMetadata> | null;\n}\n\n/**\n * Strict fragment contract used by MotionGPU.\n */\nconst FRAGMENT_FUNCTION_SIGNATURE_PATTERN =\n\t/\\bfn\\s+frag\\s*\\(\\s*([^)]*?)\\s*\\)\\s*->\\s*([A-Za-z_][A-Za-z0-9_<>\\s]*)\\s*(?:\\{|$)/m;\nconst FRAGMENT_FUNCTION_NAME_PATTERN = /\\bfn\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*\\(/g;\n\n/**\n * Cache of resolved material snapshots keyed by immutable material instance.\n */\ntype AnyFragMaterial = FragMaterial<string, string, string, string>;\ntype AnyResolvedMaterial = ResolvedMaterial<string, string, string>;\n\nconst resolvedMaterialCache = new WeakMap<AnyFragMaterial, AnyResolvedMaterial>();\nconst preprocessedFragmentCache = new WeakMap<AnyFragMaterial, PreprocessedMaterialFragment>();\nconst materialSourceMetadataCache = new WeakMap<AnyFragMaterial, MaterialSourceMetadata | null>();\n\nfunction getCachedResolvedMaterial<\n\tTUniformKey extends string,\n\tTTextureKey extends string,\n\tTIncludeKey extends string\n>(\n\tmaterial: FragMaterial<TUniformKey, TTextureKey, string, TIncludeKey>\n): ResolvedMaterial<TUniformKey, TTextureKey, TIncludeKey> | null {\n\tconst cached = resolvedMaterialCache.get(material);\n\tif (!cached) {\n\t\treturn null;\n\t}\n\n\t// Invariant: the cache key is the same material object used to produce this resolved payload.\n\treturn cached as ResolvedMaterial<TUniformKey, TTextureKey, TIncludeKey>;\n}\n\nconst STACK_TRACE_CHROME_PATTERN = /^\\s*at\\s+(?:(.*?)\\s+\\()?(.+?):(\\d+):(\\d+)\\)?$/;\nconst STACK_TRACE_FIREFOX_PATTERN = /^(.*?)@(.+?):(\\d+):(\\d+)$/;\n\nfunction getPathBasename(path: string): string {\n\tconst normalized = path.split(/[?#]/)[0] ?? path;\n\tconst parts = normalized.split(/[\\\\/]/);\n\tconst last = parts[parts.length - 1];\n\treturn last && last.length > 0 ? last : path;\n}\n\nfunction normalizeSignaturePart(value: string): string {\n\treturn value.replace(/\\s+/g, ' ').trim();\n}\n\nfunction listFunctionNames(fragment: string): string[] {\n\tconst names = new Set<string>();\n\tfor (const match of fragment.matchAll(FRAGMENT_FUNCTION_NAME_PATTERN)) {\n\t\tconst name = match[1];\n\t\tif (!name) {\n\t\t\tcontinue;\n\t\t}\n\t\tnames.add(name);\n\t}\n\n\treturn Array.from(names);\n}\n\nfunction captureMaterialSourceFromStack(): MaterialSourceMetadata | null {\n\tconst stack = new Error().stack;\n\tif (!stack) {\n\t\treturn null;\n\t}\n\n\tconst stackLines = stack.split('\\n').slice(1);\n\tfor (const rawLine of stackLines) {\n\t\tconst line = rawLine.trim();\n\t\tif (line.length === 0) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst chromeMatch = line.match(STACK_TRACE_CHROME_PATTERN);\n\t\tconst firefoxMatch = line.match(STACK_TRACE_FIREFOX_PATTERN);\n\t\tconst functionName = chromeMatch?.[1] ?? firefoxMatch?.[1] ?? undefined;\n\t\tconst file = chromeMatch?.[2] ?? firefoxMatch?.[2];\n\t\tconst lineValue = chromeMatch?.[3] ?? firefoxMatch?.[3];\n\t\tconst columnValue = chromeMatch?.[4] ?? firefoxMatch?.[4];\n\n\t\tif (!file || !lineValue || !columnValue) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (file.includes('/core/material') || file.includes('\\\\core\\\\material')) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst parsedLine = Number.parseInt(lineValue, 10);\n\t\tconst parsedColumn = Number.parseInt(columnValue, 10);\n\t\tif (!Number.isFinite(parsedLine) || !Number.isFinite(parsedColumn)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\treturn {\n\t\t\tcomponent: getPathBasename(file),\n\t\t\tfile,\n\t\t\tline: parsedLine,\n\t\t\tcolumn: parsedColumn,\n\t\t\t...(functionName ? { functionName } : {})\n\t\t};\n\t}\n\n\treturn null;\n}\n\nfunction resolveSourceMetadata(\n\tsource: MaterialSourceMetadata | undefined\n): MaterialSourceMetadata | null {\n\tconst captured = captureMaterialSourceFromStack();\n\tconst component = source?.component ?? captured?.component;\n\tconst file = source?.file ?? captured?.file;\n\tconst line = source?.line ?? captured?.line;\n\tconst column = source?.column ?? captured?.column;\n\tconst functionName = source?.functionName ?? captured?.functionName;\n\n\tif (\n\t\tcomponent === undefined &&\n\t\tfile === undefined &&\n\t\tline === undefined &&\n\t\tcolumn === undefined &&\n\t\tfunctionName === undefined\n\t) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\t...(component !== undefined ? { component } : {}),\n\t\t...(file !== undefined ? { file } : {}),\n\t\t...(line !== undefined ? { line } : {}),\n\t\t...(column !== undefined ? { column } : {}),\n\t\t...(functionName !== undefined ? { functionName } : {})\n\t};\n}\n\n/**\n * Asserts that material has been normalized by {@link defineMaterial}.\n */\nfunction assertDefinedMaterial(material: AnyFragMaterial): void {\n\tif (\n\t\t!Object.isFrozen(material) ||\n\t\t!material.uniforms ||\n\t\t!material.textures ||\n\t\t!material.defines ||\n\t\t!material.includes\n\t) {\n\t\tthrow new Error(\n\t\t\t'Invalid material instance. Create materials with defineMaterial(...) before passing them to <FragCanvas>.'\n\t\t);\n\t}\n}\n\n/**\n * Clones uniform value input to decouple material instances from external objects.\n */\nfunction cloneUniformValue(value: UniformValue): UniformValue {\n\tif (typeof value === 'number') {\n\t\treturn value;\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn Object.freeze([...value]) as UniformValue;\n\t}\n\n\tif (typeof value === 'object' && value !== null && 'type' in value && 'value' in value) {\n\t\tconst typed = value as TypedUniform;\n\t\tconst typedValue = typed.value as unknown;\n\n\t\tlet clonedTypedValue = typedValue;\n\t\tif (typedValue instanceof Float32Array) {\n\t\t\tclonedTypedValue = new Float32Array(typedValue);\n\t\t} else if (Array.isArray(typedValue)) {\n\t\t\tclonedTypedValue = Object.freeze([...typedValue]);\n\t\t}\n\n\t\treturn Object.freeze({\n\t\t\ttype: typed.type,\n\t\t\tvalue: clonedTypedValue\n\t\t}) as UniformValue;\n\t}\n\n\treturn value;\n}\n\n/**\n * Clones optional texture value payload.\n */\nfunction cloneTextureValue(value: TextureValue | undefined): TextureValue {\n\tif (value === undefined || value === null) {\n\t\treturn null;\n\t}\n\n\tif (typeof value === 'object' && 'source' in value) {\n\t\tconst data = value as TextureData;\n\t\treturn {\n\t\t\tsource: data.source,\n\t\t\t...(data.width !== undefined ? { width: data.width } : {}),\n\t\t\t...(data.height !== undefined ? { height: data.height } : {}),\n\t\t\t...(data.colorSpace !== undefined ? { colorSpace: data.colorSpace } : {}),\n\t\t\t...(data.flipY !== undefined ? { flipY: data.flipY } : {}),\n\t\t\t...(data.premultipliedAlpha !== undefined\n\t\t\t\t? { premultipliedAlpha: data.premultipliedAlpha }\n\t\t\t\t: {}),\n\t\t\t...(data.generateMipmaps !== undefined ? { generateMipmaps: data.generateMipmaps } : {}),\n\t\t\t...(data.update !== undefined ? { update: data.update } : {})\n\t\t};\n\t}\n\n\treturn value;\n}\n\n/**\n * Clones and validates fragment source contract.\n */\nfunction resolveFragment(fragment: string): string {\n\tif (typeof fragment !== 'string' || fragment.trim().length === 0) {\n\t\tthrow new Error('Material fragment shader must be a non-empty WGSL string.');\n\t}\n\n\tconst signature = fragment.match(FRAGMENT_FUNCTION_SIGNATURE_PATTERN);\n\tif (!signature) {\n\t\tconst discoveredFunctions = listFunctionNames(fragment).slice(0, 4);\n\t\tconst discoveredLabel =\n\t\t\tdiscoveredFunctions.length > 0\n\t\t\t\t? `Found: ${discoveredFunctions.map((name) => `\\`${name}(...)\\``).join(', ')}.`\n\t\t\t\t: 'No WGSL function declarations were found.';\n\n\t\tthrow new Error(\n\t\t\t`Material fragment contract mismatch: missing entrypoint \\`fn frag(uv: vec2f) -> vec4f\\`. ${discoveredLabel}`\n\t\t);\n\t}\n\n\tconst params = normalizeSignaturePart(signature[1] ?? '');\n\tconst returnType = normalizeSignaturePart(signature[2] ?? '');\n\n\tif (params !== 'uv: vec2f') {\n\t\tthrow new Error(\n\t\t\t`Material fragment contract mismatch for \\`frag\\`: expected parameter list \\`(uv: vec2f)\\`, received \\`(${params || '...'})\\`.`\n\t\t);\n\t}\n\n\tif (returnType !== 'vec4f') {\n\t\tthrow new Error(\n\t\t\t`Material fragment contract mismatch for \\`frag\\`: expected return type \\`vec4f\\`, received \\`${returnType}\\`.`\n\t\t);\n\t}\n\n\treturn fragment;\n}\n\n/**\n * Clones and validates uniform declarations.\n */\nfunction resolveUniforms<TUniformKey extends string>(\n\tuniforms: UniformMap<TUniformKey> | undefined\n): UniformMap<TUniformKey> {\n\tconst resolved: UniformMap<TUniformKey> = {} as UniformMap<TUniformKey>;\n\n\tfor (const [name, value] of Object.entries(uniforms ?? {}) as Array<\n\t\t[TUniformKey, UniformValue]\n\t>) {\n\t\tassertUniformName(name);\n\t\tconst clonedValue = cloneUniformValue(value);\n\t\tconst type = inferUniformType(clonedValue);\n\t\tassertUniformValueForType(type, clonedValue);\n\t\tresolved[name] = clonedValue;\n\t}\n\n\tresolveUniformLayout(resolved);\n\treturn resolved;\n}\n\n/**\n * Clones and validates texture declarations.\n */\nfunction resolveTextures<TTextureKey extends string>(\n\ttextures: TextureDefinitionMap<TTextureKey> | undefined\n): TextureDefinitionMap<TTextureKey> {\n\tconst resolved: TextureDefinitionMap<TTextureKey> = {} as TextureDefinitionMap<TTextureKey>;\n\n\tfor (const [name, definition] of Object.entries(textures ?? {}) as Array<\n\t\t[TTextureKey, TextureDefinition]\n\t>) {\n\t\tassertUniformName(name);\n\t\tconst source = definition?.source;\n\t\tconst normalizedSource = cloneTextureValue(source);\n\n\t\tconst clonedDefinition: TextureDefinition = {\n\t\t\t...(definition ?? {}),\n\t\t\t...(source !== undefined ? { source: normalizedSource } : {})\n\t\t};\n\n\t\tresolved[name] = Object.freeze(clonedDefinition);\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Clones and validates define declarations.\n */\nfunction resolveDefines<TDefineKey extends string>(\n\tdefines: MaterialDefines<TDefineKey> | undefined\n): MaterialDefines<TDefineKey> {\n\treturn normalizeDefines(defines);\n}\n\n/**\n * Clones and validates include declarations.\n */\nfunction resolveIncludes<TIncludeKey extends string>(\n\tincludes: MaterialIncludes<TIncludeKey> | undefined\n): MaterialIncludes<TIncludeKey> {\n\treturn normalizeIncludes(includes);\n}\n\n/**\n * Builds a deterministic texture-config signature map used in material cache signatures.\n *\n * @param textures - Raw texture definitions from material input.\n * @param textureKeys - Sorted texture keys.\n * @returns Compact signature entries describing effective texture config per key.\n */\nfunction buildTextureConfigSignature<TTextureKey extends string>(\n\ttextures: TextureDefinitionMap<TTextureKey>,\n\ttextureKeys: TTextureKey[]\n): Record<TTextureKey, string> {\n\tconst signature = {} as Record<TTextureKey, string>;\n\n\tfor (const key of textureKeys) {\n\t\tconst normalized = normalizeTextureDefinition(textures[key]);\n\t\tsignature[key] = [\n\t\t\tnormalized.colorSpace,\n\t\t\tnormalized.flipY ? '1' : '0',\n\t\t\tnormalized.generateMipmaps ? '1' : '0',\n\t\t\tnormalized.premultipliedAlpha ? '1' : '0',\n\t\t\tnormalized.anisotropy,\n\t\t\tnormalized.filter,\n\t\t\tnormalized.addressModeU,\n\t\t\tnormalized.addressModeV\n\t\t].join(':');\n\t}\n\n\treturn signature;\n}\n\n/**\n * Creates a stable WGSL define block from the provided map.\n *\n * @param defines - Optional material defines.\n * @returns Joined WGSL const declarations ordered by key.\n */\nexport function buildDefinesBlock(defines: MaterialDefines | undefined): string {\n\tconst normalizedDefines = normalizeDefines(defines);\n\tif (Object.keys(normalizedDefines).length === 0) {\n\t\treturn '';\n\t}\n\n\treturn Object.entries(normalizedDefines)\n\t\t.sort(([a], [b]) => a.localeCompare(b))\n\t\t.map(([key, value]) => {\n\t\t\tassertUniformName(key);\n\t\t\treturn toDefineLine(key, value);\n\t\t})\n\t\t.join('\\n');\n}\n\n/**\n * Prepends resolved defines to a fragment shader.\n *\n * @param fragment - Raw WGSL fragment source.\n * @param defines - Optional define map.\n * @returns Fragment source with a leading define block when defines are present.\n */\nexport function applyMaterialDefines(\n\tfragment: string,\n\tdefines: MaterialDefines | undefined\n): string {\n\tconst defineBlock = buildDefinesBlock(defines);\n\tif (defineBlock.length === 0) {\n\t\treturn fragment;\n\t}\n\n\treturn `${defineBlock}\\n\\n${fragment}`;\n}\n\n/**\n * Creates an immutable material object with validated shader/uniform/texture contracts.\n *\n * @param input - User material declaration.\n * @returns Frozen material object safe to share and cache.\n */\nexport function defineMaterial<\n\tTUniformKey extends string = string,\n\tTTextureKey extends string = string,\n\tTDefineKey extends string = string,\n\tTIncludeKey extends string = string\n>(\n\tinput: FragMaterialInput<TUniformKey, TTextureKey, TDefineKey, TIncludeKey>\n): FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey> {\n\tconst fragment = resolveFragment(input.fragment);\n\tconst uniforms = Object.freeze(resolveUniforms(input.uniforms));\n\tconst textures = Object.freeze(resolveTextures(input.textures));\n\tconst defines = Object.freeze(resolveDefines(input.defines));\n\tconst includes = Object.freeze(resolveIncludes(input.includes));\n\tconst source = Object.freeze(resolveSourceMetadata(undefined));\n\n\tconst preprocessed = preprocessMaterialFragment({\n\t\tfragment,\n\t\tdefines,\n\t\tincludes\n\t});\n\n\tconst material: FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey> = Object.freeze({\n\t\tfragment,\n\t\tuniforms,\n\t\ttextures,\n\t\tdefines,\n\t\tincludes\n\t});\n\n\tpreprocessedFragmentCache.set(material, preprocessed);\n\tmaterialSourceMetadataCache.set(material, source);\n\treturn material;\n}\n\n/**\n * Resolves a material to renderer-ready data and a deterministic signature.\n *\n * @param material - Material input created via {@link defineMaterial}.\n * @returns Resolved material with packed uniform layout, sorted texture keys and cache signature.\n */\nexport function resolveMaterial<\n\tTUniformKey extends string = string,\n\tTTextureKey extends string = string,\n\tTDefineKey extends string = string,\n\tTIncludeKey extends string = string\n>(\n\tmaterial: FragMaterial<TUniformKey, TTextureKey, TDefineKey, TIncludeKey>\n): ResolvedMaterial<TUniformKey, TTextureKey, TIncludeKey> {\n\tassertDefinedMaterial(material);\n\n\tconst cached = getCachedResolvedMaterial(material);\n\tif (cached) {\n\t\treturn cached;\n\t}\n\n\tconst uniforms = material.uniforms as UniformMap<TUniformKey>;\n\tconst textures = material.textures as TextureDefinitionMap<TTextureKey>;\n\tconst uniformLayout = resolveUniformLayout(uniforms);\n\tconst textureKeys = Object.keys(textures).sort() as TTextureKey[];\n\tconst preprocessed =\n\t\tpreprocessedFragmentCache.get(material) ??\n\t\tpreprocessMaterialFragment({\n\t\t\tfragment: material.fragment,\n\t\t\tdefines: material.defines,\n\t\t\tincludes: material.includes\n\t\t});\n\tconst fragmentWgsl = preprocessed.fragment;\n\tconst textureConfig = buildTextureConfigSignature(textures, textureKeys);\n\n\tconst signature = JSON.stringify({\n\t\tfragmentWgsl,\n\t\tuniforms: uniformLayout.entries.map((entry) => `${entry.name}:${entry.type}`),\n\t\ttextureKeys,\n\t\ttextureConfig\n\t});\n\n\tconst resolved: ResolvedMaterial<TUniformKey, TTextureKey, TIncludeKey> = {\n\t\tfragmentWgsl,\n\t\tfragmentLineMap: preprocessed.lineMap,\n\t\tuniforms,\n\t\ttextures,\n\t\tuniformLayout,\n\t\ttextureKeys,\n\t\tsignature,\n\t\tfragmentSource: material.fragment,\n\t\tincludeSources: material.includes as MaterialIncludes<TIncludeKey>,\n\t\tdefineBlockSource: preprocessed.defineBlockSource,\n\t\tsource: materialSourceMetadataCache.get(material) ?? null\n\t};\n\n\tresolvedMaterialCache.set(material, resolved);\n\treturn resolved;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recompile-policy.d.ts","sourceRoot":"","sources":["../../src/lib/core/recompile-policy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;OAEG;IACH,gBAAgB,EAAE,gBAAgB,CAAC;CACnC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,8BAA8B,GAAG,MAAM,CAE5F"}
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
+
//#region src/lib/core/recompile-policy.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
3
|
+
* Returns deterministic renderer pipeline signature.
|
|
4
|
+
*
|
|
5
|
+
* Rebuild triggers:
|
|
6
|
+
* - material signature changes (shader/layout related)
|
|
7
|
+
* - output color space changes
|
|
8
|
+
*
|
|
9
|
+
* Non-triggers:
|
|
10
|
+
* - runtime uniform values
|
|
11
|
+
* - runtime texture sources
|
|
12
|
+
* - clear color changes
|
|
13
|
+
*/
|
|
14
|
+
function buildRendererPipelineSignature(input) {
|
|
15
|
+
return `${input.materialSignature}|${input.outputColorSpace}`;
|
|
15
16
|
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { buildRendererPipelineSignature };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=recompile-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recompile-policy.js","names":[],"sources":["../../src/lib/core/recompile-policy.ts"],"sourcesContent":["import type { OutputColorSpace } from './types.js';\n\n/**\n * Inputs that affect renderer pipeline compilation.\n */\nexport interface RendererPipelineSignatureInput {\n\t/**\n\t * Material pipeline signature (fragment preprocess + uniform/texture layout).\n\t */\n\tmaterialSignature: string;\n\t/**\n\t * Output color-space transform mode.\n\t */\n\toutputColorSpace: OutputColorSpace;\n}\n\n/**\n * Returns deterministic renderer pipeline signature.\n *\n * Rebuild triggers:\n * - material signature changes (shader/layout related)\n * - output color space changes\n *\n * Non-triggers:\n * - runtime uniform values\n * - runtime texture sources\n * - clear color changes\n */\nexport function buildRendererPipelineSignature(input: RendererPipelineSignatureInput): string {\n\treturn `${input.materialSignature}|${input.outputColorSpace}`;\n}\n"],"mappings":";;;;;;;;;;;;;AA4BA,SAAgB,+BAA+B,OAA+C;AAC7F,QAAO,GAAG,MAAM,kBAAkB,GAAG,MAAM"}
|
|
@@ -53,3 +53,4 @@ export interface RenderGraphPlan {
|
|
|
53
53
|
* @returns Resolved render graph plan.
|
|
54
54
|
*/
|
|
55
55
|
export declare function planRenderGraph(passes: RenderPass[] | undefined, defaultClearColor: [number, number, number, number], renderTargetSlots?: Iterable<string>): RenderGraphPlan;
|
|
56
|
+
//# sourceMappingURL=render-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-graph.d.ts","sourceRoot":"","sources":["../../src/lib/core/render-graph.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAExF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,IAAI,EAAE,UAAU,CAAC;IACjB;;OAEG;IACH,KAAK,EAAE,mBAAmB,CAAC;IAC3B;;OAEG;IACH,MAAM,EAAE,oBAAoB,CAAC;IAC7B;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,OAAO,CAAC;IACf;;OAEG;IACH,UAAU,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7C;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB;;OAEG;IACH,WAAW,EAAE,oBAAoB,CAAC;CAClC;AAWD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC9B,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,EAChC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EACnD,iBAAiB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,GAClC,eAAe,CAwEjB"}
|
|
@@ -1,73 +1,66 @@
|
|
|
1
|
+
//#region src/lib/core/render-graph.ts
|
|
1
2
|
/**
|
|
2
|
-
|
|
3
|
-
|
|
3
|
+
* Creates a copy of RGBA clear color.
|
|
4
|
+
*/
|
|
4
5
|
function cloneClearColor(color) {
|
|
5
|
-
|
|
6
|
+
return [
|
|
7
|
+
color[0],
|
|
8
|
+
color[1],
|
|
9
|
+
color[2],
|
|
10
|
+
color[3]
|
|
11
|
+
];
|
|
6
12
|
}
|
|
7
13
|
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if (needsSwap) {
|
|
57
|
-
availableSlots.add('target');
|
|
58
|
-
availableSlots.add('source');
|
|
59
|
-
finalOutput = 'source';
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
if (output !== 'canvas') {
|
|
63
|
-
availableSlots.add(output);
|
|
64
|
-
}
|
|
65
|
-
finalOutput = output;
|
|
66
|
-
}
|
|
67
|
-
enabledIndex += 1;
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
steps,
|
|
71
|
-
finalOutput
|
|
72
|
-
};
|
|
14
|
+
* Builds validated render graph plan from runtime pass list.
|
|
15
|
+
*
|
|
16
|
+
* @param passes - Runtime passes.
|
|
17
|
+
* @param defaultClearColor - Global clear color fallback.
|
|
18
|
+
* @returns Resolved render graph plan.
|
|
19
|
+
*/
|
|
20
|
+
function planRenderGraph(passes, defaultClearColor, renderTargetSlots) {
|
|
21
|
+
const steps = [];
|
|
22
|
+
const declaredTargets = new Set(renderTargetSlots ?? []);
|
|
23
|
+
const availableSlots = new Set(["source"]);
|
|
24
|
+
let finalOutput = "canvas";
|
|
25
|
+
let enabledIndex = 0;
|
|
26
|
+
for (const pass of passes ?? []) {
|
|
27
|
+
if (pass.enabled === false) continue;
|
|
28
|
+
const needsSwap = pass.needsSwap ?? true;
|
|
29
|
+
const input = pass.input ?? "source";
|
|
30
|
+
const output = pass.output ?? (needsSwap ? "target" : "source");
|
|
31
|
+
if (input === "canvas") throw new Error(`Render pass #${enabledIndex} cannot read from "canvas".`);
|
|
32
|
+
if (input !== "source" && input !== "target" && !declaredTargets.has(input)) throw new Error(`Render pass #${enabledIndex} reads unknown target "${input}".`);
|
|
33
|
+
if (output !== "source" && output !== "target" && output !== "canvas" && !declaredTargets.has(output)) throw new Error(`Render pass #${enabledIndex} writes unknown target "${output}".`);
|
|
34
|
+
if (needsSwap && (input !== "source" || output !== "target")) throw new Error(`Render pass #${enabledIndex} uses needsSwap=true but does not follow source->target flow.`);
|
|
35
|
+
if (!availableSlots.has(input)) throw new Error(`Render pass #${enabledIndex} reads "${input}" before it is written.`);
|
|
36
|
+
const clear = pass.clear ?? false;
|
|
37
|
+
const clearColor = cloneClearColor(pass.clearColor ?? defaultClearColor);
|
|
38
|
+
const preserve = pass.preserve ?? true;
|
|
39
|
+
steps.push({
|
|
40
|
+
pass,
|
|
41
|
+
input,
|
|
42
|
+
output,
|
|
43
|
+
needsSwap,
|
|
44
|
+
clear,
|
|
45
|
+
clearColor,
|
|
46
|
+
preserve
|
|
47
|
+
});
|
|
48
|
+
if (needsSwap) {
|
|
49
|
+
availableSlots.add("target");
|
|
50
|
+
availableSlots.add("source");
|
|
51
|
+
finalOutput = "source";
|
|
52
|
+
} else {
|
|
53
|
+
if (output !== "canvas") availableSlots.add(output);
|
|
54
|
+
finalOutput = output;
|
|
55
|
+
}
|
|
56
|
+
enabledIndex += 1;
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
steps,
|
|
60
|
+
finalOutput
|
|
61
|
+
};
|
|
73
62
|
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { planRenderGraph };
|
|
65
|
+
|
|
66
|
+
//# sourceMappingURL=render-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-graph.js","names":[],"sources":["../../src/lib/core/render-graph.ts"],"sourcesContent":["import type { RenderPass, RenderPassInputSlot, RenderPassOutputSlot } from './types.js';\n\n/**\n * Resolved render-pass step with defaults applied.\n */\nexport interface RenderGraphStep {\n\t/**\n\t * User pass instance.\n\t */\n\tpass: RenderPass;\n\t/**\n\t * Resolved input slot.\n\t */\n\tinput: RenderPassInputSlot;\n\t/**\n\t * Resolved output slot.\n\t */\n\toutput: RenderPassOutputSlot;\n\t/**\n\t * Whether ping-pong swap should be performed after render.\n\t */\n\tneedsSwap: boolean;\n\t/**\n\t * Whether pass should clear output before drawing.\n\t */\n\tclear: boolean;\n\t/**\n\t * Effective clear color.\n\t */\n\tclearColor: [number, number, number, number];\n\t/**\n\t * Whether output should be preserved after pass ends.\n\t */\n\tpreserve: boolean;\n}\n\n/**\n * Immutable render-graph execution plan for one frame.\n */\nexport interface RenderGraphPlan {\n\t/**\n\t * Resolved enabled steps in execution order.\n\t */\n\tsteps: RenderGraphStep[];\n\t/**\n\t * Output slot holding final frame result before presentation.\n\t */\n\tfinalOutput: RenderPassOutputSlot;\n}\n\n/**\n * Creates a copy of RGBA clear color.\n */\nfunction cloneClearColor(\n\tcolor: [number, number, number, number]\n): [number, number, number, number] {\n\treturn [color[0], color[1], color[2], color[3]];\n}\n\n/**\n * Builds validated render graph plan from runtime pass list.\n *\n * @param passes - Runtime passes.\n * @param defaultClearColor - Global clear color fallback.\n * @returns Resolved render graph plan.\n */\nexport function planRenderGraph(\n\tpasses: RenderPass[] | undefined,\n\tdefaultClearColor: [number, number, number, number],\n\trenderTargetSlots?: Iterable<string>\n): RenderGraphPlan {\n\tconst steps: RenderGraphStep[] = [];\n\tconst declaredTargets = new Set(renderTargetSlots ?? []);\n\tconst availableSlots = new Set<RenderPassInputSlot | RenderPassOutputSlot>(['source']);\n\tlet finalOutput: RenderPassOutputSlot = 'canvas';\n\tlet enabledIndex = 0;\n\n\tfor (const pass of passes ?? []) {\n\t\tif (pass.enabled === false) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst needsSwap = pass.needsSwap ?? true;\n\t\tconst input: RenderPassInputSlot = pass.input ?? 'source';\n\t\tconst output: RenderPassOutputSlot = pass.output ?? (needsSwap ? 'target' : 'source');\n\n\t\tif (input === 'canvas') {\n\t\t\tthrow new Error(`Render pass #${enabledIndex} cannot read from \"canvas\".`);\n\t\t}\n\n\t\tconst inputIsNamed = input !== 'source' && input !== 'target';\n\t\tif (inputIsNamed && !declaredTargets.has(input)) {\n\t\t\tthrow new Error(`Render pass #${enabledIndex} reads unknown target \"${input}\".`);\n\t\t}\n\n\t\tconst outputIsNamed = output !== 'source' && output !== 'target' && output !== 'canvas';\n\t\tif (outputIsNamed && !declaredTargets.has(output)) {\n\t\t\tthrow new Error(`Render pass #${enabledIndex} writes unknown target \"${output}\".`);\n\t\t}\n\n\t\tif (needsSwap && (input !== 'source' || output !== 'target')) {\n\t\t\tthrow new Error(\n\t\t\t\t`Render pass #${enabledIndex} uses needsSwap=true but does not follow source->target flow.`\n\t\t\t);\n\t\t}\n\n\t\tif (!availableSlots.has(input)) {\n\t\t\tthrow new Error(`Render pass #${enabledIndex} reads \"${input}\" before it is written.`);\n\t\t}\n\n\t\tconst clear = pass.clear ?? false;\n\t\tconst clearColor = cloneClearColor(pass.clearColor ?? defaultClearColor);\n\t\tconst preserve = pass.preserve ?? true;\n\n\t\tsteps.push({\n\t\t\tpass,\n\t\t\tinput,\n\t\t\toutput,\n\t\t\tneedsSwap,\n\t\t\tclear,\n\t\t\tclearColor,\n\t\t\tpreserve\n\t\t});\n\n\t\tif (needsSwap) {\n\t\t\tavailableSlots.add('target');\n\t\t\tavailableSlots.add('source');\n\t\t\tfinalOutput = 'source';\n\t\t} else {\n\t\t\tif (output !== 'canvas') {\n\t\t\t\tavailableSlots.add(output);\n\t\t\t}\n\t\t\tfinalOutput = output;\n\t\t}\n\n\t\tenabledIndex += 1;\n\t}\n\n\treturn {\n\t\tsteps,\n\t\tfinalOutput\n\t};\n}\n"],"mappings":";;;;AAqDA,SAAS,gBACR,OACmC;AACnC,QAAO;EAAC,MAAM;EAAI,MAAM;EAAI,MAAM;EAAI,MAAM;EAAG;;;;;;;;;AAUhD,SAAgB,gBACf,QACA,mBACA,mBACkB;CAClB,MAAM,QAA2B,EAAE;CACnC,MAAM,kBAAkB,IAAI,IAAI,qBAAqB,EAAE,CAAC;CACxD,MAAM,iBAAiB,IAAI,IAAgD,CAAC,SAAS,CAAC;CACtF,IAAI,cAAoC;CACxC,IAAI,eAAe;AAEnB,MAAK,MAAM,QAAQ,UAAU,EAAE,EAAE;AAChC,MAAI,KAAK,YAAY,MACpB;EAGD,MAAM,YAAY,KAAK,aAAa;EACpC,MAAM,QAA6B,KAAK,SAAS;EACjD,MAAM,SAA+B,KAAK,WAAW,YAAY,WAAW;AAE5E,MAAI,UAAU,SACb,OAAM,IAAI,MAAM,gBAAgB,aAAa,6BAA6B;AAI3E,MADqB,UAAU,YAAY,UAAU,YACjC,CAAC,gBAAgB,IAAI,MAAM,CAC9C,OAAM,IAAI,MAAM,gBAAgB,aAAa,yBAAyB,MAAM,IAAI;AAIjF,MADsB,WAAW,YAAY,WAAW,YAAY,WAAW,YAC1D,CAAC,gBAAgB,IAAI,OAAO,CAChD,OAAM,IAAI,MAAM,gBAAgB,aAAa,0BAA0B,OAAO,IAAI;AAGnF,MAAI,cAAc,UAAU,YAAY,WAAW,UAClD,OAAM,IAAI,MACT,gBAAgB,aAAa,+DAC7B;AAGF,MAAI,CAAC,eAAe,IAAI,MAAM,CAC7B,OAAM,IAAI,MAAM,gBAAgB,aAAa,UAAU,MAAM,yBAAyB;EAGvF,MAAM,QAAQ,KAAK,SAAS;EAC5B,MAAM,aAAa,gBAAgB,KAAK,cAAc,kBAAkB;EACxE,MAAM,WAAW,KAAK,YAAY;AAElC,QAAM,KAAK;GACV;GACA;GACA;GACA;GACA;GACA;GACA;GACA,CAAC;AAEF,MAAI,WAAW;AACd,kBAAe,IAAI,SAAS;AAC5B,kBAAe,IAAI,SAAS;AAC5B,iBAAc;SACR;AACN,OAAI,WAAW,SACd,gBAAe,IAAI,OAAO;AAE3B,iBAAc;;AAGf,kBAAgB;;AAGjB,QAAO;EACN;EACA;EACA"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/// <reference types="@webgpu/types" />
|
|
1
2
|
import type { RenderTargetDefinitionMap } from './types.js';
|
|
2
3
|
/**
|
|
3
4
|
* Concrete render target configuration resolved for current canvas size.
|
|
@@ -37,3 +38,4 @@ export declare function resolveRenderTargetDefinitions(definitions: RenderTarget
|
|
|
37
38
|
* @returns Stable signature string.
|
|
38
39
|
*/
|
|
39
40
|
export declare function buildRenderTargetSignature(resolvedDefinitions: ResolvedRenderTargetDefinition[]): string;
|
|
41
|
+
//# sourceMappingURL=render-targets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-targets.d.ts","sourceRoot":"","sources":["../../src/lib/core/render-targets.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAE5D;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,MAAM,EAAE,gBAAgB,CAAC;CACzB;AA2BD;;;;;;;;GAQG;AACH,wBAAgB,8BAA8B,CAC7C,WAAW,EAAE,yBAAyB,GAAG,SAAS,EAClD,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,gBAAgB,GAC7B,8BAA8B,EAAE,CA0BlC;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACzC,mBAAmB,EAAE,8BAA8B,EAAE,GACnD,MAAM,CAMR"}
|
|
@@ -1,63 +1,62 @@
|
|
|
1
|
-
import { assertUniformName } from
|
|
1
|
+
import { assertUniformName } from "./uniforms.js";
|
|
2
|
+
//#region src/lib/core/render-targets.ts
|
|
2
3
|
/**
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
* Asserts positive finite numeric input for render target options.
|
|
5
|
+
*/
|
|
5
6
|
function assertPositiveFinite(name, value) {
|
|
6
|
-
|
|
7
|
-
throw new Error(`${name} must be a finite number greater than 0`);
|
|
8
|
-
}
|
|
7
|
+
if (!Number.isFinite(value) || value <= 0) throw new Error(`${name} must be a finite number greater than 0`);
|
|
9
8
|
}
|
|
10
9
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
* Resolves a render target dimension from explicit value or scaled canvas size.
|
|
11
|
+
*/
|
|
13
12
|
function resolveDimension(explicitValue, canvasDimension, scale) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
if (explicitValue !== void 0) {
|
|
14
|
+
assertPositiveFinite("RenderTarget dimension", explicitValue);
|
|
15
|
+
return Math.max(1, Math.floor(explicitValue));
|
|
16
|
+
}
|
|
17
|
+
return Math.max(1, Math.floor(canvasDimension * scale));
|
|
19
18
|
}
|
|
20
19
|
/**
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
return resolved;
|
|
20
|
+
* Resolves all render target definitions for a specific canvas size.
|
|
21
|
+
*
|
|
22
|
+
* @param definitions - Declarative definitions.
|
|
23
|
+
* @param canvasWidth - Current canvas width in pixels.
|
|
24
|
+
* @param canvasHeight - Current canvas height in pixels.
|
|
25
|
+
* @param defaultFormat - Fallback texture format.
|
|
26
|
+
* @returns Sorted concrete render target definitions.
|
|
27
|
+
*/
|
|
28
|
+
function resolveRenderTargetDefinitions(definitions, canvasWidth, canvasHeight, defaultFormat) {
|
|
29
|
+
if (!definitions) return [];
|
|
30
|
+
const keys = Object.keys(definitions).sort();
|
|
31
|
+
const resolved = [];
|
|
32
|
+
for (const key of keys) {
|
|
33
|
+
assertUniformName(key);
|
|
34
|
+
const definition = definitions[key];
|
|
35
|
+
const scale = definition?.scale ?? 1;
|
|
36
|
+
assertPositiveFinite("RenderTarget scale", scale);
|
|
37
|
+
const width = resolveDimension(definition?.width, canvasWidth, scale);
|
|
38
|
+
const height = resolveDimension(definition?.height, canvasHeight, scale);
|
|
39
|
+
resolved.push({
|
|
40
|
+
key,
|
|
41
|
+
width,
|
|
42
|
+
height,
|
|
43
|
+
format: definition?.format ?? defaultFormat
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
return resolved;
|
|
50
47
|
}
|
|
51
48
|
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
})
|
|
62
|
-
.join('|');
|
|
49
|
+
* Builds a deterministic signature used to detect render target topology changes.
|
|
50
|
+
*
|
|
51
|
+
* @param resolvedDefinitions - Concrete target definitions.
|
|
52
|
+
* @returns Stable signature string.
|
|
53
|
+
*/
|
|
54
|
+
function buildRenderTargetSignature(resolvedDefinitions) {
|
|
55
|
+
return resolvedDefinitions.map((definition) => {
|
|
56
|
+
return `${definition.key}:${definition.format}:${definition.width}x${definition.height}`;
|
|
57
|
+
}).join("|");
|
|
63
58
|
}
|
|
59
|
+
//#endregion
|
|
60
|
+
export { buildRenderTargetSignature, resolveRenderTargetDefinitions };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=render-targets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render-targets.js","names":[],"sources":["../../src/lib/core/render-targets.ts"],"sourcesContent":["import { assertUniformName } from './uniforms.js';\nimport type { RenderTargetDefinitionMap } from './types.js';\n\n/**\n * Concrete render target configuration resolved for current canvas size.\n */\nexport interface ResolvedRenderTargetDefinition {\n\t/**\n\t * Render target key.\n\t */\n\tkey: string;\n\t/**\n\t * Resolved width in pixels.\n\t */\n\twidth: number;\n\t/**\n\t * Resolved height in pixels.\n\t */\n\theight: number;\n\t/**\n\t * Resolved format.\n\t */\n\tformat: GPUTextureFormat;\n}\n\n/**\n * Asserts positive finite numeric input for render target options.\n */\nfunction assertPositiveFinite(name: string, value: number): void {\n\tif (!Number.isFinite(value) || value <= 0) {\n\t\tthrow new Error(`${name} must be a finite number greater than 0`);\n\t}\n}\n\n/**\n * Resolves a render target dimension from explicit value or scaled canvas size.\n */\nfunction resolveDimension(\n\texplicitValue: number | undefined,\n\tcanvasDimension: number,\n\tscale: number\n): number {\n\tif (explicitValue !== undefined) {\n\t\tassertPositiveFinite('RenderTarget dimension', explicitValue);\n\t\treturn Math.max(1, Math.floor(explicitValue));\n\t}\n\n\treturn Math.max(1, Math.floor(canvasDimension * scale));\n}\n\n/**\n * Resolves all render target definitions for a specific canvas size.\n *\n * @param definitions - Declarative definitions.\n * @param canvasWidth - Current canvas width in pixels.\n * @param canvasHeight - Current canvas height in pixels.\n * @param defaultFormat - Fallback texture format.\n * @returns Sorted concrete render target definitions.\n */\nexport function resolveRenderTargetDefinitions(\n\tdefinitions: RenderTargetDefinitionMap | undefined,\n\tcanvasWidth: number,\n\tcanvasHeight: number,\n\tdefaultFormat: GPUTextureFormat\n): ResolvedRenderTargetDefinition[] {\n\tif (!definitions) {\n\t\treturn [];\n\t}\n\n\tconst keys = Object.keys(definitions).sort();\n\tconst resolved: ResolvedRenderTargetDefinition[] = [];\n\n\tfor (const key of keys) {\n\t\tassertUniformName(key);\n\t\tconst definition = definitions[key];\n\t\tconst scale = definition?.scale ?? 1;\n\t\tassertPositiveFinite('RenderTarget scale', scale);\n\n\t\tconst width = resolveDimension(definition?.width, canvasWidth, scale);\n\t\tconst height = resolveDimension(definition?.height, canvasHeight, scale);\n\n\t\tresolved.push({\n\t\t\tkey,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tformat: definition?.format ?? defaultFormat\n\t\t});\n\t}\n\n\treturn resolved;\n}\n\n/**\n * Builds a deterministic signature used to detect render target topology changes.\n *\n * @param resolvedDefinitions - Concrete target definitions.\n * @returns Stable signature string.\n */\nexport function buildRenderTargetSignature(\n\tresolvedDefinitions: ResolvedRenderTargetDefinition[]\n): string {\n\treturn resolvedDefinitions\n\t\t.map((definition) => {\n\t\t\treturn `${definition.key}:${definition.format}:${definition.width}x${definition.height}`;\n\t\t})\n\t\t.join('|');\n}\n"],"mappings":";;;;;AA4BA,SAAS,qBAAqB,MAAc,OAAqB;AAChE,KAAI,CAAC,OAAO,SAAS,MAAM,IAAI,SAAS,EACvC,OAAM,IAAI,MAAM,GAAG,KAAK,yCAAyC;;;;;AAOnE,SAAS,iBACR,eACA,iBACA,OACS;AACT,KAAI,kBAAkB,QAAW;AAChC,uBAAqB,0BAA0B,cAAc;AAC7D,SAAO,KAAK,IAAI,GAAG,KAAK,MAAM,cAAc,CAAC;;AAG9C,QAAO,KAAK,IAAI,GAAG,KAAK,MAAM,kBAAkB,MAAM,CAAC;;;;;;;;;;;AAYxD,SAAgB,+BACf,aACA,aACA,cACA,eACmC;AACnC,KAAI,CAAC,YACJ,QAAO,EAAE;CAGV,MAAM,OAAO,OAAO,KAAK,YAAY,CAAC,MAAM;CAC5C,MAAM,WAA6C,EAAE;AAErD,MAAK,MAAM,OAAO,MAAM;AACvB,oBAAkB,IAAI;EACtB,MAAM,aAAa,YAAY;EAC/B,MAAM,QAAQ,YAAY,SAAS;AACnC,uBAAqB,sBAAsB,MAAM;EAEjD,MAAM,QAAQ,iBAAiB,YAAY,OAAO,aAAa,MAAM;EACrE,MAAM,SAAS,iBAAiB,YAAY,QAAQ,cAAc,MAAM;AAExE,WAAS,KAAK;GACb;GACA;GACA;GACA,QAAQ,YAAY,UAAU;GAC9B,CAAC;;AAGH,QAAO;;;;;;;;AASR,SAAgB,2BACf,qBACS;AACT,QAAO,oBACL,KAAK,eAAe;AACpB,SAAO,GAAG,WAAW,IAAI,GAAG,WAAW,OAAO,GAAG,WAAW,MAAM,GAAG,WAAW;GAC/E,CACD,KAAK,IAAI"}
|
package/dist/core/renderer.d.ts
CHANGED
|
@@ -17,3 +17,4 @@ export declare function findDirtyFloatRanges(previous: Float32Array, next: Float
|
|
|
17
17
|
* @throws {Error} On WebGPU unavailability, shader compilation issues, or runtime setup failures.
|
|
18
18
|
*/
|
|
19
19
|
export declare function createRenderer(options: RendererOptions): Promise<Renderer>;
|
|
20
|
+
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/lib/core/renderer.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAMX,QAAQ,EACR,eAAe,EAIf,MAAM,YAAY,CAAC;AAgYpB;;;;;GAKG;AACH,wBAAgB,oBAAoB,CACnC,QAAQ,EAAE,YAAY,EACtB,IAAI,EAAE,YAAY,EAClB,iBAAiB,SAAwB,GACvC,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAwCzC;AAsFD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,CA69BhF"}
|