Files
workinf_Blender_Wasm/web/protocol/render-capabilities.ts
mes123456 0fe8d2bb56
Some checks are pending
M6 deployable RC / quick (push) Waiting to run
M6 deployable RC / chromium (push) Blocked by required conditions
M6 deployable RC / release (push) Blocked by required conditions
Advance M8-M11 parity workflows
2026-08-17 04:37:07 -04:00

66 lines
3.0 KiB
TypeScript

import { blockedGate, capabilityIssue, readyGate, type CapabilityGateResult } from "./capability-gates";
import type { ShaderNodeType } from "./shader-graph";
export type RenderBackend = "WEBGL2" | "WEBGPU";
export type PostProcessPass = "FXAA" | "BLOOM" | "SSAO" | "SSR" | "TAA" | "DOF" | "MOTION_BLUR";
export type RenderCapabilityRequest =
| { kind: "ARBITRARY_SHADER"; nodeTypes: string[] }
| { kind: "VOLUME" }
| { kind: "SUBSURFACE" }
| { kind: "WEBGPU_BACKEND" }
| { kind: "POSTPROCESS"; passes: PostProcessPass[] };
export interface RenderCapabilityContext {
webgpuAvailable?: boolean;
webgpuRendererBundled?: boolean;
supportedShaderNodes?: ReadonlySet<ShaderNodeType>;
supportedPostProcessPasses?: ReadonlySet<PostProcessPass>;
volumeRendererAvailable?: boolean;
subsurfaceRendererAvailable?: boolean;
}
const boundedShaderNodes = new Set<ShaderNodeType>([
"RGB",
"VALUE",
"MATH",
"IMAGE_TEXTURE",
"NORMAL_MAP",
"PRINCIPLED",
"MATERIAL_OUTPUT",
]);
export function gateRenderCapability(
request: RenderCapabilityRequest,
context: RenderCapabilityContext = {},
): CapabilityGateResult {
if (request.kind === "ARBITRARY_SHADER") {
const supported = context.supportedShaderNodes ?? boundedShaderNodes;
const unsupported = [...new Set(request.nodeTypes.filter((type) => type === "UNSUPPORTED" || !supported.has(type as ShaderNodeType)))].sort();
if (unsupported.length === 0) return readyGate("PBR-012", "BOUNDED_SHADER_GRAPH");
return blockedGate("PBR-012", "ARBITRARY_SHADER", [
capabilityIssue("SHADER_NODE_UNSUPPORTED", `Web shader compiler does not support: ${unsupported.join(", ")}`, "nodeTypes"),
]);
}
if (request.kind === "VOLUME") {
return context.volumeRendererAvailable
? readyGate("PBR-012", "VOLUME")
: blockedGate("PBR-012", "VOLUME", [capabilityIssue("VOLUME_SHADER_UNAVAILABLE", "Volume transport is not available in the Web renderer")]);
}
if (request.kind === "SUBSURFACE") {
return context.subsurfaceRendererAvailable
? readyGate("PBR-012", "SUBSURFACE")
: blockedGate("PBR-012", "SUBSURFACE", [capabilityIssue("SUBSURFACE_SHADER_UNAVAILABLE", "Blender-compatible subsurface scattering is not available in the Web renderer")]);
}
if (request.kind === "WEBGPU_BACKEND") {
if (context.webgpuAvailable && context.webgpuRendererBundled) return readyGate("PBR-012", "WEBGPU_BACKEND");
const reason = context.webgpuAvailable ? "The WebGPU renderer bundle is not installed" : "WebGPU is unavailable in this browser or device";
return blockedGate("PBR-012", "WEBGPU_BACKEND", [capabilityIssue("WEBGPU_RENDERER_UNAVAILABLE", reason)]);
}
const supported = context.supportedPostProcessPasses ?? new Set<PostProcessPass>();
const unsupported = [...new Set(request.passes.filter((pass) => !supported.has(pass)))];
return unsupported.length === 0
? readyGate("PBR-012", "POSTPROCESS")
: blockedGate("PBR-012", "POSTPROCESS", [capabilityIssue("POSTPROCESS_PASS_UNAVAILABLE", `Unsupported post-process passes: ${unsupported.join(", ")}`, "passes")]);
}