From b748399f1f567640577a1bfd46a38814bf5c22e9 Mon Sep 17 00:00:00 2001 From: MichealReed Date: Tue, 11 Feb 2025 01:43:13 -0600 Subject: [PATCH 01/13] simplify cmake, build dawn in repo, fix render for windows --- .gitignore | 3 + CMakeLists.txt | 29 +------ cmake/example.cmake | 27 +++---- cmake/gpu.cmake | 170 +++++++++++++++++++++++++--------------- cmake/webgpu.cmake | 61 -------------- examples/render/run.cpp | 11 +-- 6 files changed, 132 insertions(+), 169 deletions(-) delete mode 100644 cmake/webgpu.cmake diff --git a/.gitignore b/.gitignore index 1a8b5bc..c7f60c3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,6 @@ build .cache compile_commands.json +# editor specific +.vscode/* + diff --git a/CMakeLists.txt b/CMakeLists.txt index db89df7..a464b34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,23 +1,11 @@ cmake_minimum_required(VERSION 3.28) project(gpu) -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/webgpu.cmake") - set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # export compile_commands.json to use with # LSP -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -option(USE_LOCAL_LIBS - "Use local libraries instead of fetching from the internet" OFF) - -# Ensure the build type is set -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE - Release - CACHE STRING "Choose the type of build: Debug or Release" FORCE) -endif() - option(FASTBUILD "Option to enable fast builds" OFF) if(FASTBUILD) set(CMAKE_BUILD_TYPE None) # Avoid default flags of predefined build types @@ -30,21 +18,8 @@ if(DEBUG) set(CMAKE_CXX_FLAGS "-O0 -g") endif() -if(WIN64) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN") -endif() - include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpu.cmake") -message(STATUS "CMAKE_CURRENT_SOURCE_DIR: ${CMAKE_CURRENT_SOURCE_DIR}") -message( - STATUS - "Include directories for wgpu: ${CMAKE_CURRENT_SOURCE_DIR}/third_party/headers" -) - add_library(gpud SHARED gpu.hpp) set_target_properties(gpud PROPERTIES LINKER_LANGUAGE CXX) -target_link_libraries(gpud PRIVATE wgpu) -target_link_libraries(gpud PRIVATE webgpu) -target_link_libraries(gpud PRIVATE gpu) -install(TARGETS gpud) +target_link_libraries(gpud PRIVATE gpu) \ No newline at end of file diff --git a/cmake/example.cmake b/cmake/example.cmake index eba8e7c..41b15fd 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -1,17 +1,17 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # export compile_commands.json to use with # LSP -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) # Construct potential paths -set(FILEPATH_CURRENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") -set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/${FILENAME}") +set(FILEPATH_CURRENT_DIR "${DIRECTORY}/") +set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/") # Include file finding utility script -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/find_gpu.cmake") +include("${FILEPATH_PROJECT_ROOT}/cmake/find_gpu.cmake") # Check if the file exists in the current directory find_project_root(${CMAKE_CURRENT_SOURCE_DIR} ${FILENAME} @@ -49,20 +49,19 @@ endif() if(NOT TARGET gpu) message(STATUS "GPU_LIB not found") - include("${TARGET_FILE_PATH}/cmake/webgpu.cmake") include("${TARGET_FILE_PATH}/cmake/gpu.cmake") endif() - add_executable(${PROJECT_NAME} run.cpp) target_link_libraries(${PROJECT_NAME} PRIVATE gpu) -target_link_libraries(${PROJECT_NAME} PRIVATE wgpu) -target_link_libraries(${PROJECT_NAME} PRIVATE webgpu) +target_link_libraries(${PROJECT_NAME} PRIVATE ${WEBGPU_DAWN}) -if(WIN32) - # Ensure DLL is copied if on Windows +if(MSVC) +# Copy webgpu_dawn.dll to the build directory add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DLL_PATH} - $) + TARGET ${PROJECT_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${DAWN_INSTALL_PREFIX}/${CMAKE_BUILD_TYPE}/webgpu_dawn.dll + $ + ) endif() + diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index 08db244..15f3b43 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -1,69 +1,115 @@ -get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) -get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) - -# Construct potential paths -set(FILEPATH_CURRENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") -set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/${FILENAME}") - -# Include file finding utility script -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/find_gpu.cmake") - -# Check if the file exists in the current directory -find_project_root(${CMAKE_CURRENT_SOURCE_DIR} ${FILENAME} TARGET_FILE_PATH) -if("${TARGET_FILE_PATH}" STREQUAL "") - find_project_root(${FILEPATH_CURRENT_DIR} ${FILENAME} TARGET_FILE_PATH) - if("${TARGET_FILE_PATH}" STREQUAL "") - message( - FATAL_ERROR - "File ${FILENAME} not found in either ${CMAKE_CURRENT_SOURCE_DIR} or ${CMAKE_CURRENT_SOURCE_DIR}/../../" - ) - endif() -endif() +set(FILENAME "gpu.hpp") -# Define architecture and build type directories or file names -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH "x64") +if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") + set(FILEPATH_PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") else() - set(ARCH "x86") + get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) + get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) + + set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/") endif() -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(BUILD_TYPE "Debug") + +include(FetchContent) + +set(FETCHCONTENT_BASE_DIR "${FILEPATH_PROJECT_ROOT}/third_party/fetchcontent/_deps") +set(DAWN_INSTALL_PREFIX "${FETCHCONTENT_BASE_DIR}/dawn-build/out/${CMAKE_BUILD_TYPE}" CACHE INTERNAL "Dawn install location" FORCE) + + +# Before fetching, set configuration options for Dawn. +# These CMake variables are “global” (cached INTERNAL) so that Dawn’s own CMakeLists.txt +# will pick them up. Adjust them as needed. +set(DAWN_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE INTERNAL "Dawn build type" FORCE) +set(DCMAKE_INSTALL_PREFIX ${DAWN_INSTALL_PREFIX} CACHE INTERNAL "Dawn install location" FORCE) + +# Dawn options +set(DAWN_FETCH_DEPENDENCIES ON CACHE INTERNAL "Fetch Dawn dependencies" FORCE) +set(DAWN_ENABLE_INSTALL ON CACHE INTERNAL "Enable Dawn installation" FORCE) +set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF CACHE INTERNAL "Build Dawn monolithically" FORCE) +set(DAWN_BUILD_EXAMPLES OFF CACHE INTERNAL "Build Dawn examples" FORCE) +set(DAWN_BUILD_SAMPLES OFF CACHE INTERNAL "Build Dawn samples" FORCE) +set(DAWN_BUILD_TESTS OFF CACHE INTERNAL "Build Dawn tests" FORCE) +set(DAWN_BUILD_UTILS OFF CACHE INTERNAL "Build Dawn utilities" FORCE) +set(TINT_BUILD_TESTS OFF CACHE INTERNAL "Build Tint Tests" FORCE) +set(TINT_BUILD_IR_BINARY OFF CACHE INTERNAL "Build Tint IR binary" FORCE) +set(TINT_BUILD_CMD_TOOLS OFF CACHE INTERNAL "Build Tint command line tools" FORCE) +set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries" FORCE) + + +# Set up an install location for Dawn – you can change this to a specific location. + + +FetchContent_Declare( + dawn + DOWNLOAD_COMMAND + cd ${FETCHCONTENT_BASE_DIR}/dawn-src && + git init && + git fetch --depth=1 https://dawn.googlesource.com/dawn && + git reset --hard FETCH_HEAD +) + + +# This call will download the repository and add it as a subdirectory. +FetchContent_MakeAvailable(dawn) + + +# At this point, assuming Dawn’s CMakeLists.txt is written so that an install step is available, +# we trigger a build of its install target. This custom target will build (and install) Dawn +# into ${DAWN_INSTALL_PREFIX}. (If Dawn already adds an install target, you may simply depend on it.) +add_custom_target(build_dawn_config ALL + COMMAND ${CMAKE_COMMAND} ${FETCHCONTENT_BASE_DIR}/dawn-src + -B ${DAWN_INSTALL_PREFIX} + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DDAWN_FETCH_DEPENDENCIES=ON + -DDAWN_ENABLE_INSTALL=ON + -DDAWN_BUILD_MONOLITHIC_LIBRARY=OFF + -DDAWN_BUILD_EXAMPLES=OFF + -DDAWN_BUILD_SAMPLES=OFF + -DDAWN_BUILD_TESTS=OFF + -DDAWN_BUILD_UTILS=OFF + -DTINT_BUILD_TESTS=OFF + -DTINT_BUILD_IR_BINARY=OFF + -DTINT_BUILD_CMD_TOOLS=OFF + -DBUILD_SHARED_LIBS=OFF + -G "${CMAKE_GENERATOR}" + COMMENT "Configuring Dawn build with custom options in ${DAWN_INSTALL_PREFIX}" +) + +add_custom_target(build_dawn_install ALL + COMMAND ${CMAKE_COMMAND} --build ${DAWN_INSTALL_PREFIX} --target install + COMMENT "Installing Dawn into ${DAWN_INSTALL_PREFIX}" +) + +include(${FETCHCONTENT_BASE_DIR}/dawn-build/cmake/DawnTargets.cmake) + +set(GPU_SOURCES + "${FILEPATH_PROJECT_ROOT}/gpu.cpp" + "${FILEPATH_PROJECT_ROOT}/numeric_types/half.cpp" +) + +set(GPU_HEADERS + "${FILEPATH_PROJECT_ROOT}/gpu.hpp" + "${FILEPATH_PROJECT_ROOT}/utils/logging.hpp" + "${FILEPATH_PROJECT_ROOT}/utils/array_utils.hpp" + "${FILEPATH_PROJECT_ROOT}/numeric_types/half.hpp" +) + +if(EMSCRIPTEN) + file(REMOVE "${FILEPATH_PROJECT_ROOT}/webgpu/webgpu.h") else() - set(BUILD_TYPE "Release") + list(APPEND GPU_HEADERS "${DAWN_INSTALL_PREFIX}/gen/webgpu-headers/webgpu.h") endif() -add_library(webgpulib SHARED IMPORTED) -add_library(gpu INTERFACE) -add_library(wgpu INTERFACE) -add_dependencies(gpu webgpulib) -# Define the header-only library -target_include_directories(gpu INTERFACE ${TARGET_FILE_PATH}) - -# Add headers webgpu.h -target_include_directories(wgpu - INTERFACE ${TARGET_FILE_PATH}/third_party/headers) -include(ExternalProject) - -set(DAWN_EXT_PREFIX "${TARGET_FILE_PATH}/third_party/local/dawn") - -ExternalProject_Add( - dawn_project - PREFIX ${DAWN_EXT_PREFIX} - GIT_REPOSITORY "https://dawn.googlesource.com/dawn" - GIT_TAG "main" - SOURCE_DIR "${DAWN_EXT_PREFIX}/source" - BINARY_DIR "${DAWN_EXT_PREFIX}/build" - INSTALL_DIR "${DAWN_EXT_PREFIX}/install" - GIT_SUBMODULES "" - # setting cmake args doesn't work and I don't know why - CONFIGURE_COMMAND - ${CMAKE_COMMAND} -S ${DAWN_EXT_PREFIX}/source -B - ${DAWN_EXT_PREFIX}/build -DDAWN_FETCH_DEPENDENCIES=ON - -DDAWN_ENABLE_INSTALL=ON -DDAWN_BUILD_MONOLITHIC_LIBRARY=ON - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -G ${CMAKE_GENERATOR} - INSTALL_COMMAND ${CMAKE_COMMAND} --install . --prefix - ${DAWN_EXT_PREFIX}/install - LOG_INSTALL ON) -find_library(LIBDAWN dawn PATHS "${DAWN_EXT_PREFIX}/install/lib") -target_link_libraries(webgpulib INTERFACE ${LIBDAWN}) + +# Create the INTERFACE library ‘gpu’ +add_library(gpu STATIC ${GPU_SOURCES} ${GPU_HEADERS}) +target_include_directories(gpu PUBLIC "${FILEPATH_PROJECT_ROOT}") +target_include_directories(gpu PUBLIC "${FILEPATH_PROJECT_ROOT}/third_party/headers") + +# Ensure that the gpu target is built only after Dawn has been installed. +add_dependencies(gpu build_dawn_install) + +find_library(WEBGPU_DAWN + NAMES webgpu_dawn + HINTS "${DAWN_INSTALL_PREFIX}/src/dawn/native/Debug/" +) \ No newline at end of file diff --git a/cmake/webgpu.cmake b/cmake/webgpu.cmake deleted file mode 100644 index c63f1e2..0000000 --- a/cmake/webgpu.cmake +++ /dev/null @@ -1,61 +0,0 @@ -# Specify the filename to search for -set(FILENAME "gpu.hpp") - -get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) -get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) - -# Construct potential paths -set(FILEPATH_CURRENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") -set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/${FILENAME}") - -# Include file finding utility script -include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/find_gpu.cmake") - -# Check if the file exists in the current directory -find_project_root(${CMAKE_CURRENT_SOURCE_DIR} ${FILENAME} TARGET_FILE_PATH) -if("${TARGET_FILE_PATH}" STREQUAL "") - find_project_root(${FILEPATH_CURRENT_DIR} ${FILENAME} TARGET_FILE_PATH) - if("${TARGET_FILE_PATH}" STREQUAL "") - message( - FATAL_ERROR - "File ${FILENAME} not found in either ${CMAKE_CURRENT_SOURCE_DIR} or ${CMAKE_CURRENT_SOURCE_DIR}/../../" - ) - endif() -endif() - -include(FetchContent) - -set(FETCHCONTENT_BASE_DIR "${TARGET_FILE_PATH}/third_party/fetchcontent") -set(WEBGPU_DIST_LOCAL_PATH - "${TARGET_FILE_PATH}/third_party/local/WebGPU-distribution") - -if(USE_LOCAL_LIBS) - set(WEBGPU_DIST_GIT_REPO ${WEBGPU_DIST_LOCAL_PATH}) - message(STATUS "Using local WebGPU distribution: ${WEBGPU_DIST_LOCAL_PATH}") -else() - set(WEBGPU_DIST_GIT_REPO - "https://github.com/eliemichel/WebGPU-distribution") -endif() - -option(WEBGPU_TAG "WebGPU distribution tag to use") -if(NOT WEBGPU_TAG) - set(WEBGPU_TAG "dawn") -endif() -message(STATUS "Using WebGPU distribution tag: ${WEBGPU_TAG}") - -if(WEBGPU_TAG STREQUAL "dawn") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWEBGPU_BACKEND_DAWN") - # use specific commit set(WEBGPU_TAG - # "1025b977e1927b6d0327e67352f90feb4bcf8274") set(WEBGPU_TAG - # "acf972b7b909f52e183bdae3971b93bb13d4a29e") - # add_compile_options(-UABSL_INTERNAL_AT_LEAST_CXX20) set(CMAKE_CXX_FLAGS - # "${CMAKE_CXX_FLAGS} -UABSL_INTERNAL_AT_LEAST_CXX20") - message(STATUS "Using Dawn backend") -endif() - -FetchContent_Declare( - webgpu - GIT_REPOSITORY ${WEBGPU_DIST_GIT_REPO} - GIT_TAG ${WEBGPU_TAG} - GIT_SHALLOW TRUE) -FetchContent_MakeAvailable(webgpu) diff --git a/examples/render/run.cpp b/examples/render/run.cpp index f2c6bec..f9a90f9 100644 --- a/examples/render/run.cpp +++ b/examples/render/run.cpp @@ -149,11 +149,12 @@ int main(int argc, char **argv) { std::array raster; for (size_t i = 0; i < screen.size(); ++i) { - size_t index = - std::min(sizeof(intensity) - 2, - std::max(0ul, static_cast(screen[i] * - (sizeof(intensity) - 2)))); - raster[i] = intensity[index]; + // Convert all values to size_t to ensure proper type matching + const size_t intensity_max = sizeof(intensity) - 2; + const size_t scaled_value = static_cast(screen[i] * intensity_max); + size_t index = std::min(intensity_max, + std::max(static_cast(0), scaled_value)); + raster[i] = intensity[index]; } char buffer[(NROWS + 2) * (NCOLS + 2)]; From bbc3addc4a8fb5ed7bf3c9ecf525a2c91f70ff6a Mon Sep 17 00:00:00 2001 From: MichealReed Date: Tue, 11 Feb 2025 13:28:05 -0600 Subject: [PATCH 02/13] More simplification --- CMakeLists.txt | 2 + cmake/example.cmake | 68 ++++++++++-------------------- cmake/find_gpu.cmake | 30 -------------- cmake/gpu.cmake | 99 ++++++++++++++++++++------------------------ 4 files changed, 70 insertions(+), 129 deletions(-) delete mode 100644 cmake/find_gpu.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index a464b34..ca735a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,3 +1,5 @@ +# This only builds a shared lib, see cmake/example.cmake +# and cmake/gpu.cmake for more details cmake_minimum_required(VERSION 3.28) project(gpu) diff --git a/cmake/example.cmake b/cmake/example.cmake index 41b15fd..d92c204 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -1,32 +1,20 @@ -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # export compile_commands.json to use with - # LSP -set(CMAKE_CXX_STANDARD 20) -set(CMAKE_CXX_STANDARD_REQUIRED ON) +# Getting Started with CMAKE +# Each example includes this and sets PROJECT_NAME +# cd examples/hello_world +# cmake -S . build/ -DCMAKE_BUILD_TYPE=Release +# cmake --build build/ --config Release +# ./build/hello_world + +if(NOT MSVC) + set(CMAKE_CXX_STANDARD 17) +else() + set(CMAKE_CXX_STANDARD 20) +endif() +# Path finding logic to find our root recipes from nested folders get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) -# Construct potential paths -set(FILEPATH_CURRENT_DIR "${DIRECTORY}/") -set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/") - -# Include file finding utility script -include("${FILEPATH_PROJECT_ROOT}/cmake/find_gpu.cmake") - -# Check if the file exists in the current directory -find_project_root(${CMAKE_CURRENT_SOURCE_DIR} ${FILENAME} - TARGET_FILE_PATH) -if("${TARGET_FILE_PATH}" STREQUAL "") - find_project_root(${FILEPATH_CURRENT_DIR} ${FILENAME} - TARGET_FILE_PATH) - if("${TARGET_FILE_PATH}" STREQUAL "") - message( - FATAL_ERROR - "File ${FILENAME} not found in either ${CMAKE_CURRENT_SOURCE_DIR} or ${CMAKE_CURRENT_SOURCE_DIR}/../../" - ) - endif() -endif() - # Ensure the build type is set if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE @@ -34,34 +22,24 @@ if(NOT CMAKE_BUILD_TYPE) CACHE STRING "Choose the type of build: Debug or Release" FORCE) endif() -# Define architecture and build type directories or file names -if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(ARCH "x64") -else() - set(ARCH "x86") -endif() - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(BUILD_TYPE "Debug") -else() - set(BUILD_TYPE "Release") -endif() +# Include the gpu.cpp + Dawn library +include("${PROJECT_ROOT}/cmake/gpu.cmake") -if(NOT TARGET gpu) - message(STATUS "GPU_LIB not found") - include("${TARGET_FILE_PATH}/cmake/gpu.cmake") -endif() +# Create the executable add_executable(${PROJECT_NAME} run.cpp) + +# Link gpu + dawn library target_link_libraries(${PROJECT_NAME} PRIVATE gpu) -target_link_libraries(${PROJECT_NAME} PRIVATE ${WEBGPU_DAWN}) +# Certain platforms need to copy the library files to the build directory if(MSVC) -# Copy webgpu_dawn.dll to the build directory + # Copy webgpu_dawn.dll to the build directory + # CMake multigenerators like MSVC need --config Release on + # the cmake --build command or they will output to /Debug add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${DAWN_INSTALL_PREFIX}/${CMAKE_BUILD_TYPE}/webgpu_dawn.dll - $ - ) + $) endif() diff --git a/cmake/find_gpu.cmake b/cmake/find_gpu.cmake deleted file mode 100644 index b6b7dad..0000000 --- a/cmake/find_gpu.cmake +++ /dev/null @@ -1,30 +0,0 @@ -# file name to find -set(FILENAME "gpu.hpp") - -# Function to check for file existence up the directory hierarchy -function(find_project_root current_dir filename result_var) - set(found FALSE) # Flag to indicate if the file is found - set(current_check_dir "${current_dir}") # Start from the given directory - # using 1 is jsut to supress the cmane-format warning - foreach(i RANGE 0 2 1) - set(filepath "${current_check_dir}/${filename}") - - if(EXISTS "${filepath}") - set(${result_var} - "${current_check_dir}" - PARENT_SCOPE) - set(found TRUE) - break() - endif() - - # Move one level up - get_filename_component(current_check_dir "${current_check_dir}" - DIRECTORY) - endforeach() - - if(NOT found) - set(${result_var} - "" - PARENT_SCOPE) # Set to empty if not found - endif() -endfunction() diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index 15f3b43..c8f011a 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -1,44 +1,46 @@ set(FILENAME "gpu.hpp") +# Setup project root here. if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") - set(FILEPATH_PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") + set(PROJECT_ROOT "${CMAKE_CURRENT_SOURCE_DIR}") else() get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) - - set(FILEPATH_PROJECT_ROOT "${PROJECT_ROOT}/") + + set(PROJECT_ROOT "${PROJECT_ROOT}/") endif() +message(STATUS "PROJECT_ROOT: ${PROJECT_ROOT}") + include(FetchContent) -set(FETCHCONTENT_BASE_DIR "${FILEPATH_PROJECT_ROOT}/third_party/fetchcontent/_deps") +set(FETCHCONTENT_BASE_DIR "${PROJECT_ROOT}/third_party/fetchcontent/_deps") set(DAWN_INSTALL_PREFIX "${FETCHCONTENT_BASE_DIR}/dawn-build/out/${CMAKE_BUILD_TYPE}" CACHE INTERNAL "Dawn install location" FORCE) # Before fetching, set configuration options for Dawn. -# These CMake variables are “global” (cached INTERNAL) so that Dawn’s own CMakeLists.txt -# will pick them up. Adjust them as needed. -set(DAWN_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE INTERNAL "Dawn build type" FORCE) set(DCMAKE_INSTALL_PREFIX ${DAWN_INSTALL_PREFIX} CACHE INTERNAL "Dawn install location" FORCE) +set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE INTERNAL "Dawn configuration types" FORCE) -# Dawn options -set(DAWN_FETCH_DEPENDENCIES ON CACHE INTERNAL "Fetch Dawn dependencies" FORCE) -set(DAWN_ENABLE_INSTALL ON CACHE INTERNAL "Enable Dawn installation" FORCE) -set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF CACHE INTERNAL "Build Dawn monolithically" FORCE) +# Dawn options for more, +# see https://dawn.googlesource.com/dawn/+/refs/heads/main/CMakeLists.txt +set(DAWN_ALWAYS_ASSERT OFF CACHE INTERNAL "Always assert in Dawn" FORCE) +set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE INTERNAL "Build Dawn monolithically" FORCE) set(DAWN_BUILD_EXAMPLES OFF CACHE INTERNAL "Build Dawn examples" FORCE) set(DAWN_BUILD_SAMPLES OFF CACHE INTERNAL "Build Dawn samples" FORCE) set(DAWN_BUILD_TESTS OFF CACHE INTERNAL "Build Dawn tests" FORCE) -set(DAWN_BUILD_UTILS OFF CACHE INTERNAL "Build Dawn utilities" FORCE) +set(DAWN_ENABLE_INSTALL ON CACHE INTERNAL "Enable Dawn installation" FORCE) +set(DAWN_FETCH_DEPENDENCIES ON CACHE INTERNAL "Fetch Dawn dependencies" FORCE) + set(TINT_BUILD_TESTS OFF CACHE INTERNAL "Build Tint Tests" FORCE) set(TINT_BUILD_IR_BINARY OFF CACHE INTERNAL "Build Tint IR binary" FORCE) set(TINT_BUILD_CMD_TOOLS OFF CACHE INTERNAL "Build Tint command line tools" FORCE) -set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries" FORCE) - -# Set up an install location for Dawn – you can change this to a specific location. +set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries" FORCE) +# Fetch Setup FetchContent_Declare( dawn DOWNLOAD_COMMAND @@ -49,67 +51,56 @@ FetchContent_Declare( ) -# This call will download the repository and add it as a subdirectory. +# Download the repository and add it as a subdirectory. FetchContent_MakeAvailable(dawn) -# At this point, assuming Dawn’s CMakeLists.txt is written so that an install step is available, -# we trigger a build of its install target. This custom target will build (and install) Dawn -# into ${DAWN_INSTALL_PREFIX}. (If Dawn already adds an install target, you may simply depend on it.) -add_custom_target(build_dawn_config ALL +# Since we require Dawn to be built before linking against it, we need to configure it now. +execute_process( COMMAND ${CMAKE_COMMAND} ${FETCHCONTENT_BASE_DIR}/dawn-src -B ${DAWN_INSTALL_PREFIX} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -DDAWN_FETCH_DEPENDENCIES=ON - -DDAWN_ENABLE_INSTALL=ON - -DDAWN_BUILD_MONOLITHIC_LIBRARY=OFF - -DDAWN_BUILD_EXAMPLES=OFF - -DDAWN_BUILD_SAMPLES=OFF - -DDAWN_BUILD_TESTS=OFF - -DDAWN_BUILD_UTILS=OFF - -DTINT_BUILD_TESTS=OFF - -DTINT_BUILD_IR_BINARY=OFF - -DTINT_BUILD_CMD_TOOLS=OFF - -DBUILD_SHARED_LIBS=OFF -G "${CMAKE_GENERATOR}" - COMMENT "Configuring Dawn build with custom options in ${DAWN_INSTALL_PREFIX}" ) -add_custom_target(build_dawn_install ALL - COMMAND ${CMAKE_COMMAND} --build ${DAWN_INSTALL_PREFIX} --target install - COMMENT "Installing Dawn into ${DAWN_INSTALL_PREFIX}" +# Build Dawn +execute_process( + WORKING_DIRECTORY ${FETCHCONTENT_BASE_DIR}/dawn-src + COMMAND ${CMAKE_COMMAND} --build ${DAWN_INSTALL_PREFIX} --config ${CMAKE_BUILD_TYPE} ) -include(${FETCHCONTENT_BASE_DIR}/dawn-build/cmake/DawnTargets.cmake) - +# Add sources set(GPU_SOURCES - "${FILEPATH_PROJECT_ROOT}/gpu.cpp" - "${FILEPATH_PROJECT_ROOT}/numeric_types/half.cpp" + "${PROJECT_ROOT}/gpu.cpp" + "${PROJECT_ROOT}/numeric_types/half.cpp" ) +# Add headers set(GPU_HEADERS - "${FILEPATH_PROJECT_ROOT}/gpu.hpp" - "${FILEPATH_PROJECT_ROOT}/utils/logging.hpp" - "${FILEPATH_PROJECT_ROOT}/utils/array_utils.hpp" - "${FILEPATH_PROJECT_ROOT}/numeric_types/half.hpp" + "${PROJECT_ROOT}/gpu.hpp" + "${PROJECT_ROOT}/utils/logging.hpp" + "${PROJECT_ROOT}/utils/array_utils.hpp" + "${PROJECT_ROOT}/numeric_types/half.hpp" ) +# Emscripten includes a header automatically if(EMSCRIPTEN) - file(REMOVE "${FILEPATH_PROJECT_ROOT}/webgpu/webgpu.h") + file(REMOVE "${PROJECT_ROOT}/webgpu/webgpu.h") else() - list(APPEND GPU_HEADERS "${DAWN_INSTALL_PREFIX}/gen/webgpu-headers/webgpu.h") + list(APPEND GPU_HEADERS "${PROJECT_ROOT}/third_party/headers/webgpu/webgpu.h") endif() -# Create the INTERFACE library ‘gpu’ +# Create the STATIC library for gpu add_library(gpu STATIC ${GPU_SOURCES} ${GPU_HEADERS}) -target_include_directories(gpu PUBLIC "${FILEPATH_PROJECT_ROOT}") -target_include_directories(gpu PUBLIC "${FILEPATH_PROJECT_ROOT}/third_party/headers") +target_include_directories(gpu PUBLIC "${PROJECT_ROOT}") +target_include_directories(gpu PUBLIC "${PROJECT_ROOT}/third_party/headers") -# Ensure that the gpu target is built only after Dawn has been installed. -add_dependencies(gpu build_dawn_install) - -find_library(WEBGPU_DAWN +# Find the monolithic library for Dawn +find_library(WEBGPU_DAWN_MONOLITHIC NAMES webgpu_dawn - HINTS "${DAWN_INSTALL_PREFIX}/src/dawn/native/Debug/" -) \ No newline at end of file + HINTS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" +) + +# Link the monolithic library +target_link_libraries(gpu PRIVATE ${WEBGPU_DAWN_MONOLITHIC}) From 2360ba9af7432c33a2703eb2a88706d4150387dc Mon Sep 17 00:00:00 2001 From: MichealReed Date: Tue, 11 Feb 2025 13:44:09 -0600 Subject: [PATCH 03/13] cleanup --- CMakeLists.txt | 2 +- cmake/gpu.cmake | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ca735a9..e8e569a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,4 +24,4 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpu.cmake") add_library(gpud SHARED gpu.hpp) set_target_properties(gpud PROPERTIES LINKER_LANGUAGE CXX) -target_link_libraries(gpud PRIVATE gpu) \ No newline at end of file +target_link_libraries(gpud PRIVATE gpu) diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index c8f011a..11d6c67 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -41,6 +41,8 @@ set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries" FORCE) # Fetch Setup +# Add a commit hash to pin the version of Dawn. +# git fetch --depth=1 url FetchContent_Declare( dawn DOWNLOAD_COMMAND From 30f7594896ecd9c4b7616bd9ad0d03598f0b4939 Mon Sep 17 00:00:00 2001 From: MichealReed Date: Tue, 11 Feb 2025 15:59:24 -0600 Subject: [PATCH 04/13] build path for msvc find library --- cmake/gpu.cmake | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index 11d6c67..1767a50 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -6,7 +6,6 @@ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}") else() get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) - set(PROJECT_ROOT "${PROJECT_ROOT}/") endif() @@ -21,7 +20,6 @@ set(DAWN_INSTALL_PREFIX "${FETCHCONTENT_BASE_DIR}/dawn-build/out/${CMAKE_BUILD_T # Before fetching, set configuration options for Dawn. set(DCMAKE_INSTALL_PREFIX ${DAWN_INSTALL_PREFIX} CACHE INTERNAL "Dawn install location" FORCE) -set(CMAKE_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE} CACHE INTERNAL "Dawn configuration types" FORCE) # Dawn options for more, # see https://dawn.googlesource.com/dawn/+/refs/heads/main/CMakeLists.txt @@ -98,11 +96,18 @@ add_library(gpu STATIC ${GPU_SOURCES} ${GPU_HEADERS}) target_include_directories(gpu PUBLIC "${PROJECT_ROOT}") target_include_directories(gpu PUBLIC "${PROJECT_ROOT}/third_party/headers") -# Find the monolithic library for Dawn -find_library(WEBGPU_DAWN_MONOLITHIC +# find_library, windows adds extra folder +if(MSVC) + find_library(WEBGPU_DAWN_MONOLITHIC NAMES webgpu_dawn - HINTS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" -) + PATHS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" + ) +else() + find_library(WEBGPU_DAWN_MONOLITHIC + NAMES webgpu_dawn + PATHS "${DAWN_INSTALL_PREFIX}/src/dawn/native" + ) +endif() # Link the monolithic library target_link_libraries(gpu PRIVATE ${WEBGPU_DAWN_MONOLITHIC}) From 82ff79d1b2853e29f9e5de81c93bef9670535b4d Mon Sep 17 00:00:00 2001 From: MichealReed Date: Tue, 11 Feb 2025 16:13:29 -0600 Subject: [PATCH 05/13] require the libs so we fail early --- cmake/gpu.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index 1767a50..b687e83 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -101,11 +101,13 @@ if(MSVC) find_library(WEBGPU_DAWN_MONOLITHIC NAMES webgpu_dawn PATHS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" + REQUIRED ) else() find_library(WEBGPU_DAWN_MONOLITHIC NAMES webgpu_dawn PATHS "${DAWN_INSTALL_PREFIX}/src/dawn/native" + REQUIRED ) endif() From ebd5bcf1b7f3dc7d9f888039adba36cbf6e39b4f Mon Sep 17 00:00:00 2001 From: MichealReed Date: Tue, 11 Feb 2025 17:22:24 -0600 Subject: [PATCH 06/13] use hints for MSVC --- cmake/gpu.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index b687e83..52a348b 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -100,7 +100,7 @@ target_include_directories(gpu PUBLIC "${PROJECT_ROOT}/third_party/headers") if(MSVC) find_library(WEBGPU_DAWN_MONOLITHIC NAMES webgpu_dawn - PATHS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" + HINTS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" REQUIRED ) else() From d1c0b81a529f49c9bddb2e27021ce3624824c32e Mon Sep 17 00:00:00 2001 From: MichealReed Date: Sun, 16 Feb 2025 18:24:49 -0600 Subject: [PATCH 07/13] adds emscripten support --- .gitignore | 2 + CMakeLists.txt | 1 + cmake/dawn.cmake | 149 ++++++++++++++++++++++++++++++ cmake/example.cmake | 94 ++++++++++++++----- cmake/gpu.cmake | 89 ++---------------- cmake/templates/index.html.in | 22 +++++ examples/shadertui/CMakeLists.txt | 1 + gpu.hpp | 6 +- numeric_types/half.cpp | 2 +- 9 files changed, 260 insertions(+), 106 deletions(-) create mode 100644 cmake/dawn.cmake create mode 100644 cmake/templates/index.html.in diff --git a/.gitignore b/.gitignore index c7f60c3..4dc9cf7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ build/* # any build subdirectory in the tree **/build/ +**/build_web/ examples/hello_gpu/build/* examples/raymarch/build/* docs/html @@ -8,6 +9,7 @@ source .DS_Store third_party/lib/* third_party/local/* +third_party/dawn/* # formatter files .cmake-format.py diff --git a/CMakeLists.txt b/CMakeLists.txt index e8e569a..816cdf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ if(DEBUG) set(CMAKE_CXX_FLAGS "-O0 -g") endif() +include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/dawn.cmake") include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/gpu.cmake") add_library(gpud SHARED gpu.hpp) diff --git a/cmake/dawn.cmake b/cmake/dawn.cmake new file mode 100644 index 0000000..f7ab748 --- /dev/null +++ b/cmake/dawn.cmake @@ -0,0 +1,149 @@ +# Setup directories +set(FETCHCONTENT_BASE_DIR "${PROJECT_ROOT}/third_party") +set(DAWN_DIR "${FETCHCONTENT_BASE_DIR}/dawn" CACHE INTERNAL "") +set(DAWN_BUILD_DIR "${DAWN_DIR}/build" CACHE INTERNAL "") + +if(EMSCRIPTEN) + set(EM_SDK_DIR $ENV{EMSDK} CACHE INTERNAL "") + set(DAWN_BUILD_DIR "${DAWN_DIR}/build_web" CACHE INTERNAL "") +endif() + +function(find_dawn_library) + if(MSVC) + find_library(WEBGPU_DAWN_DEBUG webgpu_dawn + NAMES webgpu_dawn + HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug" + ) + find_library(WEBGPU_DAWN_RELEASE webgpu_dawn + NAMES webgpu_dawn + HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release" + ) + elseif(NOT EMSCRIPTEN AND NOT MSVC) + find_library(WEBGPU_DAWN_LIB + NAMES webgpu_dawn + PATHS "${DAWN_BUILD_DIR}/src/dawn/native" + REQUIRED + ) + endif() + + # Set result variables in parent scope + set(DAWN_BUILD_FOUND ON PARENT_SCOPE) + if(MSVC) + set(WEBGPU_DAWN_DEBUG ${WEBGPU_DAWN_DEBUG} PARENT_SCOPE) + set(WEBGPU_DAWN_RELEASE ${WEBGPU_DAWN_RELEASE} PARENT_SCOPE) + else() + set(WEBGPU_DAWN_LIB ${WEBGPU_DAWN_LIB} PARENT_SCOPE) + endif() +endfunction() + +# Enable find for no dawn rebuilds with flutter run +set(ENABLE_DAWN_FIND OFF CACHE BOOL "Enable finding Dawn" FORCE) +set(DAWN_BUILD_FOUND OFF CACHE BOOL "Dawn build found" FORCE) +if(ENABLE_DAWN_FIND) + # find_library, windows adds extra folder + if(MSVC) + find_library(WEBGPU_DAWN_DEBUG webgpu_dawn + NAMES webgpu_dawn + HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug" + ) + find_library(WEBGPU_DAWN_RELEASE webgpu_dawn + NAMES webgpu_dawn + HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release" + ) + set(DAWN_BUILD_FOUND ON) + elseif(NOT EMSCRIPTEN AND NOT MSVC) + find_library(WEBGPU_DAWN_LIB + NAMES webgpu_dawn + PATHS "${DAWN_BUILD_DIR}/src/dawn/native" + REQUIRED + ) + set(DAWN_BUILD_FOUND ON) + else() + set(DAWN_BUILD_FOUND ON) + endif() +endif() + +# Dawn options for more, +# see https://dawn.googlesource.com/dawn/+/refs/heads/main/CMakeLists.txt +set(DAWN_ALWAYS_ASSERT OFF CACHE INTERNAL "Always assert in Dawn" FORCE) +set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE INTERNAL "Build Dawn monolithically" FORCE) +set(DAWN_BUILD_EXAMPLES OFF CACHE INTERNAL "Build Dawn examples" FORCE) +set(DAWN_BUILD_SAMPLES OFF CACHE INTERNAL "Build Dawn samples" FORCE) +set(DAWN_BUILD_TESTS OFF CACHE INTERNAL "Build Dawn tests" FORCE) +set(DAWN_ENABLE_INSTALL OFF CACHE INTERNAL "Enable Dawn installation" FORCE) +set(DAWN_FETCH_DEPENDENCIES ON CACHE INTERNAL "Fetch Dawn dependencies" FORCE) +set(TINT_BUILD_TESTS OFF CACHE INTERNAL "Build Tint Tests" FORCE) +set(TINT_BUILD_IR_BINARY OFF CACHE INTERNAL "Build Tint IR binary" FORCE) +set(TINT_BUILD_CMD_TOOLS OFF CACHE INTERNAL "Build Tint command line tools" FORCE) + +if(NOT DAWN_BUILD_FOUND) + include(FetchContent) + message("webgpu_dawn not found start building") + if(EMSCRIPTEN) + set(EMSCRIPTEN_DIR "${EM_SDK_DIR}/upstream/emscripten" CACHE INTERNAL "" FORCE) + set(DAWN_EMSCRIPTEN_TOOLCHAIN ${EMSCRIPTEN_DIR} CACHE INTERNAL "" FORCE) + endif() + + FetchContent_Declare( + dawn + DOWNLOAD_DIR ${DAWN_DIR} + SOURCE_DIR ${DAWN_DIR} + SUBBUILD_DIR ${DAWN_BUILD_DIR}/tmp + BINARY_DIR ${DAWN_BUILD_DIR} + DOWNLOAD_COMMAND + cd ${DAWN_DIR} && + git init && + git fetch --depth=1 https://dawn.googlesource.com/dawn && + git reset --hard FETCH_HEAD + ) + + # Download the repository and add it as a subdirectory. + FetchContent_MakeAvailable(dawn) + + # attempt fix flutter rebuilds + set(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH};${DAWN_DIR}/src" CACHE INTERNAL "") + + execute_process( + WORKING_DIRECTORY ${DAWN_DIR} + COMMAND ${CMAKE_COMMAND} -S ${DAWN_DIR} + -B ${DAWN_BUILD_DIR} + ) + + # Build Dawn + execute_process( + COMMAND ${CMAKE_COMMAND} --build ${DAWN_BUILD_DIR} + ) + + # find_library, windows adds extra folder + if(MSVC) + find_library(WEBGPU_DAWN_DEBUG webgpu_dawn + NAMES webgpu_dawn + HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug" + ) + find_library(WEBGPU_DAWN_RELEASE webgpu_dawn + NAMES webgpu_dawn + HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release" + ) + set(DAWN_BUILD_FOUND ON) + elseif(NOT EMSCRIPTEN AND NOT MSVC) + find_library(WEBGPU_DAWN_LIB + NAMES webgpu_dawn + PATHS "${DAWN_BUILD_DIR}/src/dawn/native" + REQUIRED + ) + set(DAWN_BUILD_FOUND ON) + else() + set(DAWN_BUILD_FOUND ON) + endif() +endif() + +if(EMSCRIPTEN) + add_library(webgpu_dawn INTERFACE IMPORTED) + target_include_directories(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include) + target_include_directories(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include/webgpu/webgpu.h) + target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js) + target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js) + target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_sig_info.js) + target_link_libraries(webgpu_dawn INTERFACE ${DAWN_DIR}/third_party/emdawnwebgpu/library_webgpu.js) +else() +endif() \ No newline at end of file diff --git a/cmake/example.cmake b/cmake/example.cmake index d92c204..99578fd 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -1,9 +1,14 @@ # Getting Started with CMAKE -# Each example includes this and sets PROJECT_NAME -# cd examples/hello_world -# cmake -S . build/ -DCMAKE_BUILD_TYPE=Release -# cmake --build build/ --config Release -# ./build/hello_world +# Each example includes this and sets PROJECT_NAME. +# +# Example usage: +# cd examples/hello_world +# cmake -S . build/ -DCMAKE_BUILD_TYPE=Release +# cmake --build build/ --config Release +# ./build/hello_world (or serve the output .js/.wasm for Emscripten) +# or for emscripten +# emcmake cmake -S . -B ./build_web -DCMAKE_BUILD_TYPE=Release +# cmake --build build_web --config Release if(NOT MSVC) set(CMAKE_CXX_STANDARD 17) @@ -11,35 +16,82 @@ else() set(CMAKE_CXX_STANDARD 20) endif() -# Path finding logic to find our root recipes from nested folders +# Locate the project root (two levels up from the current source dir) get_filename_component(PROJECT_ROOT ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(PROJECT_ROOT ${PROJECT_ROOT} DIRECTORY) -# Ensure the build type is set -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE - Release - CACHE STRING "Choose the type of build: Debug or Release" FORCE) -endif() - -# Include the gpu.cpp + Dawn library +# Include external libraries and helper scripts (dawn and gpu) +include("${PROJECT_ROOT}/cmake/dawn.cmake") include("${PROJECT_ROOT}/cmake/gpu.cmake") # Create the executable add_executable(${PROJECT_NAME} run.cpp) -# Link gpu + dawn library +# Platform-specific linking & build settings +if(EMSCRIPTEN) + # Emscripten-specific configuration + + # Define a web output directory (adjust as needed) + set(WEB_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/web_build") + + # If necessary, include the generated WebGPU include dirs first. + include_directories(BEFORE "${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include/") + + # Create a helper library for WebGPU support. + add_library(webgpu_web "${DAWN_DIR}/third_party/emdawnwebgpu/webgpu.cpp") + target_link_libraries(${PROJECT_NAME} PRIVATE webgpu_web) + + # Set Emscripten-specific link flags that enable WASM output and expose certain symbols. + # Needed to use updated version, emdawnwebgpu + set_target_properties(${PROJECT_NAME} PROPERTIES LINK_FLAGS "\ + -sUSE_WEBGPU=0 \ + -sWASM=1 \ + -DDAWN_EMSCRIPTEN_TOOLCHAIN=${EMSCRIPTEN_DIR} \ + -sEXPORTED_FUNCTIONS=_main,_malloc,_free,_memcpy \ + -sEXPORTED_RUNTIME_METHODS=ccall \ + -sUSE_GLFW=3 \ + -sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=10000000 \ + -sASYNCIFY \ + --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js \ + --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js \ + --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_sig_info.js \ + --js-library=${DAWN_DIR}/third_party/emdawnwebgpu/library_webgpu.js \ + --closure-args=--externs=${EMSCRIPTEN_DIR}/src/closure-externs/webgpu-externs.js \ + -O3 \ + ") + +else() + # Non-Emscripten (desktop) linking + if(MSVC) + target_link_libraries(gpu + PRIVATE + $<$:${WEBGPU_DAWN_DEBUG}> + $<$:${WEBGPU_DAWN_RELEASE}> + ) + else() + target_link_libraries(gpu PRIVATE webgpu_dawn) + endif() +endif() + +# Link the gpu/dawn library to the executable. target_link_libraries(${PROJECT_NAME} PRIVATE gpu) -# Certain platforms need to copy the library files to the build directory +# Platform-specific post-build actions (e.g. copying DLLs for MSVC) if(MSVC) - # Copy webgpu_dawn.dll to the build directory - # CMake multigenerators like MSVC need --config Release on - # the cmake --build command or they will output to /Debug add_custom_command( TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy - ${DAWN_INSTALL_PREFIX}/${CMAKE_BUILD_TYPE}/webgpu_dawn.dll - $) + ${DAWN_BUILD_DIR}/$/webgpu_dawn.dll + $ + COMMENT "Copying webgpu_dawn.dll to the build directory" + ) endif() +if(EMSCRIPTEN) + + # Configure the HTML file by replacing @PROJECT_NAME@ with the actual target name. + configure_file(${PROJECT_ROOT}cmake/templates/index.html.in + ${CMAKE_CURRENT_BINARY_DIR}/index.html + @ONLY) + +endif() \ No newline at end of file diff --git a/cmake/gpu.cmake b/cmake/gpu.cmake index 52a348b..6cce9e6 100644 --- a/cmake/gpu.cmake +++ b/cmake/gpu.cmake @@ -11,68 +11,11 @@ endif() message(STATUS "PROJECT_ROOT: ${PROJECT_ROOT}") - -include(FetchContent) - -set(FETCHCONTENT_BASE_DIR "${PROJECT_ROOT}/third_party/fetchcontent/_deps") -set(DAWN_INSTALL_PREFIX "${FETCHCONTENT_BASE_DIR}/dawn-build/out/${CMAKE_BUILD_TYPE}" CACHE INTERNAL "Dawn install location" FORCE) - - -# Before fetching, set configuration options for Dawn. -set(DCMAKE_INSTALL_PREFIX ${DAWN_INSTALL_PREFIX} CACHE INTERNAL "Dawn install location" FORCE) - -# Dawn options for more, -# see https://dawn.googlesource.com/dawn/+/refs/heads/main/CMakeLists.txt -set(DAWN_ALWAYS_ASSERT OFF CACHE INTERNAL "Always assert in Dawn" FORCE) -set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE INTERNAL "Build Dawn monolithically" FORCE) -set(DAWN_BUILD_EXAMPLES OFF CACHE INTERNAL "Build Dawn examples" FORCE) -set(DAWN_BUILD_SAMPLES OFF CACHE INTERNAL "Build Dawn samples" FORCE) -set(DAWN_BUILD_TESTS OFF CACHE INTERNAL "Build Dawn tests" FORCE) -set(DAWN_ENABLE_INSTALL ON CACHE INTERNAL "Enable Dawn installation" FORCE) -set(DAWN_FETCH_DEPENDENCIES ON CACHE INTERNAL "Fetch Dawn dependencies" FORCE) - -set(TINT_BUILD_TESTS OFF CACHE INTERNAL "Build Tint Tests" FORCE) -set(TINT_BUILD_IR_BINARY OFF CACHE INTERNAL "Build Tint IR binary" FORCE) -set(TINT_BUILD_CMD_TOOLS OFF CACHE INTERNAL "Build Tint command line tools" FORCE) - -set(BUILD_SHARED_LIBS OFF CACHE INTERNAL "Build shared libraries" FORCE) - - -# Fetch Setup -# Add a commit hash to pin the version of Dawn. -# git fetch --depth=1 url -FetchContent_Declare( - dawn - DOWNLOAD_COMMAND - cd ${FETCHCONTENT_BASE_DIR}/dawn-src && - git init && - git fetch --depth=1 https://dawn.googlesource.com/dawn && - git reset --hard FETCH_HEAD -) - - -# Download the repository and add it as a subdirectory. -FetchContent_MakeAvailable(dawn) - - -# Since we require Dawn to be built before linking against it, we need to configure it now. -execute_process( - COMMAND ${CMAKE_COMMAND} ${FETCHCONTENT_BASE_DIR}/dawn-src - -B ${DAWN_INSTALL_PREFIX} - -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} - -G "${CMAKE_GENERATOR}" -) - -# Build Dawn -execute_process( - WORKING_DIRECTORY ${FETCHCONTENT_BASE_DIR}/dawn-src - COMMAND ${CMAKE_COMMAND} --build ${DAWN_INSTALL_PREFIX} --config ${CMAKE_BUILD_TYPE} -) - # Add sources set(GPU_SOURCES "${PROJECT_ROOT}/gpu.cpp" "${PROJECT_ROOT}/numeric_types/half.cpp" + "${DAWN_BUILD_DIR}/gen/include/dawn/webgpu.h" ) # Add headers @@ -81,35 +24,17 @@ set(GPU_HEADERS "${PROJECT_ROOT}/utils/logging.hpp" "${PROJECT_ROOT}/utils/array_utils.hpp" "${PROJECT_ROOT}/numeric_types/half.hpp" + ) -# Emscripten includes a header automatically -if(EMSCRIPTEN) - file(REMOVE "${PROJECT_ROOT}/webgpu/webgpu.h") -else() - list(APPEND GPU_HEADERS "${PROJECT_ROOT}/third_party/headers/webgpu/webgpu.h") -endif() - - # Create the STATIC library for gpu add_library(gpu STATIC ${GPU_SOURCES} ${GPU_HEADERS}) +set_target_properties(gpu PROPERTIES LINKER_LANGUAGE CXX) target_include_directories(gpu PUBLIC "${PROJECT_ROOT}") -target_include_directories(gpu PUBLIC "${PROJECT_ROOT}/third_party/headers") - -# find_library, windows adds extra folder -if(MSVC) - find_library(WEBGPU_DAWN_MONOLITHIC - NAMES webgpu_dawn - HINTS "${DAWN_INSTALL_PREFIX}/src/dawn/native/${CMAKE_BUILD_TYPE}" - REQUIRED - ) +if(NOT EMSCRIPTEN) + target_include_directories(gpu PUBLIC "${DAWN_BUILD_DIR}/gen/include/dawn/") else() - find_library(WEBGPU_DAWN_MONOLITHIC - NAMES webgpu_dawn - PATHS "${DAWN_INSTALL_PREFIX}/src/dawn/native" - REQUIRED - ) + target_include_directories(gpu PUBLIC "${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include/") + target_include_directories(gpu PUBLIC "${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/include/webgpu/") endif() -# Link the monolithic library -target_link_libraries(gpu PRIVATE ${WEBGPU_DAWN_MONOLITHIC}) diff --git a/cmake/templates/index.html.in b/cmake/templates/index.html.in new file mode 100644 index 0000000..1bd64ca --- /dev/null +++ b/cmake/templates/index.html.in @@ -0,0 +1,22 @@ + + + + + @PROJECT_NAME@ + + + + + + + \ No newline at end of file diff --git a/examples/shadertui/CMakeLists.txt b/examples/shadertui/CMakeLists.txt index 0938023..b728fc8 100644 --- a/examples/shadertui/CMakeLists.txt +++ b/examples/shadertui/CMakeLists.txt @@ -1,3 +1,4 @@ +# Not working yet needs update with libs for emscripten cmake_minimum_required(VERSION 3.28) project(shadertui) diff --git a/gpu.hpp b/gpu.hpp index 5327fe7..edc8b38 100644 --- a/gpu.hpp +++ b/gpu.hpp @@ -15,7 +15,7 @@ #include // std::pair #include -#include "webgpu/webgpu.h" +#include "webgpu.h" #include "numeric_types/half.hpp" #include "utils/logging.hpp" @@ -910,6 +910,7 @@ inline Context createContext( // If the device was created, set up logging and fetch the queue if (devData.status == WGPURequestDeviceStatus_Success) { + #ifndef __EMSCRIPTEN__ WGPULoggingCallbackInfo loggingCallbackInfo { .nextInChain = nullptr, .callback = @@ -925,6 +926,7 @@ inline Context createContext( .userdata2 = nullptr }; wgpuDeviceSetLoggingCallback(ctx.device, loggingCallbackInfo); + #endif ctx.queue = wgpuDeviceGetQueue(ctx.device); } } @@ -1206,7 +1208,7 @@ inline void toCPU(Context &ctx, WGPUBuffer buffer, void *data, size_t size) { } wgpuQueueSubmit(ctx.queue, 1, &op.commandBuffer); wgpuCommandBufferRelease(op.commandBuffer); - CallbackData callbackData = {op.readbackBuffer, bufferSize, data, &op.promise, + CallbackData callbackData = {op.readbackBuffer, static_cast(bufferSize), data, &op.promise, &op.future}; WGPUQueueWorkDoneCallbackInfo workDoneCallbackInfo = { diff --git a/numeric_types/half.cpp b/numeric_types/half.cpp index e5bdaf0..fe5aab7 100644 --- a/numeric_types/half.cpp +++ b/numeric_types/half.cpp @@ -241,7 +241,7 @@ fn main( } } -int main() { +int testMain() { printf("\nHalf-precision float tests\n==========================\n"); printf("\nRegular values float round trips\n\n"); From 9247b79f3f31b87a19bc7dc0ae524608e8eea593 Mon Sep 17 00:00:00 2001 From: MichealReed Date: Sun, 16 Feb 2025 18:26:57 -0600 Subject: [PATCH 08/13] remove redundant find function --- cmake/dawn.cmake | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/cmake/dawn.cmake b/cmake/dawn.cmake index f7ab748..b9394d4 100644 --- a/cmake/dawn.cmake +++ b/cmake/dawn.cmake @@ -8,34 +8,6 @@ if(EMSCRIPTEN) set(DAWN_BUILD_DIR "${DAWN_DIR}/build_web" CACHE INTERNAL "") endif() -function(find_dawn_library) - if(MSVC) - find_library(WEBGPU_DAWN_DEBUG webgpu_dawn - NAMES webgpu_dawn - HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Debug" - ) - find_library(WEBGPU_DAWN_RELEASE webgpu_dawn - NAMES webgpu_dawn - HINTS "${DAWN_BUILD_DIR}/src/dawn/native/Release" - ) - elseif(NOT EMSCRIPTEN AND NOT MSVC) - find_library(WEBGPU_DAWN_LIB - NAMES webgpu_dawn - PATHS "${DAWN_BUILD_DIR}/src/dawn/native" - REQUIRED - ) - endif() - - # Set result variables in parent scope - set(DAWN_BUILD_FOUND ON PARENT_SCOPE) - if(MSVC) - set(WEBGPU_DAWN_DEBUG ${WEBGPU_DAWN_DEBUG} PARENT_SCOPE) - set(WEBGPU_DAWN_RELEASE ${WEBGPU_DAWN_RELEASE} PARENT_SCOPE) - else() - set(WEBGPU_DAWN_LIB ${WEBGPU_DAWN_LIB} PARENT_SCOPE) - endif() -endfunction() - # Enable find for no dawn rebuilds with flutter run set(ENABLE_DAWN_FIND OFF CACHE BOOL "Enable finding Dawn" FORCE) set(DAWN_BUILD_FOUND OFF CACHE BOOL "Dawn build found" FORCE) From 3e59576f2b752a4f6255445d0569583d87f38d44 Mon Sep 17 00:00:00 2001 From: MichealReed Date: Sun, 16 Feb 2025 18:42:27 -0600 Subject: [PATCH 09/13] clean linker flags --- cmake/example.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/example.cmake b/cmake/example.cmake index 99578fd..192358f 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -9,6 +9,7 @@ # or for emscripten # emcmake cmake -S . -B ./build_web -DCMAKE_BUILD_TYPE=Release # cmake --build build_web --config Release +# python3 -m http.server 8080 --d build_web if(NOT MSVC) set(CMAKE_CXX_STANDARD 17) @@ -50,14 +51,13 @@ if(EMSCRIPTEN) -sEXPORTED_FUNCTIONS=_main,_malloc,_free,_memcpy \ -sEXPORTED_RUNTIME_METHODS=ccall \ -sUSE_GLFW=3 \ - -sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=10000000 \ + -sALLOW_MEMORY_GROWTH=1 \ -sASYNCIFY \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_sig_info.js \ --js-library=${DAWN_DIR}/third_party/emdawnwebgpu/library_webgpu.js \ --closure-args=--externs=${EMSCRIPTEN_DIR}/src/closure-externs/webgpu-externs.js \ - -O3 \ ") else() From 0653a4b524e7bbb6e91d2fe02c827ee7782d5b65 Mon Sep 17 00:00:00 2001 From: MichealReed Date: Sun, 16 Feb 2025 18:47:51 -0600 Subject: [PATCH 10/13] needs large stack size --- cmake/example.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/example.cmake b/cmake/example.cmake index 192358f..8216077 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -51,7 +51,7 @@ if(EMSCRIPTEN) -sEXPORTED_FUNCTIONS=_main,_malloc,_free,_memcpy \ -sEXPORTED_RUNTIME_METHODS=ccall \ -sUSE_GLFW=3 \ - -sALLOW_MEMORY_GROWTH=1 \ + -sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=10000000 \ -sASYNCIFY \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js \ From 9f4059b7d1ae5a0eba4fa26772a42a73064a66bf Mon Sep 17 00:00:00 2001 From: MichealReed Date: Sun, 16 Feb 2025 18:50:13 -0600 Subject: [PATCH 11/13] use stack in MB instead --- cmake/example.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/example.cmake b/cmake/example.cmake index 8216077..6f195ec 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -51,7 +51,7 @@ if(EMSCRIPTEN) -sEXPORTED_FUNCTIONS=_main,_malloc,_free,_memcpy \ -sEXPORTED_RUNTIME_METHODS=ccall \ -sUSE_GLFW=3 \ - -sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=10000000 \ + -sALLOW_MEMORY_GROWTH=1 -sSTACK_SIZE=5MB \ -sASYNCIFY \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_enum_tables.js \ --js-library=${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_struct_info.js \ From 78ae4685a15faf8f962d8f63a66f26fa86ed24ca Mon Sep 17 00:00:00 2001 From: MichealReed Date: Mon, 17 Feb 2025 17:30:11 -0600 Subject: [PATCH 12/13] must set DAWN_EMSCRIPTEN_TOOLCHAIN for build too --- cmake/dawn.cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake/dawn.cmake b/cmake/dawn.cmake index b9394d4..46d7403 100644 --- a/cmake/dawn.cmake +++ b/cmake/dawn.cmake @@ -6,6 +6,7 @@ set(DAWN_BUILD_DIR "${DAWN_DIR}/build" CACHE INTERNAL "") if(EMSCRIPTEN) set(EM_SDK_DIR $ENV{EMSDK} CACHE INTERNAL "") set(DAWN_BUILD_DIR "${DAWN_DIR}/build_web" CACHE INTERNAL "") + set(DAWN_EMSCRIPTEN_TOOLCHAIN ${EM_SDK_DIR}/upstream/emscripten CACHE INTERNAL "" FORCE) endif() # Enable find for no dawn rebuilds with flutter run From 6197322e8e48e1c761043d6ca6badc89724b95e3 Mon Sep 17 00:00:00 2001 From: MichealReed Date: Mon, 17 Feb 2025 22:59:26 -0600 Subject: [PATCH 13/13] EOF fixes --- cmake/dawn.cmake | 2 +- cmake/example.cmake | 2 +- cmake/templates/index.html.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake/dawn.cmake b/cmake/dawn.cmake index 46d7403..2ead9ae 100644 --- a/cmake/dawn.cmake +++ b/cmake/dawn.cmake @@ -119,4 +119,4 @@ if(EMSCRIPTEN) target_link_libraries(webgpu_dawn INTERFACE ${DAWN_BUILD_DIR}/gen/src/emdawnwebgpu/library_webgpu_generated_sig_info.js) target_link_libraries(webgpu_dawn INTERFACE ${DAWN_DIR}/third_party/emdawnwebgpu/library_webgpu.js) else() -endif() \ No newline at end of file +endif() diff --git a/cmake/example.cmake b/cmake/example.cmake index 6f195ec..7cf1f8d 100644 --- a/cmake/example.cmake +++ b/cmake/example.cmake @@ -94,4 +94,4 @@ if(EMSCRIPTEN) ${CMAKE_CURRENT_BINARY_DIR}/index.html @ONLY) -endif() \ No newline at end of file +endif() diff --git a/cmake/templates/index.html.in b/cmake/templates/index.html.in index 1bd64ca..b6f130c 100644 --- a/cmake/templates/index.html.in +++ b/cmake/templates/index.html.in @@ -19,4 +19,4 @@ } - \ No newline at end of file +