Until recently, VTK’s WebGPU backend could only talk to the implementation it was
compiled against. WebGPU is a specification with several implementations — Dawn
backs Chrome and is what most desktop applications build against, wgpu-native
backs Firefox and ships as a Rust library, and in a browser the implementation
is the browser. They expose the same C API, but the choice was made by whoever
ran CMake rather than whoever ran the program.
That had a long tail. A VTK binary could not be handed to a user with a different
implementation installed, testing against a second implementation meant a second
build tree, and a distribution that wanted to update Dawn had to rebuild
everything downstream of it.
On master, the module resolves its 202 entry points at startup instead, links
none of them, and runs the same binary on Dawn, wgpu-native, or emdawnwebgpu in
the browser.
The build no longer decides. The module calls through a table of function
pointers that the loader fills once, from whichever library it finds at startup.
How it works
Every wgpu* function VTK calls has a slot in a generated dispatch table, and
the header that declares it also redirects the name:
struct vtkWebGPUProcDispatch
{
WGPUProcQueueSubmit QueueSubmit = nullptr;
WGPUProcBufferAddRef BufferAddRef = nullptr;
/* ... 200 more ... */
};
extern VTK_WEBGPU_PROC_EXPORT vtkWebGPUProcDispatch vtkWebGPUProcs;
#define wgpuQueueSubmit vtkWebGPUProcs.QueueSubmit
#define wgpuBufferAddRef vtkWebGPUProcs.BufferAddRef
The redirect is a forced include, so it covers the module’s own sources and its
tests and stops there. An application that includes a VTK header still sees the
plain names.
The table is generated from the vendored upstream webgpu.h by a script generate_proc_dispatch.py, and the output is checked in rather than generated at configure time. VTK has to build without a Python interpreter, including its Emscripten cross-builds,
and committing the generated file also keeps every entry point visible in review.
Dawn is no longer needed to configure
Configuring with VTK_ENABLE_WEBGPU=ON used to require Dawn to be installed. As
of !13787 it no
longer does. The backend speaks the standard C API and resolves its entry points
at runtime, so Dawn is wanted at configure time only to declare Dawn’s own
extensions, which go beyond the standard API.
Those extensions now sit behind their own option:
cmake -DVTK_ENABLE_WEBGPU=ON \
-DVTK_USE_DAWN_WEBGPU=ON \
-DDawn_DIR=/opt/dawn/lib/cmake/Dawn ...
VTK_USE_DAWN_WEBGPU defaults to OFF, requires VTK_ENABLE_WEBGPU, and is
unavailable on Emscripten. Turning it on makes Dawn a hard requirement:
configuration fails with an error when Dawn_DIR does not point at one, rather
than quietly building without the extensions. Leaving it OFF does not stop a
Dawn library from being loaded at runtime — it only means the extensions are not
declared.
Choosing an implementation
Three places are searched, in order, and the first that loads wins:
VTK_WEBGPU_LIBRARY, an explicit path — the override.- The names implementations are normally installed under:
libwebgpu_dawn.so,
libwgpu_native.so, and so on. - The library the build was configured against, tried only when
VTK_WEBGPU_LIBRARYwas unset — an explicit override that fails to load is
an error, not a reason to fall back. This candidate is compiled in only when
VTK_USE_DAWN_WEBGPU=ONand the install is not relocatable, so a default
WebGPU build has nothing here at all.
export VTK_WEBGPU_LIBRARY=/opt/dawn/lib/libwebgpu_dawn.so
One thing worth noting because it is easy to hit: Dawn has to be built as a
shared library, DAWN_BUILD_MONOLITHIC_LIBRARY=SHARED. The default is static,
and a .a has no symbols to resolve at runtime.
If nothing resolves, initialization fails with a diagnostic naming the first
missing entry point, so an application can fall back to another rendering backend
rather than crashing on the first draw.
What it looks like
Iron protein potential, four nested isosurfaces. Rendered by VTK’s WebGPU
backend through a dispatch table filled at startup — Dawn on macOS, in this case.
Nothing about the output changes, which is the point. The same executable, with
VTK_WEBGPU_LIBRARY pointed at a different library, produces this through a
different implementation; wgpu-native on Linux drives the same scene.

