Co-authored-by: nihui <171016+nihui@users.noreply.github.com>
2.7 KiB
WebGPU Native Support Implementation Summary
Overview
This implementation successfully adds WebGPU native support to NCNN by reusing existing Vulkan compute shader infrastructure with automatic transformations for WebGPU compatibility.
Problem Solved
The original issue identified two critical problems when trying to compile Vulkan shaders for WebGPU:
-
SPIR-V Storage Class Error:
unknown SPIR-V storage class: 9- Cause: WebGPU doesn't support push constants the same way Vulkan does
- Solution: Convert
layout (push_constant) uniformtolayout (binding = N) uniform
-
Specialization Constant Expression Error:
unhandled expression for ID 33- Cause: Integer comparison in psc macro causes SPIR-V compilation issues
- Solution: Use
float(x)==0instead ofx==0in the psc macro
Implementation Details
1. Build System Changes
CMakeLists.txt:
- Automatic WebGPU detection when targeting emscripten with Vulkan enabled
- Uses
CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NCNN_VULKANcondition - Sets
NCNN_WEBGPU=1preprocessor define
2. Shader Preprocessing Pipeline
cmake/ncnn_add_shader.cmake:
- Added conditional logic to use WebGPU shader transformation when targeting emscripten + vulkan
- Uses
ncnn_generate_webgpu_shader_header.cmakefor transformation
cmake/ncnn_generate_webgpu_shader_header.cmake:
- New transformation pipeline that converts push constants to uniform bindings
- Regex-based transformation:
layout (push_constant) uniform X { ... } Y;→struct X { ... }; layout (binding = 1) uniform X_blob { X Y; };
3. Runtime Changes
src/gpu.cpp:
- Added conditional compilation for psc macro definition
- WebGPU uses
(float(x)==0?p.x:x)instead of(x==0?p.x:x)
Verification Results
✅ All shader transformations working: 300+ compute shaders successfully transformed
✅ Push constant conversion: Correctly converts to uniform bindings
✅ psc macro compatibility: Uses float casting for WebGPU
✅ Automated testing: Created verification script that passes all checks
Example Transformation
Before (Vulkan):
layout (push_constant) uniform parameter {
int dims, w, h, c, cstep;
} p;
if (gx >= psc(w)) return; // psc(w) = (w==0?p.w:w)
After (WebGPU):
struct parameter {
int dims, w, h, c, cstep;
};
layout (binding = 1) uniform parameter_blob { parameter p; };
if (gx >= psc(w)) return; // psc(w) = (float(w)==0?p.w:w)
Usage
# Enable WebGPU native support with emscripten
emcmake cmake .. -DNCNN_VULKAN=ON
emmake make -j$(nproc)
This implementation provides a solid foundation for WebGPU native support while maintaining compatibility with existing Vulkan infrastructure.