VTK::RenderingWebGPU#

Description#

This module contains the WebGPU native backend for RenderingCore. Currently, it supports rendering polygonal geometry in different representations with point/cell scalar-mapped colors.

When both the RenderingOpenGL2 and RenderingWebGPU libraries are linked, the user must provide preferences to select the rendering backend at runtime. This can be done in two ways:

  1. Pass command line arguments to your application --vtk-factory-prefer RenderingBackend=WebGPU or --vtk-factory-prefer RenderingBackend=OpenGL2. Then, you will need to invoke vtkObjectFactory::InitializePreferencesFromCommandLineArgs(argc, argv) in your main function before creating any VTK object.

  2. Alternatively, set the VTK_FACTORY_PREFER environment variable to RenderingBackend=WebGPU or RenderingBackend=OpenGL2.


Building VTK with Dawn (Highly Experimental)#

Prerequisites#

  • Git

  • tools for building VTK

  • A compiler C++ 20 compatible (eg: clang-19 or newer) required to compile Dawn. [VTK supports C++17 compilers]. Not required if using pre-built dawn binaries

Desktop#

On desktop (Linux, macOS, and Windows), this module runs on Dawn’s WebGPU implementation, through the C API. You can get Dawn with any of these two methods:

  1. Build Dawn from source.

  2. Fetch pre-built Dawn binaries built in release mode.

These two methods are supported on all three operating systems. Pre-build Dawn binaries are available only for linux-x86_64, windows-x86_64, macos-x86_64 and macos-arm64. If you are on a different platform, you will need to build Dawn from source.

Here, VTK_SOURCE_DIR is the path to the root of the VTK source directory, and VTK_BUILD_DIR is the path to the directory where you want to build VTK.

Build Dawn from source#

Dawn should be built at tag v20260720.160313. Here, DAWN_INSTALL_DIR should point to the directory where Dawn is installed (should contain lib and include directories).

# Clone the repo and checkout the required version
git clone https://github.com/google/dawn dawn && cd dawn
git checkout v20260720.160313
cmake -S . -B out/Debug -GNinja -DDAWN_FETCH_DEPENDENCIES=ON -DDAWN_ENABLE_INSTALL=ON -DDAWN_BUILD_MONOLITHIC_LIBRARY=SHARED
cmake --build out/Debug
cmake --install out/Debug --prefix ${DAWN_INSTALL_DIR}

Fetch pre-built Dawn binaries#

Run the following command to fetch pre-built Dawn binaries. This will download and install Dawn to VTK_SOURCE_DIR/.gitlab.

cd "${VTK_SOURCE_DIR}"
CMAKE_CONFIGURATION="fedora" cmake -P .gitlab/ci/download_dawn.cmake
export DAWN_INSTALL_DIR="${VTK_SOURCE_DIR}/.gitlab/dawn"
cd "${VTK_SOURCE_DIR}"
CMAKE_CONFIGURATION="macos_arm64" cmake -P .gitlab/ci/download_dawn.cmake
export DAWN_INSTALL_DIR="${VTK_SOURCE_DIR}/.gitlab/dawn"
cd "${VTK_SOURCE_DIR}"
CMAKE_CONFIGURATION="macos_x86_64" cmake -P .gitlab/ci/download_dawn.cmake
export DAWN_INSTALL_DIR="${VTK_SOURCE_DIR}/.gitlab/dawn"
cd "$env:VTK_SOURCE_DIR"
$env:CMAKE_CONFIGURATION="windows"; cmake -P .gitlab/ci/download_dawn.cmake
$env:DAWN_INSTALL_DIR="$env:VTK_SOURCE_DIR\.gitlab\dawn"

After you are finished, you should see a new directory VTK_SOURCE_DIR/.gitlab/dawn which contains the pre-built Dawn binaries. Set DAWN_INSTALL_DIR to VTK_SOURCE_DIR/.gitlab/dawn so that you can pass it to CMake when configuring VTK’s build.

Configure and build VTK#

Run the following commands to configure and build VTK with WebGPU support.

cmake \
-S "${VTK_SOURCE_DIR}" \
-B "${VTK_BUILD_DIR}" \
-GNinja \
-DVTK_ENABLE_WEBGPU=ON \
-DDawn_DIR="${DAWN_INSTALL_DIR}/lib/cmake/Dawn" \
-DVTK_BUILD_TESTING=ON

