Guide: How do I use VTK-wasm webgpu experimental feature

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.

  1. 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
        ...
    )
    
  2. 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
    )
    
  3. 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 with VTK_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';
        }];
    };
    
  4. 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:

Steps:

  1. 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/
    
  2. Install toolset

    $ npm init --yes
    $ npm install itk-wasm@1.0.0-b.83
    
  3. 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
    
  4. Build and serve!

    $ npx itk-wasm -i kitware/vtk-wasm -b ./build-emscripten -s . build
    $ python3 -m http.server -d build-emscripten 8080
    
  5. Open http://localhost:8080

  6. 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.

9 Likes

Updated post with link to slides about implementation design and performance comparisons.