Skip to content

Commit 5f3535f

Browse files
committed
Modernize gpu.cpp and add browser WebGPU support
1 parent cfdbcc6 commit 5f3535f

87 files changed

Lines changed: 2170 additions & 10702 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/build.yml‎

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,39 @@
1-
name: gpucpp-ci
1+
name: gpu.cpp
22

3-
on:
3+
on:
44
push:
5-
branches:
6-
- main
5+
branches: [main]
76
pull_request:
8-
types: [opened, reopened, labeled, unlabeled, synchronize]
9-
branches:
10-
- main
117
workflow_dispatch:
128

139
jobs:
14-
build:
15-
runs-on: ubuntu-latest
10+
test:
11+
strategy:
12+
matrix:
13+
os: [macos-latest, ubuntu-latest]
14+
runs-on: ${{ matrix.os }}
1615
steps:
17-
- name: Checkout repository
18-
uses: actions/checkout@v2
19-
20-
- name: No-op Step
21-
run: echo "This is a no-op action"
22-
23-
- name: Install CMake
24-
run: sudo apt-get install cmake
25-
26-
- name: Install dependencies
27-
run: |
28-
sudo apt-get update
29-
sudo apt-get install -y libvulkan1 mesa-vulkan-drivers vulkan-tools
30-
sudo apt-get install -y libxrandr-dev
16+
- uses: actions/checkout@v4
17+
- if: runner.os == 'Linux'
18+
run: |
19+
sudo apt-get update
20+
sudo apt-get install -y libvulkan1 mesa-vulkan-drivers ninja-build
21+
- run: python3 -m pip install numpy
22+
- run: tools/build_dawn.sh
23+
- run: ./test
3124

32-
- name: Build
33-
run: make all
34-
35-
- name: Run hello world
36-
run: make
25+
browser-build:
26+
runs-on: ubuntu-latest
27+
steps:
28+
- uses: actions/checkout@v4
29+
- uses: actions/checkout@v4
30+
with:
31+
repository: emscripten-core/emsdk
32+
path: emsdk
33+
fetch-depth: 1
34+
- run: |
35+
sudo apt-get update
36+
sudo apt-get install -y ninja-build
37+
- run: ./test --build-web
38+
env:
39+
GPUCPP_EMSDK_ROOT: ${{ github.workspace }}/emsdk