cmake --build "${VTK_BUILD_DIR}"
cmake `
-S "$env:VTK_SOURCE_DIR" `
-B "$env:VTK_BUILD_DIR" `
-DCMAKE_BUILD_TYPE=Release `
-GNinja `
-DVTK_ENABLE_WEBGPU=ON `
-DDawn_DIR="$env:DAWN_INSTALL_DIR/lib/cmake/Dawn" `
-DVTK_BUILD_TESTING=ON

cmake --build "$env:VTK_BUILD_DIR"

Warning

When copy pasting the commands on Windows, please paste them into a Powershell window and not a Command prompt!

Warning

On Windows, ensure that you are using the same CMAKE_BUILD_TYPE for both building Dawn and configuring VTK. Or else, you will see a linker error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '0' doesn't match value '2' in vtkRenderingWebGPUObjectFactory.cxx.obj.

WebAssembly#

On WebAssembly, this module uses the WebGPU implementation provided by the browser. You do not need to build Dawn from source or fetch pre-built Dawn binaries. You just need to configure and build VTK with Emscripten. It takes care of linking the WebGPU implementation provided by the browser (with the --use-port=emdawnwebgpu flag).

Configure and build VTK#

Run the following commands to configure and build VTK for WASM with WebGPU support.

emcmake cmake \
-S "${VTK_SOURCE_DIR}" \
-B "${VTK_BUILD_DIR}" \
-GNinja \
-DVTK_ENABLE_WEBGPU=ON \
-DBUILD_SHARED_LIBS=OFF \
-DVTK_BUILD_TESTING=ON

cmake --build "${VTK_BUILD_DIR}"

Running Tests#

WebGPU Tests#

cd ${VTK_BUILD_DIR}
ctest -R RenderingWebGPU -V
cd $env:VTK_BUILD_DIR
ctest -R RenderingWebGPU -V

Rendering Core Tests#

To run the RenderingCore tests with VTK::RenderingWebGPU:

cd ${VTK_BUILD_DIR}
ctest -R RenderingCoreCxx-WebGPU -V
cd $env:VTK_BUILD_DIR
ctest -R RenderingCoreCxx-WebGPU -V

WebGPU Runtime Loading#

VTK’s WebGPU module resolves a WebGPU implementation library at runtime through a proc table. The eventual goal is to decouple the compile-time and runtime dependencies so that the same VTK build works with different native WebGPU runtimes (Dawn, wgpu-native) or browser WebGPU via Emscripten.

Note

This decoupling is not complete. When Dawn is found at configure time the module links no implementation: the wgpu* names are redirected to a dispatch table that the proc table fills in, so the only requirement is that an implementation can be found at runtime. vtkWebGPUConfiguration::Initialize() fails with a diagnostic if none can be.

On Emscripten there is no library to resolve: --use-port=emdawnwebgpu links the implementation into the module, so the proc table reports itself loaded without opening anything.

The implementation uses lazy initialization that is thread-safe and loads on first access. The library is opened with global symbol visibility, so direct calls to the WebGPU C API resolve against it without modification. Missing libraries are reported at initialization (not link time), with clear diagnostic messages. If functions are unavailable, wrappers return safe values for graceful fallback.

Architecture#

The implementation consists of two layers:

  1. vtkWebGPUProcTable (C interface): loads the WebGPU implementation library and resolves function pointers using the runtime’s proc address function.

  2. vtkWebGPUProcLoader (C++ singleton, internal): wraps the proc table with lazy initialization. Provides IsLoaded() and Load(), and is reached through vtkWebGPUConfiguration::Initialize().

VTK’s sources call the WebGPU C API by its ordinary names. The build forces Private/vtkWebGPUProcDispatch.h into the module’s own sources and its tests, and that header #defines each wgpu* name to the matching entry in a table of function pointers, filled in from wgpuGetProcAddress once the library is open. The forced include keeps the redirect off installed headers and out of anything a consumer compiles.

Private/vtkWebGPUProcDispatch.{h,cxx} are generated. After updating ThirdParty/webgpuheaders, regenerate them and commit the result:

python3 Rendering/WebGPU/generate_proc_dispatch.py

Handles cannot take the entry points as template arguments any more - the address of a table entry is not a constant expression - so vtkWebGPU::Handle takes a traits type whose AddRef/Release call through the table instead.

Initialization flow: vtkWebGPUConfiguration::Initialize() invokes vtkWebGPUProcLoader::GetInstance(), which loads the WebGPU implementation library (e.g., libwgpu_dawn.so), resolves function pointers via the proc table, then creates a WebGPU adapter and device.

Standard WebGPU Headers#

VTK vendors a copy of the upstream webgpu-headers C API in ThirdParty/webgpuheaders. It defines the core WebGPU types (WGPUInstance, WGPUDevice, etc.) and the function signatures that the proc table resolves at runtime.

This vendored copy is what VTK compiles against on every platform, including builds that link Dawn — VTK::webgpuheaders is a public dependency, so its include directory is searched ahead of any implementation’s. VTK is therefore decoupled from a particular implementation at the header level: the API cannot change underneath VTK, and downstream consumers resolve the same header through find_package(VTK).

Both VTK’s public headers and its implementation files use the C API only. No C++ wrapper (webgpu_cpp.h) is vendored or included; ownership of the C handles is expressed with Private/vtkWebGPUHandle.h. The module builds as C++17 and the installed interface does not require C++20 of its consumers.

Upstream deliberately declares only the standard API. Implementations extend it through nextInChain, using WGPUSType values from blocks upstream reserves for them. The two extensions VTK uses — Dawn’s adapter power preference and emdawnwebgpu’s canvas selector — are declared in Private/vtkWebGPUImplExtensions.h, each behind the compile-time flag for the implementation that provides it.

Library Search Strategy#

If an explicit library path is given to the loader, it is tried first and on its own. Otherwise the proc table tries the following names, in this order:

  1. libwgpu_dawn.so (the default when no path is supplied)

  2. libwebgpu_dawn.so

  3. libwgpu_dawn.so.0 (versioned variant)

  4. libwebgpu_dawn.so.0 (versioned variant)

  5. libwgpu_dawn.dylib (macOS)

  6. libwebgpu_dawn.dylib (macOS)

  7. wgpu_dawn.dll (Windows)

  8. webgpu_dawn.dll (Windows)

An explicit path is opened through vtkDynamicLoader on every platform. A bare name is opened with LoadLibraryW on Windows, so that the standard DLL search order applies: vtkDynamicLoader routes a name through Encoding::ToWindowsExtendedPath, which resolves it against the current working directory instead of searching PATH. Elsewhere vtkDynamicLoader maps onto dlopen/dlsym.

Custom paths: You can override the search by setting environment variables:

  • Linux: LD_LIBRARY_PATH=/path/to/lib

  • macOS: DYLD_LIBRARY_PATH=/path/to/lib

  • Windows: PATH=\path\to\lib

Or by naming the library outright: set VTK_WEBGPU_LIBRARY to the path of the implementation to load, and the search above is skipped.

Debugging and Diagnostics#

Library loading failed:

  • Check if the WebGPU library is installed: ldconfig -p | grep -E '(wgpu_dawn|webgpu_dawn)' (Linux), or verify in /usr/lib or /opt/local/lib (macOS), or PATH (Windows)

  • Ensure the library is in a standard search path or set LD_LIBRARY_PATH=/path/to/lib (Linux), DYLD_LIBRARY_PATH (macOS), or PATH (Windows)

  • Test library loading directly: python3 -c "import ctypes; ctypes.CDLL('/path/to/libwgpu_dawn.so')" (adjust path/name as needed)

Function not found:

  • Verify the function name is spelled correctly and the length is correct (must match string length in bytes)

  • Check if the loaded library version exports the function: nm /usr/lib/libwgpu_dawn.so | grep wgpuFunctionName

  • Enable debug output in vtkWebGPUProcTable.cxx during development


Features#

The following features are currently implemented:

  • vtkPolyData Rendering: Supports point, line, and triangle primitives.

  • Glyph Rendering: Supports point, line, and triangle primitives.

  • Composite vtkPolyData Rendering: Supports point, line, and triangle primitives.

  • Scalar Mapped Coloring:

    • Point scalar mapped coloring of surfaces.

    • Cell scalar mapped coloring.

  • Actor Representations:

    • VTK_POINTS

    • VTK_WIREFRAME

    • VTK_SURFACE

    • VTK_SURFACE with edge visibility

  • Lighting:

    • Based on VTK headlights.

    • Supports point/cell normals.

  • Rendering Adjustments:

    • Point size adjustments.

    • Line width adjustments for wireframe and surface with edges.

  • Depth Testing: Enables correct rendering of 3D objects.

  • Selections: Hardware selector can pick cells, composite datasets and actors.


Compute Shader API#

The compute shader API allows offloading work from the CPU to the GPU using WebGPU compute shaders.


Future Work#

Since WebGPU is already an abstraction over graphics APIs, this module avoids creating another level of abstraction. Helper classes in the Private/vtkWebGPU<Thing>Internals files ensure cleaner bind group initialization code.

The module uses the WebGPU C API throughout. Ownership of the C handles is expressed with VTK’s own reference-counted wrapper in Private/vtkWebGPUHandle.h, which provides the RAII the wgpu:: C++ types used to supply.

Planned improvements include:

  • Volume mappers

  • Dual-depth peeling

  • Advanced lighting

  • Platform-native render windows for Windows, macOS, Android, iOS and wayland.


References#

Here are some valuable resources for learning WebGPU:

  1. WebGPU Fundamentals

    • Complete introduction to using WebGPU

  2. WebGPU GLTF Case Study

    • Builds an efficient glTF renderer in WebGPU using JavaScript.

    • Discusses various rendering pitfalls and optimizations.

  3. WebGPU Native Examples

    • A collection of single-file examples demonstrating various WebGPU use cases in C.

  4. Learn WebGPU

    • Similar to LearnOpenGL and Vulkan tutorials.

    • Covers window setup, triangle rendering, buffers, textures, and 3D rendering.

  5. Learn WGPU

    • Beginner-friendly tutorial using wgpu.rs.

  6. Raw WebGPU

    • Introductory tutorial covering WebGPU concepts using JavaScript.

  7. How to Render a WebGPU Triangle (Series)

    • Explains swapchain and image presentation in detail.

  8. WebGPU Rocks

    • A well-organized WebGPU API and WGSL summary.

For WGSL specification, refer to: WGSL Spec