Advance WebGPU volume and bounded workflows

This commit is contained in:
mes123456
2026-08-14 18:08:29 -04:00
parent 3da1dfc804
commit 68d50f810f
119 changed files with 9028 additions and 430 deletions

View File

@@ -0,0 +1,242 @@
# VDB -> NanoVDB -> WebGPU 实施方案
更新时间2026-08-13
## 1. 范围与完成定义
VDB 重新纳入 N-015/N-019/N-023/N-026。产品链路固定为桌面工具或受控服务端使用
OpenVDB 读取 `.vdb`,转换为 NanoVDB浏览器只读取受校验的 `.nvdb` 分块,并由 WebGPU
执行稀疏树遍历、采样和体积积分。
浏览器 Blender WASM 必须继续保持 `WITH_OPENVDB=OFF``WITH_OPENVDB=ON`
`WITH_NANOVDB=ON` 只能证明编译/链接选项,不能证明以下能力:
- 外部 VDB 的受限读取、分块上传、失败恢复和缓存淘汰;
- NanoVDB 数据布局与 WGSL 遍历正确;
- density/temperature/color/emission/velocity 的 Blender 材质语义;
- `.blend` 保存、转换产物绑定、重开和资源丢失诊断;
- 与 Blender 5.2 桌面图像/数值 golden 一致;
- 大体积、损坏输入、OOM、取消和 Chromium WebGPU 性能门。
只有上述链路均有真实资源与自动测试证据时VDB 才能从 `BLOCKED` 转为可发布能力。
## 2. 架构和信任边界
```text
.blend + .vdb
|
| source SHA-256, grid allowlist, budgets
v
Desktop/Server Blender 5.2 + OpenVDB + NanoVDB
|
| deterministic .nvdb + manifest.json + converter identity
v
Project asset store / HTTP Range / OPFS content-addressed cache
|
| contiguous ranges, per-chunk SHA-256, whole-bundle SHA-256
v
Chromium Storage/Render Worker
|
| bounded GPU pages, validated grid ranges and transforms
v
WebGPU storage buffers + WGSL NanoVDB traversal + volume integrator
```
信任边界如下:
1. `.vdb` 是不可信输入,只允许进入桌面/服务端转换沙箱;浏览器不加载 OpenVDB。
2. 转换器输出也不直接信任。浏览器先校验 schema、路径、预算、连续 range、分块 hash 和整包
hash再允许 GPU 上传。
3. manifest 是持久化真源路径必须位于项目资源根HTTP 必须返回精确 `206 Content-Range`
OPFS 必须使用 content-addressed key。
4. GPU resident set 独立受限CPU/网络总包预算不能代替 GPU 预算。
5. Main 只保存源绑定、转换版本、产物 hash、grid/material 映射;不能把临时 URL 或未验证
GPU 状态写成已完成资源。
## 3. 产物与协议
### 3.1 转换请求
`VDBConversionRequestIR` 固定记录 schema、job、项目内 `.vdb` 路径、源字节数/hash、源 grid
清单、选择 grid、量化策略、分块大小和输出 `.nvdb` 路径。`VDBConverterIdentityIR` 固定记录
DESKTOP/SERVER、Blender/OpenVDB/NanoVDB 版本和转换器可执行文件 hash。
同一源 hash、转换器 identity、选择 grid、量化和 chunk size 必须产生相同的 bundle hash分别生成
但语义相同的 OpenVDB fixture 允许因文件 UUID 而有不同源 hash其 NanoVDB grid/bundle 应一致。
job ID 和输出路径不进入内容键;不能仅以文件名作为缓存键。
### 3.2 NanoVDB bundle manifest
`NanoVDBBundleManifestIR` schema 1 记录:
-`.vdb` 与 bundle `.nvdb` 的项目路径、长度和 SHA-256以及包含 grid/量化/chunk 参数的
canonical conversion request SHA-256
- 每个 grid 的 value type/class/semantic、active voxel、标准 NanoVDB segment 范围、内部 grid
payload 范围、index/world bounds、voxel size 和 4x4 index-to-world文件内 payload 偏移不要求
对齐,上传到 GPU storage buffer 时另行满足 32-byte alignment
- density/temperature/color/emission/velocity 材质绑定和受限参数;
- 32-byte 对齐、连续覆盖整个 bundle 的 chunks以及每块 SHA-256
- `NANOVDB_STORAGE_BUFFER`、GPU page/resident budget 和 `volume-wgsl-v1` 语义版本。
首期 GPU value type 白名单为 Float32、Float16、Vec3f32、Vec4f32。Double、Bool、Int、Point
Index、未知 grid class 返回 `NANOVDB_GRID_UNSUPPORTED`,不进行隐式转换。
### 3.3 浏览器流送
`streamNanoVDBChunks` 串行执行 range read -> 分块 hash -> consumer upload并在每块后报告字节
进度。串行是首期的确定性基线;通过内存峰值和取消测试后才能加入最多 4 路的有界并发。
`createHttpNanoVDBRangeSource` 只接受 HTTP 206`Content-Range` 的起点、终点、总长度必须
与 manifest 精确一致。resumable adapter 对临时状态和网络异常做有界重试response body 中断后
保留已收字节,以相同 ETag 的 `If-Range` 从精确偏移续传,干净结束的短响应仍直接拒绝。
OPFS 适配器以 `bundleSha256/chunkIndex` 为 key 原子提交。所有块校验完成后才提交完整 bundle
manifest中断留下的 staging 数据不会被重开流程发现,重开后的每次 chunk 读取仍重新校验 SHA-256。
## 4. 材质与渲染语义
首期声明 `Principled Volume` 有界子集:
| Blender 语义 | NanoVDB/manifest | WebGPU 行为 |
| --- | --- | --- |
| Density | `densityGrid` + `densityScale` | 非负消光/散射密度 |
| Temperature | `temperatureGrid` + scale | 只在 Blackbody emission 开启时采样 |
| Color | `colorGrid` 或常量颜色 | 线性工作空间散射颜色 |
| Emission | `emissionGrid` + scale | 线性辐射项;负值钳制并报告 |
| Velocity | `velocityGrid` | 首期仅保留/报告motion blur 未验证前不消费 |
| Anisotropy | manifest scalar | Henyey-Greenstein范围 `[-0.99, 0.99]` |
首期只开放单 Volume、单散射/吸收积分、线性/最近采样、对象变换和 scene exposure。多重散射、
体积阴影、烟火黑体、motion blur、多个 volume overlap、Cycles 等价保持独立阻断。
WGSL 实现必须包括 NanoVDB header/version/magic 检查、root/internal/leaf address 上界检查、空
节点跳跃、index-to-world/world-to-index、ray-box intersection、自适应步长上限、early
transmittance termination 和 NaN 防护。shader 不能通过越界 buffer read 猜测无效节点。
## 5. 保存与重开
保存流程分两层:
1. Blender Main 中的 Volume 保留项目相对 `.vdb` 引用和 grid/material 参数。
2. Web project manifest 保存 `sourceSha256 -> conversion request -> bundleSha256` 绑定、转换器
identity、chunk manifest 和 OPFS/object-store 定位信息。
重开时先比较 `.blend` Volume 引用、源 hash 和 bundle manifest。源改变、converter 改变、bundle
缺失、hash 不符或 shader semantic version 不符均返回结构化 `BLOCKED` 并要求重转;不能静默
复用旧缓存。保存成功标准包括:清空 Worker、重新打开 `.blend`、重新发现 bundle、逐块复验、
恢复同一 grid/material 映射并得到相同像素/采样摘要。
## 6. 详细任务分解
### Phase 0能力声明与协议
- `VDB-001`:删除浏览器伪 decoder 入口raw `.vdb` 浏览器解码固定返回
`VDB_CONVERSION_REQUIRED`。状态:`done_current_scope`
- `VDB-002`:实现 source manifest、conversion request、converter identity、路径/hash/预算门。
状态:`done_current_scope`
- `VDB-003`:实现 NanoVDB bundle/grid/material/GPU/chunk manifest、range plan、分块与整包
hash 校验。状态:`done_current_scope`
- `VDB-004`:实现串行 range streamer 和严格 HTTP 206 适配器。状态:`done_current_scope`
- `VDB-005`:能力门分别报告 desktop converter、server converter、stream、WebGPU renderer
禁止单一布尔值概括全链路。状态:`done_current_scope`
### Phase 1真实资源与转换器
- `VDB-010`:在本机资源库收录许可证明确的 tiny smoke、density+temperature、color、level-set、
大稀疏体积和损坏文件;记录来源 URL、许可证、原始 SHA-256。状态`done_current_scope`
资源库为 `/home/mes123456/resource-library/blender-web-vdb`,含 14 条受 hash 约束记录。
- `VDB-011`:建立 native/desktop CMake presetOpenVDB 只在该目标开启;固定 Blender 5.2、
OpenVDB/NanoVDB 版本并生成可执行文件 hash。状态`done_current_scope`desktop target 实际
链接 OpenVDB 13.0/TBB 并生成 NanoVDB 32.9,浏览器仍保持 `WITH_OPENVDB=OFF`
- `VDB-012`:实现 grid inventory 预扫、allowlist、active voxel/内存/输出预算和取消,调用官方
OpenVDB/NanoVDB API 写出确定性 `.nvdb`。状态:`done_current_scope`inventory、allowlist、源/输出/
grid/active voxel 预算、LOSSLESS/FP16、report、确定性、cancel-file、timeout 和失败原子清理已验证。
- `VDB-013`:实现服务端 job APIcontent hash 幂等、上传/转换/下载、进度、超时、取消、日志、
不可信输入隔离和输出签名。状态:`done_current_scope`;当前以 bubblewrap、只读 root、资源限制、
HMAC 构件签名和原子输出为受控本地服务基线。
- `VDB-014`:桌面与服务端对同一 fixture 的 manifest/bundle hash 相同;版本变化必须导致缓存
key 变化。状态:`done_current_scope`;语义相同的 VDB、官方 sphere 重转及桌面/隔离服务端
转换均得到相同 NanoVDB hash。
### Phase 2存储与流送
- `VDB-020`:实现项目 asset manifest 和 source/bundle binding支持 source hash 变化失效。
状态:`done_current_scope`
- `VDB-021`:实现 OPFS range source、staging/journal/atomic commit、重启发现和 LRU page cache。
状态:`done_current_scope`;已验证真实 bundle、取消清理、Worker 重开、tamper gate 和 bundle LRU。
- `VDB-022`:实现 HTTP Range 重试、ETag/If-Range、断点续传、重复/乱序/短响应拒绝。
状态:`done_current_scope`;临时状态/网络异常重试、稳定 ETag、response-body 精确偏移续传、
ETag 改变、错位 `Content-Range`、短响应和逐块 hash 均有 Chromium 故障门。
- `VDB-023`增加网络中断、Worker terminate、quota、tamper、manifest rollback 测试。
状态:`done_current_scope`;网络/body 中断、Worker terminate、真实 OPFS quota、chunk tamper、
manifest rollback、incomplete staging recovery 和旧 bundle 保持均已验证。
- `VDB-024`:在 512 MiB CPU、1 GiB bundle、512 MiB GPU 上限下验证峰值;不得整包复制到
JS heap。`planned`
### Phase 3WebGPU NanoVDB
- `VDB-030`:加入 Chromium WebGPU capability probe、adapter/device limits 和 device loss 状态机。
状态:`done_current_scope`;真实 adapter/device limit probe、device loss、device 重建和重传后
固定点 sample 一致已完成;生产视口资源重建仍归 `VDB-034`
- `VDB-031`:实现 NanoVDB Float/Vec leaf traversal WGSL 和 CPU reference sampler用固定 index
点比较值与 active/inactive 状态。状态:`in_progress`Float32 CPU/WGSL 与 native sample 已逐点
一致Float16/Vec 仍保持阻断。
- `VDB-032`:实现 GPU page allocator、storage buffer upload、indirection、resident LRU 和
dispose每页上传前已通过 chunk hash。`BLOCKED`
- `VDB-033`:实现对象 bounds raycast、front-to-back ray marching、步长/early exit 和深度合成。
状态:`in_progress`;有界正交 bounds、front-to-back integration、early exit 和确定性 96x96
Chromium 图像已完成,生产相机深度合成待接入。
- `VDB-034`:接入主线程/Offscreen renderer 的相同 volume scene deltadevice loss 后重建已
验证页面。`BLOCKED`
### Phase 4材质、Main 与导出
- `VDB-040`:读取 Blender Volume/Principled Volume 节点并生成显式 material mapping/loss report。
状态:`in_progress`density、常量 color/emission、anisotropy、nearest/linear 已映射,
color/temperature/emission grid 和 velocity 明确生成 loss。
- `VDB-041`density/temperature/color/emission/anisotropy 的 Main writer、undo/redo 和原子事务。
状态:`in_progress`Volume source/display/interpolation/step/velocity Main 写回、undo/redo、保存重开
已完成Principled Volume 完整节点事务仍阻断。
- `VDB-042`:保存 `.blend` 与 Web asset binding清空 Worker 后重开并重新流送。`BLOCKED`
状态:`in_progress`Main Volume 保存重开与 OPFS asset binding/Worker 重开分别通过,尚待生产视口
联合重开闭环。
- `VDB-043`GLB 明确报告 Volume 无核心映射USD 仅在 desktop USD/OpenVDB 路径真实可用时
写入 field asset不把 bounds proxy 当体积导出。`BLOCKED`
### Phase 5真实验收与发布
- `VDB-050`desktop OpenVDB -> NanoVDB grid count/name/type/transform/bounds/value sample golden。
- `VDB-051`Blender 5.2 与 Chromium WebGPU 的至少 3 个视角像素 golden分别比较 alpha、
transmittance、color记录容差与色彩空间。
- `VDB-052`64 MiB/512 MiB/1 GiB sparse bundle 的首帧、渐进清晰、峰值 CPU/GPU 和取消门。
- `VDB-053`:损坏 magic/version/tree offset/hash、zip bomb 等价超预算、NaN transform、设备丢失、
网络中断和 OOM 门。
- `VDB-054`:保存重开、资源缺失、源变更重转、旧 schema migration、离线 OPFS 重开。
- `VDB-055`N-026 证据记录包含真实转换器、资源、Chromium WebGPU、desktop golden 和构件 hash。
Phase 5 全部任务当前为 `BLOCKED`,不能由 Phase 0 的协议 fixture 代替。
## 7. 验收命令与停止条件
当前可运行门:
```bash
npm --prefix web run typecheck
npm --prefix web run test:vdb
npm --prefix web run test:vdb-availability
npm --prefix web run test:vdb-native
npm --prefix web run test:vdb-server
npm --prefix web run test:vdb-opfs
npm --prefix web run test:vdb-webgpu
npm --prefix web run test:vdb-viewport
npm --prefix web run test:vdb-faults
```
阶段停止条件:
- 新增资源若无许可证/来源/hash不得进入 VDB catalog 或 golden。
- desktop converter 已构建server job API 未实现时 `SERVER_CONVERSION` 保持 `BLOCKED`
- 无 CPU reference sample 对照WGSL traversal 不得进入 `READY`
- 仅能显示 box/point proxy体渲染仍为 `BLOCKED`
- 未验证 material mapping、Main 保存重开或 desktop/Chromium goldenN-015 与 N-019 仍为
`BLOCKED`
- Chromium 是当前唯一浏览器门;不配置 Firefox/WebKit也不把未测浏览器写成兼容。