UNPKG

@motion-core/motion-gpu

Version:

Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte, React, and Vue adapter entrypoints.

94 lines (93 loc) 3.99 kB
import { assertFloatRenderableFormat, assertFloatSampledFormat, assertRenderableFormat, createFormatCapabilityError } from "./format-capabilities.js"; import { builtInRenderPassBrand } from "./pass-brand.js"; import { isBuiltInRenderPass, isManagedComputePass, isManagedFeedbackPass } from "./pass-contract.js"; //#region src/lib/core/render-format-validation.ts /** Validates the renderer-owned working texture used by scene and presentation pipelines. */ function validateWorkingFormat(format, deviceFeatures) { const diagnostic = { format, target: "workingFormat", pass: "Scene pipeline", deviceFeatures }; assertFloatRenderableFormat(diagnostic); assertFloatSampledFormat(diagnostic); } /** Validates named color targets and returns their effective formats. */ function validateRenderTargetFormats(definitions, defaultFormat, deviceFeatures) { const formats = {}; for (const key of Object.keys(definitions ?? {}).sort()) { const format = definitions?.[key]?.format ?? defaultFormat; assertRenderableFormat({ format, target: key, pass: "Named render target", deviceFeatures }); formats[key] = format; } return formats; } function resolveInputFormat(slot, workingFormat, namedFormats) { return slot === "source" || slot === "target" ? workingFormat : namedFormats[slot]; } function resolveOutputFormat(slot, workingFormat, namedFormats) { if (slot === "source" || slot === "target") return workingFormat; if (slot === "canvas") return workingFormat; return namedFormats[slot]; } /** Validates only nominally branded MotionGPU render passes; structural custom passes stay open. */ function validateBuiltInRenderPassFormats(input) { for (const candidate of input.passes) { if (candidate.enabled === false || !isBuiltInRenderPass(candidate)) continue; const pass = candidate; const contract = candidate[builtInRenderPassBrand]; const inputSlot = pass.input ?? "source"; const outputSlot = pass.output ?? (pass.needsSwap ?? true ? "target" : "source"); const inputFormat = resolveInputFormat(inputSlot, input.workingFormat, input.namedFormats); const outputFormat = resolveOutputFormat(outputSlot, input.workingFormat, input.namedFormats); if (inputFormat !== void 0) assertFloatSampledFormat({ format: inputFormat, target: String(inputSlot), pass: contract.passName, deviceFeatures: input.deviceFeatures }); if (outputFormat !== void 0) assertFloatRenderableFormat({ format: outputFormat, target: String(outputSlot), pass: contract.passName, deviceFeatures: input.deviceFeatures }); } } /** Resolves the slot sampled by the implicit presentation pass for a static pass list. */ function resolvePresentationSourceSlot(passes) { let finalOutput = null; for (const candidate of passes) { if (candidate.enabled === false || isManagedComputePass(candidate) || isManagedFeedbackPass(candidate)) continue; const pass = candidate; finalOutput = pass.needsSwap ?? true ? "source" : pass.output ?? "source"; } return finalOutput; } /** Validates the implicit fullscreen presentation pass input before graph execution. */ function validatePresentationSourceFormat(input) { const format = resolveOutputFormat(input.slot, input.workingFormat, input.namedFormats); if (format === void 0) return; const capabilities = assertFloatSampledFormat({ format, target: String(input.slot), pass: "Presentation pass", deviceFeatures: input.deviceFeatures }); if (input.requiresFilterableInput && !capabilities.filterable) throw createFormatCapabilityError({ target: String(input.slot), format, pass: "Presentation pass", capability: "filterable float texture sampling", detail: "End the graph on workingFormat or enable the format-specific filtering feature." }); } //#endregion export { resolvePresentationSourceSlot, validateBuiltInRenderPassFormats, validatePresentationSourceFormat, validateRenderTargetFormats, validateWorkingFormat }; //# sourceMappingURL=render-format-validation.js.map