WebGPU Compute Shaders實戰:瀏覽器端GPU計算入門與優化

前端工程瀏覽器 AI 與 WebAssembly

WebGPU Compute Shaders:被忽視的GPU計算殺手鐧

當大多數人談論WebGPU時,第一反應總是「WebGL的替代品」。但如果你只把WebGPU當成新一代圖形API來用,那就大錯特錯了——Compute Shader才是WebGPU真正的殺手鐧

WebGPU的Compute Shader讓瀏覽器首次擁有了通用GPU計算(GPGPU)的原生能力,這不是漸進式改進,而是範式轉換。

WebGL時代要做GPGPU,只能把資料塞進紋理,用片段著色器模擬計算,再把結果讀回CPU。WebGPU的Compute Shader直接打破了這一限制。


WGSL著色器語言核心語法

WebGPU引入了全新的著色器語言WGSL,取代了GLSL。來看核心語法:

@group(0) @binding(0) var<storage, read> inputData: array<f32>;
@group(0) @binding(1) var<storage, read_write> outputData: array<f32>;

@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let idx = global_id.x;
    if (idx >= arrayLength(&inputData)) { return; }
    outputData[idx] = inputData[idx] * 2.0;
}

Workgroup Size建議

硬體 建議大小 說明
NVIDIA 128-256 Warp大小為32
AMD 64-128 Wavefront大小為64
Intel 32-64 子群組大小較小
通用安全值 64 相容所有硬體

Compute Shader vs WebGL Transform Feedback

維度 WebGL TF WebGPU Compute
程式設計模型 偽裝成渲染管線的計算 原生通用計算
資料傳遞 紋理/VBO Storage Buffer
執行緒控制 頂點數模擬 精確的dispatch控制
資料回讀 readPixels極慢 mapAsync高效
隨機寫入 不支援 原子操作+隨機寫入
共用記憶體 Workgroup Shared Memory

實戰:Compute Shader實現影像高斯模糊

JavaScript處理一張1080p影像的高斯模糊需要約450ms,而Compute Shader可以在約5ms內完成——快了約50倍。

@group(0) @binding(0) var srcTexture: texture_2d<f32>;
@group(0) @binding(1) var dstTexture: texture_storage_2d<rgba8unorm, write>;
@group(0) @binding(2) var<uniform> params: Params;

struct Params {
    width: u32,
    height: u32,
    radius: f32,
}

@compute @workgroup_size(16, 16)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let pixel_coords = vec2<u32>(global_id.x, global_id.y);
    if (pixel_coords.x >= params.width || pixel_coords.y >= params.height) { return; }

    let sigma = params.radius / 3.0;
    var color = vec4<f32>(0.0);
    var total_weight = 0.0;
    let radius_i = i32(params.radius);

    for (var dx: i32 = -radius_i; dx <= radius_i; dx++) {
        for (var dy: i32 = -radius_i; dy <= radius_i; dy++) {
            let weight = exp(-(f32(dx)*f32(dx) + f32(dy)*f32(dy)) / (2.0*sigma*sigma));
            let sx = clamp(i32(pixel_coords.x) + dx, 0, i32(params.width) - 1);
            let sy = clamp(i32(pixel_coords.y) + dy, 0, i32(params.height) - 1);
            color += textureLoad(srcTexture, vec2<u32>(sx, sy), 0) * weight;
            total_weight += weight;
        }
    }
    textureStore(dstTexture, pixel_coords, color / total_weight);
}

效能對比

方案 1080p (r=10) 4K (r=10)
JavaScript ~450ms ~1800ms
Web Worker (4執行緒) ~130ms ~520ms
WebGL片段著色器 ~12ms ~45ms
WebGPU Compute ~5ms ~18ms

實戰:大規模粒子模擬(10萬粒子60fps)

10萬個粒子每幀需要更新位置、速度、碰撞偵測,CPU根本無法負荷。

struct Particle {
    pos: vec2<f32>,
    vel: vec2<f32>,
    color: vec4<f32>,
    life: f32,
}

@group(0) @binding(0) var<storage, read_write> particles: array<Particle>;

@compute @workgroup_size(256)
fn updateParticles(@builtin(global_invocation_id) global_id: vec3<u32>) {
    let idx = global_id.x;
    if (idx >= arrayLength(&particles)) { return; }
    var p = particles[idx];
    p.vel.y += -9.8 * 0.016;
    p.vel *= 0.999;
    p.pos += p.vel * 0.016;
    if (p.pos.y < 0.0) { p.pos.y = 0.0; p.vel.y *= -0.7; }
    p.life -= 0.016;
    if (p.life <= 0.0) {
        p.pos = vec2<f32>(0.5, 0.8);
        p.life = 3.0;
    }
    particles[idx] = p;
}

關鍵技巧:同一個buffer同時作為STORAGE | VERTEX使用,實現Compute→Render零拷貝


瀏覽器相容性

瀏覽器 支援狀態 版本
Chrome ✅ 完整支援 113+
Edge ✅ 完整支援 113+
Firefox ⚠️ 實驗性 Nightly
Safari ⚠️ 部分支援 17.4+

與Web Worker + SharedArrayBuffer的協作模式

主執行緒 (WebGPU Compute) → mapAsync → SharedArrayBuffer → Web Worker (邏輯處理)

這種模式特別適合「GPU做重計算,CPU做邏輯決策」的場景,例如物理模擬中GPU算碰撞,CPU做遊戲邏輯。


總結

WebGPU Compute Shader為Web平台帶來了真正的GPU通用計算能力。2026年的今天,Chrome 113+已經穩定支援,生態工具鏈也在快速成熟。下一步值得關注WebGPU SubgroupsRay Tracing提案。

本站提供瀏覽器本地工具,免註冊即可試用 →

#WebGPU#Compute Shader#GPU计算#WGSL#并行计算