@forgeax/engine-vite-plugin-shader
v0.1.38
Published
Vite plugin: thin forwarding shell over @forgeax/engine-shader-compiler — 4 hook (load/transform/generateBundle/handleHotUpdate) + ShaderError → RollupLog wrap (hint 顶层 + meta 双投影).
Readme
@forgeax/engine-vite-plugin-shader
本包是
@forgeax/engine-shader-compiler的 Vite 插件薄壳,对齐 Vite 4-hook 模型(load / transform / generateBundle / handleHotUpdate)全装入,约束 transform 仅 forwarding 调compileShader,不重新实现编译逻辑(AC-02)。 AI 用户(含 agentic AI runtime)通过import { forgeaxShader } from '@forgeax/engine-vite-plugin-shader'在vite.config.ts里注入 plugin,得到 build-time.wgsl→ 三件套 + manifest 落盘 + ShaderError → RollupLog wrap(plan-strategy §S-6 + §S-7)。
Engine inputs and ABI transport
Engine shader loading is kept in src/engine-inputs/. load-engine-shader-entries.ts
owns the canonical WGSL entry and import closure; shared-engine-inputs.ts
owns packaged dev/prod manifest projection. Both paths feed the same plugin
manifest owner and the same SHADER_MANIFEST_PATH constant.
The standalone buildEngineShaderManifest builder can combine the admitted
shared engine projection with freshly compiled materialPackages. Custom
materials use the same source/import/cook path and do not trigger another
engine-wide compile. Result arrays are independent of the base manifest.
Production and development publish the same versioned manifest: each WGSL source
has one SHA-256 identity, while repeated source lines are stored once in a
shared fragment table. Material variants and direct entries refer to those
identities. The individual .wgsl sidecars remain available for inspection.
Standalone point-shadow requests without authored packages reuse an admitted
packaged point profile when present. Missing inputs and explicit
FORGEAX_ENGINE_SHADER_SOURCE_BUILD=1 requests retain source compilation;
authored point-shadow packages also retain their source route. Invalid shared
inputs and missing authored sources remain explicit failures.
The packaged input roster contains base-ssao and point-ssao. SSAO is an
independent fullscreen entry, so the same projection used for transferred inputs
removes it when disabled without recompiling material shaders. All four public
point-shadow/SSAO configurations remain available. The release producer removes
obsolete no-SSAO copies while preserving declarations and other live profiles.
The public VIEW_ABI export is typed transport metadata for
forgeax_view::common: group 0, binding 0, and the stable 1024-byte upload shape. It contains no live WebGPU object. Consumers should use the manifest
and reflection output; they must not add a second manifest URL or hard-code a
carrier-side index.
Authored material packages are compiled as a complete Pass set through
cookMaterialAsset. Vite uses the compiler's source discovery, retains every
module and capability variant, and publishes shared modules once. A failed
later Pass leaves the previous complete material generation installed; a
successful edit replaces all of that package's program rows together.
Pack-owned runtime materials use publishAuthoredMaterialShaders: false so
Vite supplies build artifacts without creating a second runtime material
registration. Their cooked record remains the runtime publication authority.
The plugin releases its manifest, variant, authored-material, and packaged-input
payloads in Vite's closeBundle lifecycle. A subsequent buildStart loads its
inputs again, including after a dev-server restart. Closed servers must not keep
another copy of the shader fleet alive through retained plugin callbacks.
形态铁律
- 薄壳 forwarding —— 4 hook(
load/transform/generateBundle/handleHotUpdate)全部装入,但transform仅 forwarding 调@forgeax/engine-shader-compiler.compileShader,不重新实现编译逻辑(AC-02 闸门)。 - peerDep vite —— 插件签名走
'vite'的Plugin类型;vite 由 host 应用提供(peerDependencies: { vite: ">=4" })。 - hint 双投影 ——
toRollupLog(err)同时把ShaderError.hint放到RollupLog顶层与meta.hint,AI 用户消费走err.hint顶层(charter 命题 5 一致抽象 + 命题 4 显式失败;plan-strategy §S-7)。 - emitFile 必经路径 ——
generateBundle走this.emitFile({ type: 'asset', fileName, source }),禁止直接 mutatebundle[fileName](Rollup 官方 danger callout,research Finding 3)。 - HMR 默认传播 ——
handleHotUpdate(ctx)返回ctx.modules即可;客户端import.meta.hot.accept(由transform注入字面量(whitespace-sensitive)。
API 索引
| 入口 | 说明 |
|:--|:--|
| forgeaxShader(options?) | Vite plugin factory,返回含 4 hook + resolveId + load(virtual module 通道)的 Plugin 对象(w14 落地 + feat-20260608 M3 扩展) |
| toRollupLog(err) | ShaderError → RollupLog(hint 双投影,w14 落地) |
| ForgeaXShaderRollupLog | RollupLog 扩展类型(hint 顶层投影是 forgeax 自定义字段) |
| virtual:forgeax/bundler | Build-time virtual module emitting forgeaxBundlerAdapter() factory(feat-20260608 M3,详见下节) |
virtual:forgeax/bundler virtual module
feat-20260608-create-app-param-surface-trim / M3 / D-4 q7-A: a single inline-emit virtual module that surfaces the build-time bundler-injected wiring (
shaderManifestUrl+ optionalimportTransport) as aBundlerOptions-compatible factory call. AI users discover the entry through one import line; the manifest URL stays a single SSOT inside the plugin emit path.
import { forgeaxBundlerAdapter } from 'virtual:forgeax/bundler';
// One-screen takeoff: pass adapter() directly as the third arg.
const app = await createApp(canvas, {}, forgeaxBundlerAdapter());
// Spread form when a real dev import-transport must be wired:
import { createDevImportTransport } from '@forgeax/engine-runtime';
const bundler = { ...forgeaxBundlerAdapter(), importTransport: createDevImportTransport() };
const renderer = await createRenderer(canvas, {}, bundler);Form invariants:
forgeaxShader(options?)mountsresolveId(claims the virtual id) +load(returns the inline adapter source) hooks alongside the 4 build hooks. Same plugin, no second package.- The adapter source closes over the plugin's
SHADER_MANIFEST_URLconstant -- a single SSOT shared withgenerateBundleemit + devconfigureServermiddleware.apps/source never types the literal'/shaders/manifest.json'; CI grep gate (AC-12) enforces zero hits. - The adapter source does NOT import
@forgeax/engine-app. The return value relies on TypeScript structural typing to satisfyBundlerOptionsat every callsite (D-4 q7-A reverse-coupling guard:vite-plugin-shader->@forgeax/engine-appis forbidden by the package layering). - The TypeScript ambient module declaration (
declare module 'virtual:forgeax/bundler') ships in each app'ssrc/vite-env.d.tsso per-apptsc --noEmitresolves the import without each app having to depend on the plugin's package types.
关联
- 决策 plan-strategy §S-6 4 hook 分工 / §S-7 ShaderError wrap(hint 双投影)/ §6 M2 范围。
- 上游
@forgeax/engine-shader-compiler提供compileShader纯函数 +ShaderError5 字段顶层错误类。 - 集成端
apps/hello/triangle/vite.config.tsM2 注入验证(w15)+ M3 替换 fixture 为 pbr.wgsl。
SSAO is included by default, matching the runtime StandardProfile.ssao switch. engineEntries.hdrpSsao: false explicitly strips it for a producer that never supports AO; requesting AO with that manifest produces a renderer error.
