☰
vgpu/mock实战:确定性模拟适配器让GPU单元测试不依赖显卡
2026/10/5 11:04:22 网站建设 项目流程

vgpu/mock实战:确定性模拟适配器让GPU单元测试不依赖显卡

【免费下载链接】vgpuModular cross-runtime WebGPU library for shaders, 3D scenes, GPU tensors, neural networks, and math viz项目地址: https://gitcode.com/gh_mirrors/vgpu/vgpu

vgpu(@vgpu/adapter-mock)提供了一套纯 JavaScript 的确定性模拟 WebGPU 适配器,通过vgpu/mock入口即可启动一个"无显卡"的完整Gpu实例。你的单元测试从此不再需要真实 GPU、Dawn 或原生渲染库——缓冲区写入、纹理回读、资源创建次数全部可在内存中复现,字节级一致、随时可跑。

为什么 GPU 单元测试需要 mock

WebGPU 的测试天然面临三大难题:

  • 环境依赖:CI 容器、无头服务器往往没有 GPU,也没有 Vulkan/Metal 驱动;
  • 结果不确定:不同显卡的浮点精度、渲染时序都可能让"像素级断言"变得脆弱;
  • 启动成本高:真实的 Node 端 WebGPU 依赖 Dawn 原生库,安装慢、版本漂移大。

vgpu/mock的解法很直接:用一个纯内存的假 GPU 设备替换硬件层。所有缓冲区都是Uint8Array,writeBuffer真的会拷贝字节,writeTexture真的按行偏移写入像素——所以"写进去再读出来"的往返测试在 mock 上与真机行为完全一致。

💡 官方文档的建议是:用vgpu/mock跑确定性单元测试,只有在验证 Dawn/WebGPU 真实行为时才用vgpu/node。详见 docs/topics/browser-testing.docs.md。

三步完成无显卡测试环境

第1步:安装模拟适配器包

pnpm add -D @vgpu/adapter-mock

包说明见 packages/adapter-mock/README.md。

第2步:用vgpu/mock入口启动

import { init, storage } from "vgpu/mock"; const gpu = await init(); const buffer = storage(gpu, 16); buffer.write(new Float32Array([1, 2, 3, 4])); await buffer.read(); // 字节级回读,无需显卡 gpu.dispose();

入口实现非常薄:packages/vgpu-api/src/mock.ts 中init()只是把"mock"目标传给createGpu,其余 API(bundle、frame、compute、surface等)与真实入口完全同签名,切换测试环境不需要改一行业务代码。

第3步:断言行为而非像素

mock 设备自带计量器(instrumentation):每次createBuffer、createBindGroup、createCommandEncoder都会被计数并记录描述符。你可以在测试里直接断言"某段代码恰好创建了 2 个绑定组",这比截图对比稳定得多。

确定性从哪来:4个核心设计

📦内存缓冲区— packages/core/src/mock-gpu.ts 中createMockBuffer用Uint8Array承载数据,getMappedRange直接返回字节视图,回读路径与真实设备共用同一套readback代码。

🧾描述符全记录— 所有资源创建的描述符都被原样存档,测试可事后校验 usage 标志、label、尺寸等参数是否符合预期。

🎯特性开关可声明— packages/adapter-mock/src/index.ts 的createMockAdapter({ features })让你声明"这块假显卡支持哪些特性"。请求未声明的requiredFeatures会抛出VGPU-FEATURE-UNSUPPORTED,方便同时测试特性开启/关闭两条代码路径。

📊查询结果可预测—resolveQuerySet按index × index × 10⁶生成确定值:时间戳查询得到可区分的正差值,遮挡查询的索引 0 解码为"隐藏"、其余为"可见",两条解码路径都能端到端覆盖。

测试什么、不测什么

✅ 适合用vgpu/mock⚠️ 需要真实设备(vgpu/node或浏览器)
缓冲区/纹理写入-回读往返像素级渲染快照
资源创建调用序列与参数WGSL 着色器编译/着色输出
错误作用域(pushErrorScope)行为真实性能与时序测量
生命周期管理(destroy 幂等性)Dawn 特定的 WebGPU 行为

官方示例测试 packages/adapter-mock/tests/buffer-readback.test.ts 展示了典型写法:

const { device } = await init(); const data = new Float32Array([1, 2, 3, 4]); const buffer = device.createBuffer({ size: data.byteLength, usage: ["copy_dst", "copy_src", "storage"], }); buffer.write(data); const readback = new Float32Array(await buffer.read(data.byteLength)); expect(readback).toEqual(data); // 字节相等,确定性回读

进阶:在 vgpu-api 测试中复用 mock

如果你正在开发依赖vgpu高层 API 的模块,仓库提供了现成的测试工具 packages/vgpu-api/test-utils/mock.ts:

  • createMockGpu(options)— 启动一个不加载 Dawn 的Gpu实例;
  • getMockDeviceInstrumentation(gpu)— 拿到计量计数器,直接断言资源创建次数。
const gpu = await createMockGpu(); // ... 执行你的逻辑 ... const inst = getMockDeviceInstrumentation(gpu); expect(inst.calls.createBindGroup).toBe(2);

这套组合让 GPU 代码的单元测试和 HTTP 服务一样:秒级启动、离线可跑、每次结果相同。把真实设备留给端到端与像素快照测试,把确定性回归交给vgpu/mock——这就是它作为"确定性模拟适配器"的核心价值。

【免费下载链接】vgpuModular cross-runtime WebGPU library for shaders, 3D scenes, GPU tensors, neural networks, and math viz项目地址: https://gitcode.com/gh_mirrors/vgpu/vgpu

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询