@motion-core/motion-gpu
Version:
Framework-agnostic WebGPU runtime for fullscreen WGSL shaders with explicit Svelte, React, and Vue adapter entrypoints.
86 lines (85 loc) • 2.65 kB
JavaScript
//#region src/lib/core/render-graph.ts
/**
* Creates a copy of RGBA clear color.
*/
function cloneClearColor(color) {
return [
color[0],
color[1],
color[2],
color[3]
];
}
/**
* Builds validated render graph plan from runtime pass list.
*
* @param passes - Runtime passes.
* @param defaultClearColor - Global clear color fallback.
* @returns Resolved render graph plan.
*/
function planRenderGraph(passes, defaultClearColor, renderTargetSlots) {
const steps = [];
const computeSteps = [];
const renderSteps = [];
const declaredTargets = new Set(renderTargetSlots ?? []);
const availableSlots = new Set(["source"]);
let finalOutput = "canvas";
let enabledIndex = 0;
for (const pass of passes ?? []) {
if (pass.enabled === false) continue;
if ("isCompute" in pass && pass.isCompute === true) {
const step = {
kind: "compute",
pass,
input: "source",
output: "source",
needsSwap: false,
clear: false,
clearColor: cloneClearColor(defaultClearColor),
preserve: true
};
steps.push(step);
computeSteps.push(step);
continue;
}
const rp = pass;
const needsSwap = rp.needsSwap ?? true;
const input = rp.input ?? "source";
const output = rp.output ?? (needsSwap ? "target" : "source");
if (input === "canvas") throw new Error(`Render pass #${enabledIndex} cannot read from "canvas".`);
if (input !== "source" && input !== "target" && !declaredTargets.has(input)) throw new Error(`Render pass #${enabledIndex} reads unknown target "${input}".`);
if (output !== "source" && output !== "target" && output !== "canvas" && !declaredTargets.has(output)) throw new Error(`Render pass #${enabledIndex} writes unknown target "${output}".`);
if (needsSwap && (input !== "source" || output !== "target")) throw new Error(`Render pass #${enabledIndex} uses needsSwap=true but does not follow source->target flow.`);
if (!availableSlots.has(input)) throw new Error(`Render pass #${enabledIndex} reads "${input}" before it is written.`);
const step = {
kind: "render",
pass,
input,
output,
needsSwap,
clear: rp.clear ?? false,
clearColor: cloneClearColor(rp.clearColor ?? defaultClearColor),
preserve: rp.preserve ?? true
};
steps.push(step);
renderSteps.push(step);
if (needsSwap) {
availableSlots.add("target");
availableSlots.add("source");
finalOutput = "source";
} else {
if (output !== "canvas") availableSlots.add(output);
finalOutput = output;
}
enabledIndex += 1;
}
return {
steps,
computeSteps,
renderSteps,
finalOutput
};
}
//#endregion
export { planRenderGraph };
//# sourceMappingURL=render-graph.js.map