
WebGPU 架构 - 图源自MDN
一个 Adapter,多个 Devices
GPUAdapter:一个特定的GPU,显然一个计算机可以有多个GPU,如独显与核显。甚至可以不是物理意义上的显卡:它只是显卡行为的抽象。
GPUDevice:逻辑设备,有独自的上下文,相互之间是隔离的,天然可并行。承担了一部分获取GPU资源的职责,在这点上是类似于 OpenGL Context 的。不过 gl.xxx 系函数是实时的,指令一经给出会立刻改变 GPU 的状态,但是 device.xxx 系操作是预先录制到命令缓冲区中的,只有在缓冲区被提交之后才会被执行。
graph TD
A[浏览器页面 WebGPU API] --> B[navigator.gpu]
B -->|requestAdapter()| C[GPUAdapter]
C -->|requestDevice()| D[GPUDevice]
%% Adapter 描述
C --> C1[特性信息 features, limits]
C --> C2[适配器描述 名称, 类型]
%% Device 描述
D --> D1[队列 GPUQueue device.queue]
D --> D2[资源创建 GPUBuffer, GPUTexture, GPUSampler...]
D --> D3[管线创建 GPUShaderModule, GPURenderPipeline...]
D --> D4[绑定组 GPUBindGroup]
style A fill:#f6f8fa,stroke:#666,stroke-width:1px
style B fill:#e3f2fd,stroke:#1e88e5,stroke-width:1px
style C fill:#e8f5e9,stroke:#43a047,stroke-width:1px
style D fill:#fff3e0,stroke:#fb8c00,stroke-width:1px
大部分 GPU 资源都是从 GPUDevice 这里获取的,例如:
GPUBindGroupLayout 与 GPUBindGroupGPUCommandEncoder 等一个 GPUBuffer 对象表示一块连续的显存,它用来在 CPU 与 GPU 之间 共享和存储数据,其用途多样,不过需要在声明的时候指明,例如:
const buffer = device.createBuffer({
size: 1024, // 字节数,必须是 4 的倍数
usage: GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_DST,
mappedAtCreation: false
});
GPUBufferUsage 的语义不像 OpenGL 里那样直接表示绑定点,例如 GL_COPY_READ_BUFFER 和 GL_COPY_WRITE_BUFFER 在 GL 中它们就专门用作拷贝行为的源和目标了。在 WebGPU 中它本质上是一个权限声明,只是会在对它进行相应行为的时候检查使用具有对应权限,类似于 VK 的 VkBufferUsageFlags
例如 GPUBufferUsage.COPY_DST 的意思是:允许别的资源(Buffer/Texture/CPU)往这个 Buffer 写数据。相当于在 writeBuffer 和 copyBufferToBuffer 时相关缓冲区要具有的读写权限资格。
关于GPUBuffer 的读写操作是这样的: