Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 15 additions & 19 deletions cmake/FindHalide_WebGPU.cmake
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
cmake_minimum_required(VERSION 3.28)

# tip: uncomment this line to get better debugging information if find_library() fails
# set(CMAKE_FIND_DEBUG_MODE TRUE)

if (EXISTS "$ENV{HL_WEBGPU_NATIVE_LIB}")
set(Halide_WebGPU_NATIVE_LIB "$ENV{HL_WEBGPU_NATIVE_LIB}"
CACHE FILEPATH "")
endif ()

find_library(Halide_WebGPU_NATIVE_LIB NAMES webgpu_dawn wgpu)
find_library(
Halide_WebGPU_LIBRARY
NAMES webgpu_dawn wgpu
HINTS ENV HL_WEBGPU_NATIVE_LIB
)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
Halide_WebGPU
REQUIRED_VARS Halide_WebGPU_NATIVE_LIB
HANDLE_COMPONENTS
Halide_WebGPU
REQUIRED_VARS Halide_WebGPU_LIBRARY
HANDLE_COMPONENTS
)

if (Halide_WebGPU_NATIVE_LIB AND NOT TARGET Halide::WebGPU)
add_library(Halide::WebGPU UNKNOWN IMPORTED)
set_target_properties(
Halide::WebGPU
PROPERTIES
IMPORTED_LOCATION "${Halide_WebGPU_NATIVE_LIB}"
)
if (Halide_WebGPU_LIBRARY AND NOT TARGET Halide::WebGPU)
add_library(Halide::WebGPU UNKNOWN IMPORTED)
set_target_properties(
Halide::WebGPU
PROPERTIES
IMPORTED_LOCATION "${Halide_WebGPU_LIBRARY}"
)
endif ()
13 changes: 13 additions & 0 deletions cmake/vcpkg/dawn/patches/add-dawn-node-install.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
--- a/src/dawn/node/CMakeLists.txt
+++ b/src/dawn/node/CMakeLists.txt
@@ -189,5 +189,10 @@ macro(javascript file)
"$<TARGET_FILE_DIR:dawn_node>/${file}")
endmacro()

javascript("index.js")
javascript("cts.js")
+
+# Install the dawn.node shared library
+if (DAWN_ENABLE_INSTALL)
+ install(TARGETS dawn_node LIBRARY DESTINATION lib/node_modules)
+endif ()
83 changes: 83 additions & 0 deletions cmake/vcpkg/dawn/portfile.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
vcpkg_check_linkage(ONLY_DYNAMIC_LIBRARY)

vcpkg_from_git(
OUT_SOURCE_PATH SOURCE_PATH
URL https://dawn.googlesource.com/dawn
REF 40ddf3b135d952082cdd6e0d03539e924c18221b # chromium/7350
FETCH_REF chromium/${VERSION}
PATCHES
patches/add-dawn-node-install.patch
)

vcpkg_find_acquire_program(PYTHON3)
vcpkg_find_acquire_program(GIT)

function(clone_submodule)
cmake_parse_arguments(PARSE_ARGV 0 ARG "" "SOURCE_PATH;URL;REF" "")
get_filename_component(name "${ARG_SOURCE_PATH}" NAME)
vcpkg_execute_required_process(
COMMAND "${GIT}" clone "${ARG_URL}" "${ARG_SOURCE_PATH}"
WORKING_DIRECTORY "${SOURCE_PATH}"
LOGNAME "clone-${name}"
)
vcpkg_execute_required_process(
COMMAND "${GIT}" -C "${ARG_SOURCE_PATH}" checkout "${ARG_REF}"
WORKING_DIRECTORY "${SOURCE_PATH}"
LOGNAME "checkout-${name}"
)
endfunction()

# Fetch Dawn's dependencies using their script
vcpkg_execute_required_process(
COMMAND "${PYTHON3}" tools/fetch_dawn_dependencies.py
WORKING_DIRECTORY "${SOURCE_PATH}"
LOGNAME fetch-deps
)

# Manually clone the remaining dependencies that fetch_dawn_dependencies.py doesn't handle
# using the specific commit hashes that chromium/7350 expects
clone_submodule(
SOURCE_PATH third_party/gpuweb
URL https://chromium.googlesource.com/external/github.com/gpuweb/gpuweb
REF a2637f7b880c2556919cdb288fe89815e0ed1c41
)

clone_submodule(
SOURCE_PATH third_party/node-addon-api
URL https://chromium.googlesource.com/external/github.com/nodejs/node-addon-api
REF 1e26dcb52829a74260ec262edb41fc22998669b6
)

