As some people are already aware, there’s ongoing developments to leverage WebGPU in VTK-C++ desktop applications with Dawn - Google’s native implementation of WebGPU spec on top of Vulkan, OpenGL, OpenGLES, Metal, D3D11 and D3D12 for Chromium-based browsers
VTK-wasm
As a side-effect, that very same C++ code can use WebGPU in a browser with VTK-wasm! Read on to learn how a VTK-wasm project can be adapted to use WebGPU.
-
Find
VTK::RenderingWebGPU
. This component is built by default in VTK webassembly builds.Before:
# CMakeLists.txt find_package(VTK COMPONENTS ... RenderingOpenGL2 # For Rendering with OpenGL ... )
After:
# CMakeLists.txt find_package(VTK COMPONENTS ... RenderingOpenGL2 # For Rendering with OpenGL RenderingWebGPU # For Rendering with WebGPU ... )
-
Link your targets. There’s no problem linking to OpenGL2 as well. It lets you retain support for older browsers!
Before:
# CMakeLists.txt target_link_libraries(${TARGET} PRIVATE ... VTK::RenderingOpenGL2 )
After:
# CMakeLists.txt target_link_libraries(${TARGET} PRIVATE ... VTK::RenderingOpenGL2 VTK::RenderingWebGPU )
-
Patch your initialization code so that VTK object factory plumbing prefers WebGPU instead of OpenGL VTK classes at runtime. For emscripten-based projects, this means one needs to preload the
ENV
variable withVTK_GRAPHICS_BACKEND='WEBGPU'
.# CMakeLists.txt # ENV holds the environment variables accessible by C getenv target_link_options(${TARGET} PUBLIC "-sEXPORTED_RUNTIME_METHODS=['ENV']" )
Now, switching gears to javascript.
// WebAssembly Module instantiation var Module = { canvas : ... preRun : [function (module) { // select WEBGPU backend module.ENV.VTK_GRAPHICS_BACKEND = 'WEBGPU'; }]; };
-
And finally, instantiate a webgpu device and hand it over to the
Module
object.let adapter = await navigator.gpu.requestAdapter(); let device = await adapter.requestDevice(); // Set the device from JS. This can be done in C++ as well. // See https://github.com/kainino0x/webgpu-cross-platform-demo/blob/main/main.cpp#L51 Module.preinitializedWebGPUDevice = device;
Example
VTK/Examples/Emscripten/Cxx/ConeMultiBackend serves to illustrate the use of both VTK backends using two web-pages. It’s very basic, has no UI at all. Please refer to that example’s code for better understanding about integrating webgpu.
Here’s a quick way to build and test it.
Things you’ll need:
- For windows/macOS, get Chrome beta: Try New Features with Google Chrome Beta - Google Chrome
- For linux, get chromium 113.0.5668.0 from https://chromium.cypress.io/
- npm
- docker
Steps:
-
Grab that example:
curl -L --output ConeMultiBackend.zip https://gitlab.kitware.com/vtk/vtk/-/archive/master/vtk-master.zip?path=Examples/Emscripten/Cxx/ConeMultiBackend $ unzip ConeMultiBackend.zip $ cd vtk-master-Examples-Emscripten-Cxx-ConeMultiBackend/Examples/Emscripten/Cxx/ConeMultiBackend/
-
Install toolset
$ npm init --yes $ npm install itk-wasm@1.0.0-b.83
-
Kitware builds and publishes VTK-wasm docker images so you don’t have to compile VTK with emscripten from scratch. Grab the latest image.
$ docker pull kitware/vtk-wasm:latest
-
Build and serve!
$ npx itk-wasm -i kitware/vtk-wasm -b ./build-emscripten -s . build $ python3 -m http.server -d build-emscripten 8080
-
Click on VTK WebGPU
So far, the benefits we’re noticing with WebGPU implementation in VTK is lower memory usage, a critical requirement for wasm applications and the ability to scale well for large number of actors. This example renders 10,000 vtkActor
instances without hiccups.
Tread with caution. All of this is highly experimental and many features are not yet implemented. Although, most polydata rendering is ready.
The VTK WebGPU implementation is interesting. It is designed to simplify custom mapper development and enables sharing universal shader code with vtk.js because the shader inputs reflect VTK data model which is the common ground between VTK and vtk.js
These slides (Slide 42 onwards) outline the existing VTK WebGPU design. It also goes through performance profiles against WebGL2 and API inspection with RenderDoc.