‎.gitignore‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
build/*
2+
build-web/
3+
build-dawn/
24
# any build subdirectory in the tree
35
**/build/
46
examples/hello_gpu/build/*
@@ -8,6 +10,8 @@ source
810
.DS_Store
911
third_party/lib/*
1012
third_party/local/*
13+
third_party/dawn/*
14+
third_party/emdawnwebgpu/*
1115

1216
# formatter files
1317
.cmake-format.py
@@ -19,4 +23,3 @@ build
1923
# clangd files
2024
.cache
2125
compile_commands.json
22-

‎CHANGELOG.md‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Changelog
2+
3+
## 0.2.0 - 2026-08-21
4+
5+
This release modernizes gpu.cpp around current Dawn and adds a maintained
6+
browser target.
7+
8+
### Added
9+
10+
- A browser backend using Emdawnwebgpu, Emscripten, JSPI, and an ES-module
11+
Embind API for persistent contexts and JavaScript typed arrays.
12+
- Explicit read/read-write bindings, reusable kernels, uniform parameters, and
13+
asynchronous dispatch and readback through `gpu::Future`.
14+
- Native SPIR-V input with an executable WebGPU-profile contract test.
15+
- C++ stories for WGSL, native f16, and SPIR-V; a NumPy Python story; and a
16+
Chrome story covering browser errors, context reuse, dispatch, and readback.
17+
- Reproducible scripts pinning Dawn, Emdawn, emsdk, SPIRV-Tools, and
18+
SPIRV-Headers to exact revisions.
19+
20+
### Changed
21+
22+
- WebGPU objects now use Dawn's generated C++ RAII facade and normal C++ value
23+
semantics.
24+
- The Python binding now follows the C++ API and preserves NumPy shape and
25+
`float16`, `float32`, and `int32` dtypes.
26+
- Host-side f16 uses native `_Float16` where supported; the portable core
27+
treats f16 as two-byte IEEE 754 storage.
28+
- Examples and the build are consolidated under the root CMake project and the
29+
single `./test` entrypoint.
30+
31+
### Removed
32+
33+
- The legacy raw WebGPU C API implementation, manual resource pools, custom
34+
half implementation, Haskell binding, obsolete build files, and abandoned
35+
experimental targets.

‎CMakeLists.txt‎

Lines changed: 139 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,154 @@
11
cmake_minimum_required(VERSION 3.28)
2-
project(gpu)
2+
project(gpu.cpp LANGUAGES CXX)
33

4-
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/webgpu.cmake")
5-
6-
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # export compile_commands.json to use with
7-
# LSP
8-
set(CMAKE_CXX_STANDARD 17)
4+
set(CMAKE_CXX_STANDARD 20)
95
set(CMAKE_CXX_STANDARD_REQUIRED ON)
6+
set(CMAKE_CXX_EXTENSIONS OFF)
7+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
8+
9+
if(EMSCRIPTEN)
10+
set(GPUCPP_BUILD_PYTHON_DEFAULT OFF)
11+
set(GPUCPP_BUILD_EXAMPLES_DEFAULT OFF)
12+
else()
13+
set(GPUCPP_BUILD_PYTHON_DEFAULT ${PROJECT_IS_TOP_LEVEL})
14+
set(GPUCPP_BUILD_EXAMPLES_DEFAULT ON)
15+
endif()
16+
option(GPUCPP_BUILD_PYTHON "Build the Python binding" ${GPUCPP_BUILD_PYTHON_DEFAULT})
17+
option(GPUCPP_BUILD_EXAMPLES "Build gpu.cpp examples" ${GPUCPP_BUILD_EXAMPLES_DEFAULT})
18+
19+
add_library(gpucpp INTERFACE)
20+
target_include_directories(gpucpp INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
1021

11-
option(USE_LOCAL_LIBS
12-
"Use local libraries instead of fetching from the internet" OFF)
22+
if(EMSCRIPTEN)
23+
set(GPUCPP_EMDAWN_ROOT
24+
"${CMAKE_CURRENT_SOURCE_DIR}/third_party/emdawnwebgpu" CACHE PATH
25+
"Staged Emdawnwebgpu package")
26+
set(EMDAWN_PORT
27+
"--use-port=${GPUCPP_EMDAWN_ROOT}/emdawnwebgpu.port.py")
28+
if(NOT EXISTS "${GPUCPP_EMDAWN_ROOT}/emdawnwebgpu.port.py")
29+
message(FATAL_ERROR "Emdawnwebgpu is not built; run tools/build_emdawn.sh")
30+
endif()
31+
target_compile_options(gpucpp INTERFACE "${EMDAWN_PORT}" "-fwasm-exceptions")
32+
target_link_options(gpucpp INTERFACE "${EMDAWN_PORT}" "-fwasm-exceptions"
33+
"-sJSPI=1" "--closure=1")
34+
if(CMAKE_HOST_APPLE)
35+
target_link_options(gpucpp INTERFACE "--closure-args=--platform=java")
36+
endif()
37+
else()
1338

14-
# Ensure the build type is set
15-
if(NOT CMAKE_BUILD_TYPE)
16-
set(CMAKE_BUILD_TYPE
17-
Release
18-
CACHE STRING "Choose the type of build: Debug or Release" FORCE)
39+
set(GPUCPP_DAWN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/third_party/dawn" CACHE PATH
40+
"Staged Dawn distribution")
41+
set(GPUCPP_LOCAL_DAWN "${CMAKE_CURRENT_SOURCE_DIR}/third_party/local/dawn" CACHE PATH
42+
"Developer Dawn source/build tree")
43+
44+
if(EXISTS "${GPUCPP_DAWN_ROOT}/include/dawn/webgpu_cpp.h")
45+
set(DAWN_INCLUDE_DIRS "${GPUCPP_DAWN_ROOT}/include")
46+
if(APPLE)
47+
set(DAWN_LIBRARY "${GPUCPP_DAWN_ROOT}/lib/libwebgpu_dawn.dylib")
48+
elseif(UNIX)
49+
set(DAWN_LIBRARY "${GPUCPP_DAWN_ROOT}/lib/libwebgpu_dawn.so")
50+
endif()
51+
set(SPIRV_AS "${GPUCPP_DAWN_ROOT}/bin/spirv-as")
52+
elseif(EXISTS "${GPUCPP_LOCAL_DAWN}/build-latest/gen/include/dawn/webgpu_cpp.h")
53+
set(DAWN_INCLUDE_DIRS
54+
"${GPUCPP_LOCAL_DAWN}/build-latest/gen/include"
55+
"${GPUCPP_LOCAL_DAWN}/source/include")
56+
if(APPLE)
57+
set(DAWN_LIBRARY
58+
"${GPUCPP_LOCAL_DAWN}/build-latest/src/dawn/native/libwebgpu_dawn.dylib")
59+
elseif(UNIX)
60+
set(DAWN_LIBRARY
61+
"${GPUCPP_LOCAL_DAWN}/build-latest/src/dawn/native/libwebgpu_dawn.so")
62+
endif()
63+
set(SPIRV_AS "${GPUCPP_LOCAL_DAWN}/build-spirv-tools/tools/spirv-as")
64+
else()
65+
message(FATAL_ERROR "Dawn is not built; run tools/build_dawn.sh")
1966
endif()
2067

21-
option(FASTBUILD "Option to enable fast builds" OFF)
22-
if(FASTBUILD)
23-
set(CMAKE_BUILD_TYPE None) # Avoid default flags of predefined build types
24-
set(CMAKE_CXX_FLAGS "-O0")
68+
if(NOT EXISTS "${DAWN_LIBRARY}")
69+
message(FATAL_ERROR "Dawn library not found at ${DAWN_LIBRARY}")
70+
endif()
71+
if(NOT EXISTS "${SPIRV_AS}")
72+
message(FATAL_ERROR "spirv-as not found at ${SPIRV_AS}")
2573
endif()
2674

27-
option(DEBUG "Option to enable debug flags" OFF)
28-
if(DEBUG)
29-
set(CMAKE_BUILD_TYPE Debug)
30-
set(CMAKE_CXX_FLAGS "-O0 -g")
75+
add_library(Dawn::webgpu SHARED IMPORTED)
76+
set_target_properties(Dawn::webgpu PROPERTIES
77+
IMPORTED_LOCATION "${DAWN_LIBRARY}"
78+
INTERFACE_INCLUDE_DIRECTORIES "${DAWN_INCLUDE_DIRS}")
79+
80+
target_link_libraries(gpucpp INTERFACE Dawn::webgpu)
3181
endif()
3282

33-
if(WIN64)
34-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN")
83+
if(GPUCPP_BUILD_PYTHON)
84+
find_package(Python 3.9 COMPONENTS Interpreter Development.Module REQUIRED)
85+
include(FetchContent)
86+
FetchContent_Declare(pybind11
87+
GIT_REPOSITORY https://github.com/pybind/pybind11.git
88+
GIT_TAG v3.0.4
89+
GIT_SHALLOW TRUE)
90+
FetchContent_MakeAvailable(pybind11)
91+
92+
pybind11_add_module(gpu_cpp bindings/python/gpu_cpp.cpp)
93+
target_link_libraries(gpu_cpp PRIVATE gpucpp)
3594
endif()
3695

37-
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpu.cmake")
96+
if(GPUCPP_BUILD_EXAMPLES)
97+
add_executable(hello_gpu examples/hello_world/run.cpp)
98+
add_executable(float16_gpu examples/float16/run.cpp)
99+
add_executable(gpu_puzzles examples/gpu_puzzles/run.cpp)
100+
add_executable(gpu_puzzles_key examples/gpu_puzzles/key.cpp)
101+
add_executable(matmul_gpu examples/matmul/run.cpp)
102+
add_executable(physics_gpu examples/physics/run.cpp)
103+
add_executable(render_gpu examples/render/run.cpp)
104+
add_executable(shadertui_gpu examples/shadertui/run.cpp)
105+
add_executable(transpose_gpu examples/transpose/run.cpp)
38106

39-
message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}")
40-
message(
41-
STATUS
42-
"Include directories for wgpu: ${CMAKE_CURRENT_SOURCE_DIR}/third_party/headers"
43-
)
107+
foreach(target IN ITEMS hello_gpu float16_gpu gpu_puzzles gpu_puzzles_key
108+
matmul_gpu physics_gpu render_gpu shadertui_gpu
109+
transpose_gpu)
110+
target_link_libraries(${target} PRIVATE gpucpp)
111+
endforeach()
112+
target_include_directories(matmul_gpu PRIVATE third_party/headers)
113+
target_include_directories(transpose_gpu PRIVATE third_party/headers)
44114

45-
add_library(gpud SHARED gpu.hpp)
46-
set_target_properties(gpud PROPERTIES LINKER_LANGUAGE CXX)
47-
target_link_libraries(gpud PRIVATE wgpu)
48-
target_link_libraries(gpud PRIVATE webgpu)
49-
target_link_libraries(gpud PRIVATE gpu)
50-
install(TARGETS gpud)
115+
endif()
116+
117+
enable_testing()
118+
if(EMSCRIPTEN)
119+
add_library(gpu_cpp_web_bindings OBJECT bindings/web/gpu_cpp.cpp)
120+
target_link_libraries(gpu_cpp_web_bindings PRIVATE gpucpp)
121+
122+
add_executable(gpu_cpp_web $<TARGET_OBJECTS:gpu_cpp_web_bindings>)
123+
set_target_properties(gpu_cpp_web PROPERTIES SUFFIX ".mjs")
124+
target_link_libraries(gpu_cpp_web PRIVATE gpucpp)
125+
target_link_options(gpu_cpp_web PRIVATE "--bind" "--no-entry"
126+
"-sMODULARIZE=1" "-sEXPORT_ES6=1" "-sEXPORT_NAME=createGpuCpp"
127+
"-sENVIRONMENT=web" "-sALLOW_MEMORY_GROWTH=1")
128+
129+
add_executable(web_binding_test tests/web_binding_test.cpp
130+
$<TARGET_OBJECTS:gpu_cpp_web_bindings>)
131+
set_target_properties(web_binding_test PROPERTIES SUFFIX ".html")
132+
target_link_libraries(web_binding_test PRIVATE gpucpp)
133+
target_link_options(web_binding_test PRIVATE "--bind" "--emrun"
134+
"-sMODULARIZE=1" "-sEXPORT_ES6=1"
135+
"-sALLOW_MEMORY_GROWTH=1")
136+
else()
137+
set(TEST_SPIRV "${CMAKE_CURRENT_BINARY_DIR}/write42.spv")
138+
add_custom_command(
139+
OUTPUT "${TEST_SPIRV}"
140+
COMMAND "${SPIRV_AS}" --target-env spv1.3
141+
"${CMAKE_CURRENT_SOURCE_DIR}/tests/write42.spvasm" -o "${TEST_SPIRV}"
142+
DEPENDS tests/write42.spvasm
143+
VERBATIM)
144+
145+
add_executable(gpu_test tests/gpu_test.cpp "${TEST_SPIRV}")
146+
target_link_libraries(gpu_test PRIVATE gpucpp)
147+
add_test(NAME gpu COMMAND gpu_test "${TEST_SPIRV}")
148+
endif()
149+
if(GPUCPP_BUILD_PYTHON)
150+
add_test(NAME python
151+
COMMAND "${Python_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/bindings/python/test_gpu_cpp.py")
152+
set_tests_properties(python PROPERTIES
153+
ENVIRONMENT "PYTHONPATH=$<TARGET_FILE_DIR:gpu_cpp>")
154+
endif()

0 commit comments

Comments
 (0)