| # Running the WebGPU CTS with the standalone runner | |
| `dawn_standalone_cts_runner` is a single executable that statically links V8 and | |
| Dawn and runs the WebGPU CTS directly, without a Node.js installation. | |
| The usual way to run the CTS is [`dawn.node`](../src/dawn/node/README.md), a | |
| native addon loaded by Node.js. The standalone runner instead embeds its own V8 | |
| and supplies the subset of the Node API the CTS uses. That removes the external | |
| Node.js dependency. This is important for platforms like Android where Node.js | |
| is not available. | |
| Both runners execute the same CTS JavaScript and the same Dawn bindings. | |
| ## Fetching dependencies | |
| Follow [`docs/building.md`](building.md), using | |
| `scripts/standalone-with-v8.gclient` in the `Get the code` step so `gclient` | |
| fetches both the Node bindings (`dawn_node`) and V8 (`checkout_v8`): | |
| ```sh | |
| # Clone the repo as "dawn" | |
| git clone https://dawn.googlesource.com/dawn dawn && cd dawn | |
| # Bootstrap the gclient configuration for the standalone CTS runner | |
| cp scripts/standalone-with-v8.gclient .gclient | |
| # Fetch external dependencies and toolchains with gclient | |
| gclient sync | |
| ``` | |
| If you are configuring an existing checkout, ensure `.gclient` sets both | |
| `"checkout_v8": True` and `"dawn_node": True` in `custom_vars` before running | |
| `gclient sync`. Without `checkout_v8`, the `dawn_standalone_cts_runner` target | |
| is not declared. | |
| ## Building the runner | |
| Generate a release build directory and compile `dawn_standalone_cts_runner` | |
| (building this target compiles only the standalone runner executable and its | |
| dependencies, not the `dawn.node` shared library): | |
| ```sh | |
| gn gen out/Release --args="is_debug=false dawn_use_swiftshader=false" | |
| autoninja -C out/Release dawn_standalone_cts_runner | |
| ``` | |
| - `is_debug=false` is strongly recommended: the default debug build compiles a | |
| debug V8, which runs the CTS roughly 17x slower than a release build. | |
| - `dawn_use_swiftshader=false` skips building Dawn's bundled SwiftShader | |
| renderer and ensures the runner uses the system's drivers. Remove this option | |
| if you want to test against SwiftShader. | |
| ## Building the CTS JavaScript | |
| The runner executes the CTS's compiled `out-node/` tree, which is not checked | |
| in. Any Node.js installation (`>= 16.0.0`) with `npm` and `npx` can build it. If | |
| you do not have `node`, `npm`, and `npx` installed on your system, you can add | |
| the prebuilt Node.js fetched by `gclient sync` under `third_party/node/` to your | |
| `PATH` first: | |
| ```sh | |
| # Optional: use the Node.js fetched by DEPS if npm/npx are not already installed. | |
| # Replace linux-amd64 with linux-arm64, mac-amd64, or mac-arm64 as needed | |
| # (or $PWD/third_party/node/windows-amd64 on Windows). | |
| export PATH="$PWD/third_party/node/linux-amd64/bin:$PATH" | |
| ``` | |
| Install the CTS dependencies and build `out-node/`: | |
| ```sh | |
| cd third_party/webgpu-cts | |
| npm ci | |
| npx grunt node | |
| cd ../.. | |
| ``` | |
| `npm ci` alone is not sufficient: `npx grunt node` runs the Grunt tasks that | |
| generate `out-node/`. | |
| ## Running the CTS | |
| Run from the Dawn root (or pass `--cts-dir <dir>` if the CTS lives outside | |
| `third_party/webgpu-cts`): | |
| ```sh | |
| out/Release/dawn_standalone_cts_runner -q 'webgpu:api,operation,queue,*' | |
| ``` | |
| Quote the query: CTS queries contain `;` and `"`, which most shells will | |
| otherwise interpret. Pass `--help` to list all supported flags. | |
| ### Selecting a GPU, and setting Dawn toggles | |
| `--dawn-flag` is passed through to the Dawn provider. It takes a single | |
| `key=value` and may be repeated: | |
| ```sh | |
| out/Release/dawn_standalone_cts_runner \ | |
| --dawn-flag backend=vulkan \ | |
| --dawn-flag enable-dawn-features=dump_shaders \ | |
| -q 'webgpu:api,operation,queue,*' | |
| ``` | |
| The recognised keys are: | |
| - `backend=<null|webgpu|d3d11|d3d12|d3d|metal|vulkan|vk|opengl|gl|opengles|gles>` | |
| (defaults to `d3d12` on Windows, `vulkan` on Linux/Android, and `metal` on | |
| macOS; can also be set via the `DAWNNODE_BACKEND` environment variable) | |
| - `adapter=<name>` — substring match against the adapter device name. Pass an | |
| invalid name (for example `adapter=help`) to list all available adapters in | |
| the error output | |
| - `validate=<1|true>` — enable full backend validation layers | |
| - `verbose=1` — print the selected GPU adapter name | |
| - `enable-dawn-features=<toggles>` — comma-separated list of | |
| [Dawn toggles](https://dawn.googlesource.com/dawn/+/refs/heads/main/src/dawn/native/Toggles.cpp) | |
| - `disable-dawn-features=<toggles>` — comma-separated list of Dawn toggles | |
| ## Running on Android | |
| There is no Node.js build for Android in the checkout, so the standalone runner | |
| is the only way to run the command-line CTS directly on an Android device. | |
| Cross-compiling for Android currently requires a Linux host (the GN build and | |
| Android NDK toolchain in Dawn's checkout do not support building for Android | |
| from Windows or macOS). | |
| ### Checkout | |
| On a Linux host, add `target_os = ["android"]` to `.gclient` and sync the | |
| Android NDK and toolchain dependencies: | |
| ```sh | |
| printf '\ntarget_os = ["android"]\n' >> .gclient | |
| gclient sync | |
| ``` | |
| ### Build | |
| Generate an `arm64` Android release build on Linux and compile the runner: | |
| ```sh | |
| gn gen out/Android --args='target_os="android" target_cpu="arm64" is_debug=false' | |
| autoninja -C out/Android dawn_standalone_cts_runner | |
| ``` | |
| ### Staging onto the device | |
| Only the executable and the compiled CTS JavaScript are needed on the device. | |
| > [!NOTE] | |
| > `dawn.node` is deliberately **not** pushed. The runner's module loader returns | |
| > its statically-linked binding for `require('dawn.node')`, so the shared | |
| > library is never loaded. | |
| ```sh | |
| DEV=/data/local/tmp/cts | |
| adb shell "mkdir -p $DEV/bin $DEV/webgpu-cts" | |
| adb push out/Android/dawn_standalone_cts_runner $DEV/bin/ | |
| adb shell "chmod 755 $DEV/bin/dawn_standalone_cts_runner" | |
| # out-node is ~2200 files; a single archive transfers far faster than letting | |
| # adb sync each file individually. Include cmdline.ts as well, which both the | |
| # runner and cmdline.js check as a repository-root marker. | |
| tar -C third_party/webgpu-cts -czf /tmp/cts.tgz \ | |
| out-node src/common/runtime/cmdline.ts | |
| adb push /tmp/cts.tgz $DEV/webgpu-cts/ | |
| adb shell "cd $DEV/webgpu-cts && tar xzf cts.tgz && rm cts.tgz" | |
| rm /tmp/cts.tgz | |
| ``` | |
| ### Running | |
| ```sh | |
| adb shell '/data/local/tmp/cts/bin/dawn_standalone_cts_runner \ | |
| --cts-dir /data/local/tmp/cts/webgpu-cts \ | |
| -q "webgpu:api,operation,queue,*"' | |
| ``` | |
| ## Future plans | |
| The setup above is more manual than it should be. The intent is to teach | |
| [`run-cts`](../tools/src/cmd/run-cts) about the standalone runner, so that | |
| selecting it becomes a flag on the tool already used to run the CTS, with the | |
| CTS build, query sharding, expectations handling and result reporting all | |
| handled as they are today for `dawn.node`. | |
| Once that lands, most of this document reduces to a single `./tools/run run-cts` | |
| invocation, and the manual staging steps for Android are expected to be driven | |
| by the tool as well. |