Skip to content

Commit d1c0b81

Browse files
committed
adds emscripten support
1 parent ebd5bcf commit d1c0b81

File tree

9 files changed

+260
-106
lines changed

9 files changed

+260
-106
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
build/*
22
# any build subdirectory in the tree
33
**/build/
4+
**/build_web/
45
examples/hello_gpu/build/*
56
examples/raymarch/build/*
67
docs/html
78
source
89
.DS_Store
910
third_party/lib/*
1011
third_party/local/*
12+
third_party/dawn/*
1113

1214
# formatter files
1315
.cmake-format.py

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ if(DEBUG)
2020
set(CMAKE_CXX_FLAGS "-O0 -g")
2121
endif()
2222

23+
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/dawn.cmake")
2324
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpu.cmake")
2425

2526
add_library(gpud SHARED gpu.hpp)

cmake/dawn.cmake

+149
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
# Setup directories
2+
set(FETCHCONTENT_BASE_DIR "${PROJECT_ROOT}/third_party")
3+
set(DAWN_DIR "${FETCHCONTENT_BASE_DIR}/dawn" CACHE INTERNAL "")
4+
set(DAWN_BUILD_DIR "${DAWN_DIR}/build" CACHE INTERNAL "")
5+
6+
if(EMSCRIPTEN)
7+
set(EM_SDK_DIR $ENV{EMSDK} CACHE INTERNAL "")
8+
set(DAWN_BUILD_DIR "${DAWN_DIR}/build_web" CACHE INTERNAL "")
9+
endif()
10+
11+
function(find_dawn_library)
12+
if(MSVC)
13+
find_library(WEBGPU_DAWN_DEBUG webgpu_dawn
14+
NAMES webgpu_dawn
15+
HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug"
16+
)
17+
find_library(WEBGPU_DAWN_RELEASE webgpu_dawn
18+
NAMES webgpu_dawn
19+
HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release"
20+
)
21+
elseif(NOT EMSCRIPTEN AND NOT MSVC)
22+
find_library(WEBGPU_DAWN_LIB
23+
NAMES webgpu_dawn
24+
PATHS "${DAWN_BUILD_DIR}/src/dawn/native"
25+
REQUIRED
26+
)
27+
endif()
28+
29+
# Set result variables in parent scope
30+
set(DAWN_BUILD_FOUND ON PARENT_SCOPE)
31+
if(MSVC)
32+
set(WEBGPU_DAWN_DEBUG ${WEBGPU_DAWN_DEBUG} PARENT_SCOPE)
33+
set(WEBGPU_DAWN_RELEASE ${WEBGPU_DAWN_RELEASE} PARENT_SCOPE)
34+
else()
35+
set(WEBGPU_DAWN_LIB ${WEBGPU_DAWN_LIB} PARENT_SCOPE)
36+
endif()
37+
endfunction()
38+
39+
# Enable find for no dawn rebuilds with flutter run
40+
set(ENABLE_DAWN_FIND OFF CACHE BOOL "Enable finding Dawn" FORCE)
41+
set(DAWN_BUILD_FOUND OFF CACHE BOOL "Dawn build found" FORCE)
42+
if(ENABLE_DAWN_FIND)
43+
# find_library, windows adds extra folder
44+
if(MSVC)
45+
find_library(WEBGPU_DAWN_DEBUG webgpu_dawn
46+
NAMES webgpu_dawn
47+
HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug"
48+
)
49+
find_library(WEBGPU_DAWN_RELEASE webgpu_dawn
50+
NAMES webgpu_dawn
51+
HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release"
52+
)
53+
set(DAWN_BUILD_FOUND ON)
54+
elseif(NOT EMSCRIPTEN AND NOT MSVC)
55+
find_library(WEBGPU_DAWN_LIB
56+
NAMES webgpu_dawn
57+
PATHS "${DAWN_BUILD_DIR}/src/dawn/native"
58+
REQUIRED
59+
)
60+
set(DAWN_BUILD_FOUND ON)
61+
else()
62+
set(DAWN_BUILD_FOUND ON)
63+
endif()
64+
endif()
65+
66+
# Dawn options for more,
67+
# see https://dawn.googlesource.com/dawn/+/refs/heads/main/CMakeLists.txt
68+
set(DAWN_ALWAYS_ASSERT OFF CACHE INTERNAL "Always assert in Dawn" FORCE)
69+
set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE INTERNAL "Build Dawn monolithically" FORCE)
70+
set(DAWN_BUILD_EXAMPLES OFF CACHE INTERNAL "Build Dawn examples" FORCE)
71+
set(DAWN_BUILD_SAMPLES OFF CACHE INTERNAL "Build Dawn samples" FORCE)
72+
set(DAWN_BUILD_TESTS OFF CACHE INTERNAL "Build Dawn tests" FORCE)
73+
set(DAWN_ENABLE_INSTALL OFF CACHE INTERNAL "Enable Dawn installation" FORCE)
74+
set(DAWN_FETCH_DEPENDENCIES ON CACHE INTERNAL "Fetch Dawn dependencies" FORCE)
75+
set(TINT_BUILD_TESTS OFF CACHE INTERNAL "Build Tint Tests" FORCE)
76+
set(TINT_BUILD_IR_BINARY OFF CACHE INTERNAL "Build Tint IR binary" FORCE)
77+
set(TINT_BUILD_CMD_TOOLS OFF CACHE INTERNAL "Build Tint command line tools" FORCE)
78+
79+
if(NOT DAWN_BUILD_FOUND)
80+
include(FetchContent)
81+
message("webgpu_dawn not found start building")
82+
if(EMSCRIPTEN)
83+
set(EMSCRIPTEN_DIR "${EM_SDK_DIR}/upstream/emscripten" CACHE INTERNAL "" FORCE)
84+
set(DAWN_EMSCRIPTEN_TOOLCHAIN ${EMSCRIPTEN_DIR} CACHE INTERNAL "" FORCE)
85+
endif()
86+
87+
FetchContent_Declare(
88+
dawn
89+
DOWNLOAD_DIR ${DAWN_DIR}
90+
SOURCE_DIR ${DAWN_DIR}
91+
SUBBUILD_DIR ${DAWN_BUILD_DIR}/tmp
92+
BINARY_DIR ${DAWN_BUILD_DIR}
93+
DOWNLOAD_COMMAND
94+
cd ${DAWN_DIR} &&
95+
git init &&
96+
git fetch --depth=1 https://dawn.googlesource.com/dawn &&
97+
git reset --hard FETCH_HEAD
98+
)
99+
100+
# Download the repository and add it as a subdirectory.
101+
FetchContent_MakeAvailable(dawn)
102+
103+
# attempt fix flutter rebuilds
104+
set(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH};${DAWN_DIR}/src" CACHE INTERNAL "")
105+
106+
execute_process(
107+
WORKING_DIRECTORY ${DAWN_DIR}
108+
COMMAND ${CMAKE_COMMAND} -S ${DAWN_DIR}
109+
-B ${DAWN_BUILD_DIR}
110+
)
111+
112+
# Build Dawn
113+
execute_process(
114+
COMMAND ${CMAKE_COMMAND} --build ${DAWN_BUILD_DIR}
115+
)
116+
117+
# find_library, windows adds extra folder
118+
if(MSVC)
119+
find_library(WEBGPU_DAWN_DEBUG webgpu_dawn
120+
NAMES webgpu_dawn
121+
HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug"
122+
)
123+
find_library(WEBGPU_DAWN_RELEASE webgpu_dawn
124+
NAMES webgpu_dawn
125+
HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release"
126+
)
127+
set(DAWN_BUILD_FOUND ON)
128+
elseif(NOT EMSCRIPTEN AND NOT MSVC)
129+
find_library(WEBGPU_DAWN_LIB
130+
NAMES webgpu_dawn
131+
PATHS "${DAWN_BUILD_DIR}/src/dawn/native"
132+
REQUIRED
133+
)
134+
set(DAWN_BUILD_FOUND ON)
135+
else()
136+
set(DAWN_BUILD_FOUND ON)
137+
endif()
138+
endif()
139+
140+
if(EMSCRIPTEN)
141+
add_library(webgpu_dawn INTERFACE IMPORTED)
142+
target_include_directories(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include)
143+
target_include_directories(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include/webgpu/webgpu.h)
144+
target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js)
145+
target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js)
146+
target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_sig_info.js)
147+
target_link_libraries(webgpu_dawn INTERFACE ${DAWN_DIR}/third_party/emdawnwebgpu/library_webgpu.js)
148+
else()
149+
endif()

cmake/example.cmake

+73-21
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,97 @@
11
# Getting Started with CMAKE
2-
# Each example includes this and sets PROJECT_NAME
3-
# cd examples/hello_world
4-
# cmake -S . build/ -DCMAKE_BUILD_TYPE=Release
5-
# cmake --build build/ --config Release
6-
# ./build/hello_world
2+
# Each example includes this and sets PROJECT_NAME.
3+
#
4+
# Example usage:
5+
# cd examples/hello_world
6+
# cmake -S . build/ -DCMAKE_BUILD_TYPE=Release
7+
# cmake --build build/ --config Release
8+
# ./build/hello_world (or serve the output .js/.wasm for Emscripten)
9+
# or for emscripten
10+
# emcmake cmake -S . -B ./build_web -DCMAKE_BUILD_TYPE=Release
11+
# cmake --build build_web --config Release
712

813
if(NOT MSVC)
914
set(CMAKE_CXX_STANDARD 17)
1015
else()
1116
set(CMAKE_CXX_STANDARD 20)
1217
endif()
1318

14-
# Path finding logic to find our root recipes from nested folders
19+
# Locate the project root (two levels up from the current source dir)
1520
get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
1621
get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY)
1722

18-
# Ensure the build type is set
19-
if(NOT CMAKE_BUILD_TYPE)
20-
set(CMAKE_BUILD_TYPE
21-
Release
22-
CACHE STRING "Choose the type of build: Debug or Release" FORCE)
23-
endif()
24-
25-
# Include the gpu.cpp + Dawn library
23+
# Include external libraries and helper scripts (dawn and gpu)
24+
include("${PROJECT_ROOT}/cmake/dawn.cmake")
2625
include("${PROJECT_ROOT}/cmake/gpu.cmake")
2726

2827
# Create the executable
2928
add_executable(${PROJECT_NAME} run.cpp)
3029

31-
# Link gpu + dawn library
30+
# Platform-specific linking & build settings
31+
if(EMSCRIPTEN)
32+
# Emscripten-specific configuration
33+
34+
# Define a web output directory (adjust as needed)
35+
set(WEB_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/web_build")
36+
37+
# If necessary, include the generated WebGPU include dirs first.
38+
include_directories(BEFORE "${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include/")
39+
40+
# Create a helper library for WebGPU support.
41+
add_library(webgpu_web "${DAWN_DIR}/third_party/emdawnwebgpu/webgpu.cpp")
42+
target_link_libraries(${PROJECT_NAME} PRIVATE webgpu_web)
43+
44+
# Set Emscripten-specific link flags that enable WASM output and expose certain symbols.
45+
# Needed to use updated version, emdawnwebgpu
46+
set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "\
47+
-sUSE_WEBGPU=0 \
48+
-sWASM=1 \
49+
-DDAWN_EMSCRIPTEN_TOOLCHAIN=${EMSCRIPTEN_DIR} \
50+
-sEXPORTED_FUNCTIONS=_main,_malloc,_free,_memcpy \
51+
-sEXPORTED_RUNTIME_METHODS=ccall \
52+
-sUSE_GLFW=3 \
53+
-sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=10000000 \
54+
-sASYNCIFY \
55+
--js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js \
56+
--js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js \
57+
--js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_sig_info.js \
58+
--js-library=${DAWN_DIR}/third_party/emdawnwebgpu/library_webgpu.js \
59+
--closure-args=--externs=${EMSCRIPTEN_DIR}/src/closure-externs/webgpu-externs.js \
60+
-O3 \
61+
")
62+
63+
else()
64+
# Non-Emscripten (desktop) linking
65+
if(MSVC)
66+
target_link_libraries(gpu
67+
PRIVATE
68+
$<$<CONFIG:Debug>:${WEBGPU_DAWN_DEBUG}>
69+
$<$<CONFIG:Release>:${WEBGPU_DAWN_RELEASE}>
70+
)
71+
else()
72+
target_link_libraries(gpu PRIVATE webgpu_dawn)
73+
endif()
74+
endif()
75+
76+
# Link the gpu/dawn library to the executable.
3277
target_link_libraries(${PROJECT_NAME} PRIVATE gpu)
3378

34-
# Certain platforms need to copy the library files to the build directory
79+
# Platform-specific post-build actions (e.g. copying DLLs for MSVC)
3580
if(MSVC)
36-
# Copy webgpu_dawn.dll to the build directory
37-
# CMake multigenerators like MSVC need --config Release on
38-
# the cmake --build command or they will output to /Debug
3981
add_custom_command(
4082
TARGET ${PROJECT_NAME} POST_BUILD
4183
COMMAND ${CMAKE_COMMAND} -E copy
42-
${DAWN_INSTALL_PREFIX}/${CMAKE_BUILD_TYPE}/webgpu_dawn.dll
43-
$<TARGET_FILE_DIR:${PROJECT_NAME}>)
84+
${DAWN_BUILD_DIR}/$<CONFIG>/webgpu_dawn.dll
85+
$<TARGET_FILE_DIR:${PROJECT_NAME}>
86+
COMMENT "Copying webgpu_dawn.dll to the build directory"
87+
)
4488
endif()
4589

90+
if(EMSCRIPTEN)
91+
92+
# Configure the HTML file by replacing @PROJECT_NAME@ with the actual target name.
93+
configure_file(${PROJECT_ROOT}cmake/templates/index.html.in
94+
${CMAKE_CURRENT_BINARY_DIR}/index.html
95+
@ONLY)
96+
97+
endif()

0 commit comments

Comments
 (0)