clone_submodule(
SOURCE_PATH third_party/node-api-headers
URL https://chromium.googlesource.com/external/github.com/nodejs/node-api-headers
REF d5cfe19da8b974ca35764dd1c73b91d57cd3c4ce
)

vcpkg_cmake_configure(
SOURCE_PATH "${SOURCE_PATH}"
OPTIONS
-DDAWN_BUILD_MONOLITHIC_LIBRARY=SHARED
-DDAWN_BUILD_NODE_BINDINGS=ON
-DDAWN_BUILD_PROTOBUF=OFF
-DDAWN_BUILD_SAMPLES=OFF
-DDAWN_BUILD_TESTS=OFF
-DDAWN_ENABLE_INSTALL=ON
-DDAWN_ENABLE_PIC=ON
-DTINT_BUILD_CMD_TOOLS=OFF
-DTINT_BUILD_TESTS=OFF
OPTIONS_RELEASE
-DBUILD_SHARED_LIBS=OFF
OPTIONS_DEBUG
-DBUILD_SHARED_LIBS=OFF
)

vcpkg_cmake_install()

vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/dawn)

vcpkg_copy_pdbs()

file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include")

vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE")
18 changes: 18 additions & 0 deletions cmake/vcpkg/dawn/vcpkg.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "dawn",
"version": "7350",
"port-version": 0,
"description": "Dawn, a WebGPU implementation",
"homepage": "https://dawn.googlesource.com/dawn",
"license": "BSD-3-Clause",
"dependencies": [
{
"name": "vcpkg-cmake",
"host": true
},
{
"name": "vcpkg-cmake-config",
"host": true
}
]
}
112 changes: 55 additions & 57 deletions doc/WebGPU.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ and versions of Emscripten.

The following is a non-comprehensive list of known limitations:

- Only 32-bit integers and floats have efficient support.
* 8-bit and 16-bit integers are implemented using emulation. Future
extensions to WGSL will allow them to be implemented more efficiently.
* 64-bit integers and floats will likely remain unsupported until WGSL gains
extensions to support them.
- Wrapping native device buffer handles is not yet implemented.
- You must use CMake/CTest to build/test Halide for WebGPU; using the Makefile
is not supported for WebGPU testing (and probably never will be).
- Only 32-bit integers and floats have efficient support.
* 8-bit and 16-bit integers are implemented using emulation. Future extensions
to WGSL will allow them to be implemented more efficiently.
* 64-bit integers and floats will likely remain unsupported until WGSL gains
extensions to support them.
- Wrapping native device buffer handles is not yet implemented.
- You must use CMake/CTest to build/test Halide for WebGPU; using the Makefile
is not supported for WebGPU testing (and probably never will be).

In addition to these functional limitations, the performance of the WebGPU
backend has not yet been evaluated, and so optimizations in the runtime or
Expand All @@ -37,8 +37,9 @@ When invoking `emcc` to link Halide-generated objects, include these flags:

