Advance M8-M11 parity workflows
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-17 04:37:07 -04:00
parent 7c16b279ae
commit 0fe8d2bb56
324 changed files with 31920 additions and 863 deletions

View File

@@ -1,6 +1,8 @@
export {
COMPOSITOR_WEBGPU_NODE_ALLOWLIST,
CompositorFrameCache,
CompositorValidationError,
compileCompositorWebGPUPlan,
compositorFrameCacheKey,
executeCompositorGraph,
executeCompositorGraphCached,
@@ -12,4 +14,6 @@ export type {
CompositorExecutionResult,
CompositorGraphIR,
CompositorImageBuffer,
CompositorWebGPUInstructionIR,
CompositorWebGPUPlanIR,
} from "../../../protocol/compositor";

View File

@@ -0,0 +1,83 @@
import {
COMPOSITOR_BUDGET,
CompositorValidationError,
compileCompositorWebGPUPlan,
type CompositorImageBuffer,
type CompositorWebGPUInstructionIR,
} from "../../../protocol/compositor";
function wgslFloat(value: number): string {
if (!Number.isFinite(value)) throw new CompositorValidationError("COMPOSITOR_GRAPH_INVALID", "WebGPU compositor constant is not finite");
const text = String(Math.fround(value));
return text.includes(".") || /e/i.test(text) ? text : `${text}.0`;
}
function instructionWGSL(instruction: CompositorWebGPUInstructionIR): string {
if (instruction.type === "CONSTANT_COLOR") {
return `color = vec4<f32>(${instruction.color.map(wgslFloat).join(", ")});`;
}
if (instruction.type === "EXPOSURE") {
return `color = vec4<f32>(color.rgb * ${wgslFloat(2 ** instruction.exposure)}, color.a);`;
}
if (instruction.type === "INVERT") return "color = vec4<f32>(vec3<f32>(1.0) - color.rgb, color.a);";
return "";
}
export async function requestCompositorWebGPUDevice(): Promise<GPUDevice> {
if (!navigator.gpu) throw new CompositorValidationError("WEBGPU_RENDERER_UNAVAILABLE", "WebGPU is unavailable for the compositor allowlist");
const adapter = await navigator.gpu.requestAdapter({ powerPreference: "high-performance" });
if (!adapter) throw new CompositorValidationError("WEBGPU_RENDERER_UNAVAILABLE", "No WebGPU adapter is available for the compositor allowlist");
return adapter.requestDevice();
}
export async function executeCompositorGraphWebGPU(
device: GPUDevice,
value: unknown,
width: number,
height: number,
): Promise<CompositorImageBuffer> {
const plan = compileCompositorWebGPUPlan(value);
const pixelCount = width * height;
const byteLength = pixelCount * 16;
if (!Number.isSafeInteger(width) || !Number.isSafeInteger(height) || width < 1 || height < 1 ||
width > COMPOSITOR_BUDGET.maxDimension || height > COMPOSITOR_BUDGET.maxDimension ||
!Number.isSafeInteger(pixelCount) || pixelCount > COMPOSITOR_BUDGET.maxPixels ||
byteLength > COMPOSITOR_BUDGET.maxImageBytes || byteLength > device.limits.maxStorageBufferBindingSize ||
byteLength > device.limits.maxBufferSize) {
throw new CompositorValidationError("COMPOSITOR_BUDGET_EXCEEDED", "WebGPU compositor output exceeds the image or device budget");
}
const output = device.createBuffer({ label: "Compositor WebGPU output", size: byteLength, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });
const readback = device.createBuffer({ label: "Compositor WebGPU readback", size: byteLength, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ });
try {
device.pushErrorScope("validation");
const module = device.createShaderModule({ label: `Compositor ${plan.graphId}`, code: /* wgsl */`
@group(0) @binding(0) var<storage, read_write> pixels: array<vec4<f32>>;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) id: vec3<u32>) {
if (id.x >= ${pixelCount}u) { return; }
var color = vec4<f32>(0.0);
${plan.instructions.map(instructionWGSL).filter(Boolean).join("\n ")}
pixels[id.x] = color;
}` });
const pipeline = device.createComputePipeline({ layout: "auto", compute: { module, entryPoint: "main" } });
const bindGroup = device.createBindGroup({ layout: pipeline.getBindGroupLayout(0), entries: [{ binding: 0, resource: { buffer: output } }] });
const encoder = device.createCommandEncoder();
const pass = encoder.beginComputePass();
pass.setPipeline(pipeline);
pass.setBindGroup(0, bindGroup);
pass.dispatchWorkgroups(Math.ceil(pixelCount / 64));
pass.end();
encoder.copyBufferToBuffer(output, 0, readback, 0, byteLength);
device.queue.submit([encoder.finish()]);
await readback.mapAsync(GPUMapMode.READ);
const data = new Float32Array(readback.getMappedRange().slice(0));
readback.unmap();
const validationError = await device.popErrorScope();
if (validationError) throw new CompositorValidationError("COMPOSITOR_NODE_UNSUPPORTED", `WebGPU compositor shader validation failed: ${validationError.message ?? "unknown error"}`);
return { width, height, data, colorSpace: "LINEAR_SRGB" };
}
finally {
output.destroy();
readback.destroy();
}
}