Tests that use AOT compilation can be run using a native WebGPU implementation
that has Node.js bindings, such as [Dawn](https://dawn.googlesource.com/dawn/).
You must set an environment variable named `HL_WEBGPU_NODE_BINDINGS` that
has an absolute path to the bindings to run these tests, e.g. `HL_WEBGPU_NODE_BINDINGS=/path/to/dawn.node`.
You must have the Dawn Node.js bindings installed to run these tests. Set the
`NODE_PATH` environment variable to the path to the `node_modules`
directory of the Dawn bindings.

See [below](#setting-up-dawn) for instructions on building the Dawn Node.js
bindings.
Expand All @@ -51,78 +52,75 @@ JIT compilation is not supported when using WebGPU with WASM.

For testing purposes, Halide can also target native WebGPU libraries, such as
[Dawn](https://dawn.googlesource.com/dawn/) or
[wgpu](https://github.com/gfx-rs/wgpu).
This is currently the only path that can run the JIT correctness tests.
See [below](#setting-up-dawn) for instructions on building Dawn.
[wgpu](https://github.com/gfx-rs/wgpu). This is currently the only path that can
run the JIT correctness tests. See [below](#setting-up-dawn) for instructions on
building Dawn.

> Note that as of 2023-11-27, wgpu is not supported due to
> [lacking `override` support for WGSL](https://github.com/gfx-rs/wgpu/issues/1762)
> which we require > in order to set GPU block sizes.
> Note that as of 2023-11-27, wgpu is not supported due to [lacking `override`
> support for WGSL](https://github.com/gfx-rs/wgpu/issues/1762) which we require
> to set GPU block sizes.

When targeting WebGPU with a native target, Halide defaults to looking for a
build of Dawn (with several common names and suffixes); you can override this
by setting the `HL_WEBGPU_NATIVE_LIB` environment variable to the absolute path
to the library you want.

Note that it is explicitly legal to define both `HL_WEBGPU_NATIVE_LIB` and
`HL_WEBGPU_NODE_BINDINGS` at the same time; the correct executable environment
will be selected based on the Halide target specified.

Note that it is explicitly legal to specify both WEBGPU_NATIVE_LIB and
WEBGPU_NODE_BINDINGS for the same build; the correct executable environment
will be selected based on the Halide target specified.
build of Dawn (with several common names and suffixes); you can override this by
setting the `HL_WEBGPU_NATIVE_LIB` environment variable to the absolute path to
the library you want.

## Setting up Dawn

Building Dawn's Node.js bindings currently requires using CMake.

First, [install `depot_tools`](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up) and add it to the
`PATH` environment variable.

Next, get Dawn and its dependencies:
Building Dawn's Node.js bindings currently requires using CMake. Start by
cloning Dawn and its dependencies:

# Clone the repo
git clone https://dawn.googlesource.com/dawn
cd dawn

# Bootstrap the gclient configuration with Node.js bindings enabled
cp scripts/standalone-with-node.gclient .gclient
# Fetch external dependencies
python3 tools/fetch_dawn_dependencies.py

# Fetch external dependencies and toolchains with gclient
gclient sync
# Their script misses a few:
git submodule update --init --depth 1 third_party/gpuweb
git submodule update --init --depth 1 third_party/node-addon-api
git submodule update --init --depth 1 third_party/node-api-headers

# Other dependencies that must be installed manually:
# - golang

Finally, build Dawn, enabling both the Node.js bindings and shared libraries:
Now patch Dawn to install the Node.js bindings:

mkdir -p <build_dir>
cd <build_dir>
echo "install(TARGETS dawn_node LIBRARY DESTINATION lib/node_modules)" >> src/dawn/node/CMakeLists.txt

cmake <dawn_root_dir> -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DDAWN_BUILD_NODE_BINDINGS=1 \
-DDAWN_ENABLE_PIC=1 \
-DBUILD_SHARED_LIBS=ON
Finally, build Dawn, enabling both the Node.js bindings and shared libraries:

ninja dawn.node webgpu_dawn
cmake -G Ninja -S . -B out/Release \
-DCMAKE_BUILD_TYPE=Release \
-DDAWN_BUILD_MONOLITHIC_LIBRARY=SHARED \
-DDAWN_BUILD_NODE_BINDINGS=ON \
-DDAWN_BUILD_PROTOBUF=OFF \
-DDAWN_BUILD_SAMPLES=OFF \
-DDAWN_BUILD_TESTS=OFF \
-DDAWN_ENABLE_INSTALL=ON \
-DDAWN_ENABLE_PIC=ON \
-DTINT_BUILD_CMD_TOOLS=OFF \
-DTINT_BUILD_TESTS=OFF
cmake --build out/Release
cmake --install out/Release --prefix /opt/dawn

This will produce the following artifacts:
- Node.js bindings: `<build_dir>/dawn.node`
- Native library: `<build_dir>/src/dawn/native/libwebgpu_dawn.{so,dylib,dll}`

These paths can then be used for the `HL_WEBGPU_NODE_BINDINGS` and
`HL_WEBGPU_NATIVE_LIB` environment variables when using Halide.
- Node.js bindings: `/opt/dawn/lib/node_modules/dawn.node`
- Native library: `/opt/dawn/lib/libwebgpu_dawn.{so,dylib,dll}`

You can then add `/opt/dawn/lib/node_modules` to `NODE_PATH` and `/opt/dawn/lib`
to `LD_LIBRARY_PATH`. You are, of course, free to choose any other installation
prefix besides `/opt/dawn` (e.g. `/usr/local`).

## Updating mini_webgpu.h

The recommended method for updating `mini_webgpu.h` is to copy the
`gen/include/dawn/webgpu.h` file from the Dawn build directory, then:
- Restore the `// clang-format {off,on}` lines.
- Comment out the `#include <std*>` lines.
- Remove the `void` parameter from the `WGPUProc` declaration.
`include/dawn/webgpu.h` file from the Dawn install directory, then comment out
the `#include` lines.

This guarantees a version of the WebGPU header that is compatible with Dawn.
When the native API eventually stabilizes, it should be possible to obtain a
header from the `webgpu-native` GitHub organization that will be compatible
with Dawn, wgpu, and Emscripten.
When the native API eventually stabilizes, it should be possible to get a header
from the `webgpu-native` GitHub organization that will be compatible with Dawn,
wgpu, and Emscripten.
Loading
Loading