From 542ce0d600f6915a0240ff2437c9fe9673f64294 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:52:17 -0800 Subject: [PATCH] [WebGPU] allow build WebGPU EP for WebAssembly (#23364) ### Description This PR allows WebGPU EP to be built with Emscripten for WebAssembly, Including: - cmake build files update to support correct setup for Emscripten. - code changes to fix build breaks for wasm - change in Web CI pipeline to add a build-only target for wasm with `--use_webgpu`. --- .../external/onnxruntime_external_deps.cmake | 131 ++++++++++-------- cmake/onnxruntime_providers_webgpu.cmake | 89 +++++++----- cmake/onnxruntime_webassembly.cmake | 6 + cmake/patches/dawn/dawn.patch | 118 ++++++++++++++++ cmake/patches/emscripten/patch_3.1.74.tgz | Bin 0 -> 4655 bytes .../webgpu/bert/skip_layer_norm.cc | 2 +- .../core/providers/webgpu/allocator.cc | 4 - .../core/providers/webgpu/buffer_manager.cc | 4 +- .../core/providers/webgpu/buffer_manager.h | 4 - .../core/providers/webgpu/compute_context.h | 4 - .../core/providers/webgpu/data_transfer.cc | 4 - .../webgpu/math/binary_elementwise_ops.cc | 6 +- .../core/providers/webgpu/nn/layer_norm.cc | 3 +- .../core/providers/webgpu/program_manager.h | 4 - .../core/providers/webgpu/shader_helper.h | 4 - .../core/providers/webgpu/tensor/concat.cc | 5 +- .../core/providers/webgpu/tensor/flatten.h | 13 +- .../webgpu/tensor/gather_elements.cc | 4 +- .../core/providers/webgpu/webgpu_context.cc | 39 +++++- .../core/providers/webgpu/webgpu_context.h | 4 - .../webgpu/webgpu_execution_provider.cc | 3 - onnxruntime/test/wasm/karma.conf.js | 5 + .../templates/linux-wasm-ci.yml | 22 +++ .../azure-pipelines/templates/web-ci.yml | 6 + 24 files changed, 338 insertions(+), 146 deletions(-) create mode 100644 cmake/patches/dawn/dawn.patch create mode 100644 cmake/patches/emscripten/patch_3.1.74.tgz diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index aeaaa7b51d..0aa6b70187 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -631,78 +631,99 @@ if (onnxruntime_USE_WEBGPU) URL_HASH SHA1=${DEP_SHA1_dawn} # All previous patches are merged into the upstream dawn project. We don't need to apply any patches right now. # if we need to apply patches in the future, we can uncomment the following line. - # PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn.patch + PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn.patch ) endif() - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) - set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE BOOL "" FORCE) - set(DAWN_ENABLE_INSTALL ON CACHE BOOL "" FORCE) - - if (onnxruntime_USE_EXTERNAL_DAWN) - message(FATAL_ERROR "onnxruntime_USE_EXTERNAL_DAWN and onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY cannot be enabled at the same time.") - endif() - else() - # use dawn::dawn_native and dawn::dawn_proc instead of the monolithic dawn::webgpu_dawn to minimize binary size - set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF CACHE BOOL "" FORCE) - set(DAWN_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) - endif() set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE) set(DAWN_ENABLE_NULL OFF CACHE BOOL "" FORCE) set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "" FORCE) - # disable things we don't use - set(DAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG OFF) - set(DAWN_ENABLE_DESKTOP_GL OFF CACHE BOOL "" FORCE) - set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE) - set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING OFF CACHE BOOL "" FORCE) - set(DAWN_USE_GLFW OFF CACHE BOOL "" FORCE) - set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE) - set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE) + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + set(DAWN_EMSCRIPTEN_TOOLCHAIN "${REPO_ROOT}/cmake/external/emsdk/upstream/emscripten" CACHE STRING "" FORCE) - set(TINT_BUILD_TESTS OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_CMD_TOOLS OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_GLSL_WRITER OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_GLSL_VALIDATOR OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_IR_BINARY OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_SPV_READER OFF CACHE BOOL "" FORCE) # don't need. disabling is a large binary size saving - set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "" FORCE) # needed to create cache key. runtime error if not enabled. + # Add the missing files from the emsdk installation + # + # For a "standard" emscripten build, the folder "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/" is not used. This is the + # reason why EMSDK installation does not include it. + # However, currently the WebGPU support in Emscripten is still being developed and the Dawn project is maintaining + # a fork of the Emscripten toolchain. As an extra build step, Dawn needs to generate some files using the file + # "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/gen_struct_info.py" from emscripten, which is missing in the emscripten + # installed by emsdk. + # + # We keep a copy of the missing file(s) in ${PROJECT_SOURCE_DIR}/patches/emscripten/, and now we extract them to the + # emscripten toolchain folder. + execute_process(COMMAND ${CMAKE_COMMAND} -E tar x "${PROJECT_SOURCE_DIR}/patches/emscripten/patch_3.1.74.tgz" + WORKING_DIRECTORY ${DAWN_EMSCRIPTEN_TOOLCHAIN}) + else() + if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) + set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE BOOL "" FORCE) + set(DAWN_ENABLE_INSTALL ON CACHE BOOL "" FORCE) - # SPIR-V validation shouldn't be required given we're using Tint to create the SPIR-V. - set(DAWN_ENABLE_SPIRV_VALIDATION OFF CACHE BOOL "" FORCE) - - if (WIN32) - # building this requires the HLSL writer to be enabled in Tint. TBD if that we need either of these to be ON. - set(DAWN_USE_BUILT_DXC ON CACHE BOOL "" FORCE) - set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE) - - if ((NOT onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) AND (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12)) - message(FATAL_ERROR "At least one of onnxruntime_ENABLE_DAWN_BACKEND_VULKAN or onnxruntime_ENABLE_DAWN_BACKEND_D3D12 must be enabled when using Dawn on Windows.") - endif() - if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) - set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE) - set(TINT_BUILD_SPV_WRITER ON CACHE BOOL "" FORCE) + if (onnxruntime_USE_EXTERNAL_DAWN) + message(FATAL_ERROR "onnxruntime_USE_EXTERNAL_DAWN and onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY cannot be enabled at the same time.") + endif() else() - set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE) + # use dawn::dawn_native and dawn::dawn_proc instead of the monolithic dawn::webgpu_dawn to minimize binary size + set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF CACHE BOOL "" FORCE) + set(DAWN_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) endif() - if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) - set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE) - else() - set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE) + + # disable things we don't use + set(DAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG OFF) + set(DAWN_ENABLE_DESKTOP_GL OFF CACHE BOOL "" FORCE) + set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE) + set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING OFF CACHE BOOL "" FORCE) + set(DAWN_USE_GLFW OFF CACHE BOOL "" FORCE) + set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE) + set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE) + + set(TINT_BUILD_TESTS OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_CMD_TOOLS OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_GLSL_WRITER OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_GLSL_VALIDATOR OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_IR_BINARY OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_SPV_READER OFF CACHE BOOL "" FORCE) # don't need. disabling is a large binary size saving + set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "" FORCE) # needed to create cache key. runtime error if not enabled. + + # SPIR-V validation shouldn't be required given we're using Tint to create the SPIR-V. + set(DAWN_ENABLE_SPIRV_VALIDATION OFF CACHE BOOL "" FORCE) + + if (WIN32) + # building this requires the HLSL writer to be enabled in Tint. TBD if that we need either of these to be ON. + set(DAWN_USE_BUILT_DXC ON CACHE BOOL "" FORCE) + set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE) + + if ((NOT onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) AND (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12)) + message(FATAL_ERROR "At least one of onnxruntime_ENABLE_DAWN_BACKEND_VULKAN or onnxruntime_ENABLE_DAWN_BACKEND_D3D12 must be enabled when using Dawn on Windows.") + endif() + if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) + set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE) + set(TINT_BUILD_SPV_WRITER ON CACHE BOOL "" FORCE) + else() + set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE) + endif() + if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE) + else() + set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE) + endif() + # We are currently always using the D3D12 backend. + set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE) endif() - # We are currently always using the D3D12 backend. - set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE) endif() onnxruntime_fetchcontent_makeavailable(dawn) - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) - list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::webgpu_dawn) - else() - if (NOT onnxruntime_USE_EXTERNAL_DAWN) - list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::dawn_native) + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::webgpu_dawn) + else() + if (NOT onnxruntime_USE_EXTERNAL_DAWN) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::dawn_native) + endif() + list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::dawn_proc) endif() - list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::dawn_proc) endif() endif() diff --git a/cmake/onnxruntime_providers_webgpu.cmake b/cmake/onnxruntime_providers_webgpu.cmake index fb3dc43abc..4bbca7b1b8 100644 --- a/cmake/onnxruntime_providers_webgpu.cmake +++ b/cmake/onnxruntime_providers_webgpu.cmake @@ -21,44 +21,71 @@ source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_providers_webgpu_cc_srcs}) onnxruntime_add_static_library(onnxruntime_providers_webgpu ${onnxruntime_providers_webgpu_cc_srcs}) onnxruntime_add_include_to_target(onnxruntime_providers_webgpu - onnxruntime_common dawn::dawncpp_headers dawn::dawn_headers onnx onnx_proto flatbuffers::flatbuffers Boost::mp11 safeint_interface) + onnxruntime_common onnx onnx_proto flatbuffers::flatbuffers Boost::mp11 safeint_interface) - set(onnxruntime_providers_webgpu_dll_deps) - - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) - target_link_libraries(onnxruntime_providers_webgpu dawn::webgpu_dawn) - - if (WIN32) - if (onnxruntime_ENABLE_DELAY_LOADING_WIN_DLLS) - list(APPEND onnxruntime_DELAYLOAD_FLAGS "/DELAYLOAD:webgpu_dawn.dll") - endif() - - list(APPEND onnxruntime_providers_webgpu_dll_deps "$") + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + # target "emdawnwebgpu_c" is created by Dawn, including "-fno-exceptions" in its compile options by default. + # + # in ONNX Runtime build, "-s DISABLE_EXCEPTION_CATCHING=0" is appended to CMAKE_CXX_FLAGS by default unless build flag + # "--disable_wasm_exception_catching" is specified. It is not compatible with "-fno-exceptions". + # + # if "-s DISABLE_EXCEPTION_CATCHING=0" is set, we need to remove "-fno-exceptions" from emdawnwebgpu_c + if (CMAKE_CXX_FLAGS MATCHES "DISABLE_EXCEPTION_CATCHING=0") + get_property(EM_DAWN_WEBGPU_C_COMPILE_OPTIONS TARGET emdawnwebgpu_c PROPERTY COMPILE_OPTIONS) + list(REMOVE_ITEM EM_DAWN_WEBGPU_C_COMPILE_OPTIONS "-fno-exceptions") + set_property(TARGET emdawnwebgpu_c PROPERTY COMPILE_OPTIONS ${EM_DAWN_WEBGPU_C_COMPILE_OPTIONS}) endif() + + # target "emdawnwebgpu_cpp" is created by Dawn. When it is linked to onnxruntime_providers_webgpu as "PUBLIC" + # dependency, a few build/link flags will be set automatically to make sure emscripten can generate correct + # WebAssembly/JavaScript code for WebGPU support. + target_link_libraries(onnxruntime_providers_webgpu PUBLIC emdawnwebgpu_cpp) + + # ASYNCIFY is required for WGPUFuture support (ie. async functions in WebGPU API) + target_link_options(onnxruntime_providers_webgpu PUBLIC + "SHELL:-s ASYNCIFY=1" + "SHELL:-s ASYNCIFY_STACK_SIZE=65536" + ) else() - if (NOT onnxruntime_USE_EXTERNAL_DAWN) - target_link_libraries(onnxruntime_providers_webgpu dawn::dawn_native) + onnxruntime_add_include_to_target(onnxruntime_providers_webgpu dawn::dawncpp_headers dawn::dawn_headers) + + set(onnxruntime_providers_webgpu_dll_deps) + + if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) + target_link_libraries(onnxruntime_providers_webgpu dawn::webgpu_dawn) + + if (WIN32) + if (onnxruntime_ENABLE_DELAY_LOADING_WIN_DLLS) + list(APPEND onnxruntime_DELAYLOAD_FLAGS "/DELAYLOAD:webgpu_dawn.dll") + endif() + + list(APPEND onnxruntime_providers_webgpu_dll_deps "$") + endif() + else() + if (NOT onnxruntime_USE_EXTERNAL_DAWN) + target_link_libraries(onnxruntime_providers_webgpu dawn::dawn_native) + endif() + target_link_libraries(onnxruntime_providers_webgpu dawn::dawn_proc) endif() - target_link_libraries(onnxruntime_providers_webgpu dawn::dawn_proc) - endif() - if (WIN32 AND onnxruntime_ENABLE_DAWN_BACKEND_D3D12) - # Ensure dxil.dll and dxcompiler.dll exist in the output directory $ - add_dependencies(onnxruntime_providers_webgpu copy_dxil_dll) - add_dependencies(onnxruntime_providers_webgpu dxcompiler) + if (WIN32 AND onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + # Ensure dxil.dll and dxcompiler.dll exist in the output directory $ + add_dependencies(onnxruntime_providers_webgpu copy_dxil_dll) + add_dependencies(onnxruntime_providers_webgpu dxcompiler) - list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxil.dll") - list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxcompiler.dll") - endif() + list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxil.dll") + list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxcompiler.dll") + endif() - if (onnxruntime_providers_webgpu_dll_deps) - # Copy dependency DLLs to the output directory - add_custom_command( - TARGET onnxruntime_providers_webgpu - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${onnxruntime_providers_webgpu_dll_deps}" "$" - COMMAND_EXPAND_LISTS - VERBATIM ) + if (onnxruntime_providers_webgpu_dll_deps) + # Copy dependency DLLs to the output directory + add_custom_command( + TARGET onnxruntime_providers_webgpu + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${onnxruntime_providers_webgpu_dll_deps}" "$" + COMMAND_EXPAND_LISTS + VERBATIM ) + endif() endif() add_dependencies(onnxruntime_providers_webgpu ${onnxruntime_EXTERNAL_DEPENDENCIES}) diff --git a/cmake/onnxruntime_webassembly.cmake b/cmake/onnxruntime_webassembly.cmake index c29503ecc4..6cd05d1ad0 100644 --- a/cmake/onnxruntime_webassembly.cmake +++ b/cmake/onnxruntime_webassembly.cmake @@ -111,6 +111,7 @@ if (onnxruntime_BUILD_WEBASSEMBLY_STATIC_LIB) ${PROVIDERS_JS} ${PROVIDERS_XNNPACK} ${PROVIDERS_WEBNN} + ${PROVIDERS_WEBGPU} onnxruntime_session onnxruntime_util re2::re2 @@ -188,6 +189,7 @@ else() ${PROVIDERS_JS} ${PROVIDERS_XNNPACK} ${PROVIDERS_WEBNN} + ${PROVIDERS_WEBGPU} onnxruntime_session onnxruntime_util re2::re2 @@ -391,6 +393,10 @@ jsepDownload:_pp_") endif() endif() + if (onnxruntime_USE_WEBGPU) + target_compile_definitions(onnxruntime_webassembly PRIVATE USE_WEBGPU=1) + endif() + if (onnxruntime_EMSCRIPTEN_SETTINGS) foreach(setting IN LISTS onnxruntime_EMSCRIPTEN_SETTINGS) target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s ${setting}") diff --git a/cmake/patches/dawn/dawn.patch b/cmake/patches/dawn/dawn.patch new file mode 100644 index 0000000000..868db0c43e --- /dev/null +++ b/cmake/patches/dawn/dawn.patch @@ -0,0 +1,118 @@ +diff --git a/src/emdawnwebgpu/CMakeLists.txt b/src/emdawnwebgpu/CMakeLists.txt +index de673537d3..c98dc46de7 100644 +--- a/src/emdawnwebgpu/CMakeLists.txt ++++ b/src/emdawnwebgpu/CMakeLists.txt +@@ -78,6 +78,7 @@ if (${DAWN_ENABLE_EMSCRIPTEN}) + endif() + + set(ARGS ++ ${Python3_EXECUTABLE} + "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/gen_struct_info.py" + -q + "${EM_BUILD_GEN_DIR}/struct_info_webgpu.json" +diff --git a/third_party/emdawnwebgpu/library_webgpu.js b/third_party/emdawnwebgpu/library_webgpu.js +index d1835cb090..df03ea2f94 100644 +--- a/third_party/emdawnwebgpu/library_webgpu.js ++++ b/third_party/emdawnwebgpu/library_webgpu.js +@@ -16,10 +16,19 @@ + throw new Error("To use Dawn's library_webgpu.js, disable -sUSE_WEBGPU and first include Dawn's library_webgpu_struct_info.js and library_webgpu_enum_tables.js (before library_webgpu.js)"); + } + ++ if (MEMORY64) { ++ throw new Error("The current implementation of Dawn's library_webgpu.js does not support MEMORY64 yet"); ++ } ++ + // Helper functions for code generation + globalThis.gpu = { +- convertSentinelToUndefined: function(name) { +- return `if (${name} == -1) ${name} = undefined;`; ++ convertSentinelToUndefined: function(name, isPtr = false) { ++ // When `CAN_ADDRESS_2GB` is true, value `-1` is normalized to `0xFFFFFFFF` for pointer. ++ if (CAN_ADDRESS_2GB && isPtr) { ++ return `if (${name} == 0xFFFFFFFF) ${name} = undefined;`; ++ } else { ++ return `if (${name} == -1) ${name} = undefined;`; ++ } + }, + + makeGetBool: function(struct, offset) { +@@ -700,6 +709,7 @@ var LibraryWebGPU = { + {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.adapterType, 'adapterType', 'i32') }}}; + {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.vendorID, '0', 'i32') }}}; + {{{ makeSetValue('info', C_STRUCTS.WGPUAdapterInfo.deviceID, '0', 'i32') }}}; ++ return 1; + }, + + wgpuAdapterGetLimits: (adapterPtr, limitsOutPtr) => { +@@ -882,7 +892,7 @@ var LibraryWebGPU = { + + if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE'); + +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + + var mapped; + try { +@@ -909,7 +919,7 @@ var LibraryWebGPU = { + + if (size === 0) warnOnce('getMappedRange size=0 no longer means WGPU_WHOLE_MAP_SIZE'); + +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + + var mapped; + try { +@@ -950,7 +960,7 @@ var LibraryWebGPU = { + var buffer = WebGPU.getJsObject(bufferPtr); + WebGPU.Internals.bufferOnUnmaps[bufferPtr] = []; + +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + + {{{ runtimeKeepalivePush() }}} + WebGPU.Internals.futureInsert(futureId, buffer.mapAsync(mode, offset, size).then(() => { +@@ -1145,7 +1155,7 @@ var LibraryWebGPU = { + + wgpuCommandEncoderClearBuffer: (encoderPtr, bufferPtr, offset, size) => { + var commandEncoder = WebGPU.getJsObject(encoderPtr); +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + + var buffer = WebGPU.getJsObject(bufferPtr); + commandEncoder.clearBuffer(buffer, offset, size); +@@ -2103,7 +2113,7 @@ var LibraryWebGPU = { + wgpuRenderBundleEncoderSetIndexBuffer: (passPtr, bufferPtr, format, offset, size) => { + var pass = WebGPU.getJsObject(passPtr); + var buffer = WebGPU.getJsObject(bufferPtr); +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size); + }, + +@@ -2116,7 +2126,7 @@ var LibraryWebGPU = { + wgpuRenderBundleEncoderSetVertexBuffer: (passPtr, slot, bufferPtr, offset, size) => { + var pass = WebGPU.getJsObject(passPtr); + var buffer = WebGPU.getJsObject(bufferPtr); +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + pass.setVertexBuffer(slot, buffer, offset, size); + }, + +@@ -2211,7 +2221,7 @@ var LibraryWebGPU = { + wgpuRenderPassEncoderSetIndexBuffer: (passPtr, bufferPtr, format, offset, size) => { + var pass = WebGPU.getJsObject(passPtr); + var buffer = WebGPU.getJsObject(bufferPtr); +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + pass.setIndexBuffer(buffer, WebGPU.IndexFormat[format], offset, size); + }, + +@@ -2234,7 +2244,7 @@ var LibraryWebGPU = { + wgpuRenderPassEncoderSetVertexBuffer: (passPtr, slot, bufferPtr, offset, size) => { + var pass = WebGPU.getJsObject(passPtr); + var buffer = WebGPU.getJsObject(bufferPtr); +- {{{ gpu.convertSentinelToUndefined('size') }}} ++ {{{ gpu.convertSentinelToUndefined('size', true) }}} + pass.setVertexBuffer(slot, buffer, offset, size); + }, + diff --git a/cmake/patches/emscripten/patch_3.1.74.tgz b/cmake/patches/emscripten/patch_3.1.74.tgz new file mode 100644 index 0000000000000000000000000000000000000000..cfb52de6386538aede41508e829843fecc858433 GIT binary patch literal 4655 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 literal 0 HcmV?d00001 diff --git a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc index fe541f58d3..a1840257d7 100644 --- a/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc +++ b/onnxruntime/contrib_ops/webgpu/bert/skip_layer_norm.cc @@ -116,7 +116,7 @@ Status SkipLayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeCo auto* output = context.Output(0, x_shape); auto* input_skip_bias_sum = context.Output(3, x_shape); - size_t data_size = x_shape.Size(); + int64_t data_size = x_shape.Size(); if (data_size == 0) { return Status::OK(); } diff --git a/onnxruntime/core/providers/webgpu/allocator.cc b/onnxruntime/core/providers/webgpu/allocator.cc index 8e27acdc28..51a06ad764 100644 --- a/onnxruntime/core/providers/webgpu/allocator.cc +++ b/onnxruntime/core/providers/webgpu/allocator.cc @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#ifdef __EMSCRIPTEN__ -#include -#endif - #include "core/framework/session_state.h" #include "core/providers/webgpu/allocator.h" #include "core/providers/webgpu/webgpu_context.h" diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.cc b/onnxruntime/core/providers/webgpu/buffer_manager.cc index 233bb24083..1c2ff3f91a 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.cc +++ b/onnxruntime/core/providers/webgpu/buffer_manager.cc @@ -85,7 +85,7 @@ class SimpleCacheManager : public IBufferCacheManager { void OnRefresh() override { for (auto& buffer : pending_buffers_) { - buffers_[wgpuBufferGetSize(buffer)].push_back(buffer); + buffers_[static_cast(wgpuBufferGetSize(buffer))].push_back(buffer); } pending_buffers_.clear(); } @@ -167,7 +167,7 @@ class BucketCacheManager : public IBufferCacheManager { // TODO: consider graph capture. currently not supported for (auto& buffer : pending_buffers_) { - auto buffer_size = wgpuBufferGetSize(buffer); + auto buffer_size = static_cast(wgpuBufferGetSize(buffer)); auto it = buckets_.find(buffer_size); if (it != buckets_.end() && it->second.size() < buckets_limit_[buffer_size]) { diff --git a/onnxruntime/core/providers/webgpu/buffer_manager.h b/onnxruntime/core/providers/webgpu/buffer_manager.h index 00febfbc29..20bee52835 100644 --- a/onnxruntime/core/providers/webgpu/buffer_manager.h +++ b/onnxruntime/core/providers/webgpu/buffer_manager.h @@ -5,10 +5,6 @@ #include -#ifdef __EMSCRIPTEN__ -#include -#endif - #include #include "core/framework/execution_provider.h" diff --git a/onnxruntime/core/providers/webgpu/compute_context.h b/onnxruntime/core/providers/webgpu/compute_context.h index 2fbd639b27..680e03aef0 100644 --- a/onnxruntime/core/providers/webgpu/compute_context.h +++ b/onnxruntime/core/providers/webgpu/compute_context.h @@ -3,10 +3,6 @@ #pragma once -#ifdef __EMSCRIPTEN__ -#include -#endif - #include #include diff --git a/onnxruntime/core/providers/webgpu/data_transfer.cc b/onnxruntime/core/providers/webgpu/data_transfer.cc index 615ae11175..ac376b4fce 100644 --- a/onnxruntime/core/providers/webgpu/data_transfer.cc +++ b/onnxruntime/core/providers/webgpu/data_transfer.cc @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#ifdef __EMSCRIPTEN__ -#include -#endif - #include "core/providers/webgpu/data_transfer.h" #include "core/providers/webgpu/webgpu_context.h" diff --git a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc index ec7fed5a94..75866513e2 100644 --- a/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc +++ b/onnxruntime/core/providers/webgpu/math/binary_elementwise_ops.cc @@ -123,10 +123,10 @@ Status BinaryElementwise::ComputeInternal(ComputeContext& context) const { if (a_last_dim_divisible_by_4 || b_last_dim_divisible_by_4) { vectorize = true; } else { - size_t shared_dimension = 1; + int64_t shared_dimension = 1; for (size_t i = 1; i < output_shape.NumDimensions(); i++) { - size_t dimA = lhs_shape.NumDimensions() >= i ? lhs_shape[lhs_shape.NumDimensions() - i] : 1; - size_t dimB = rhs_shape.NumDimensions() >= i ? rhs_shape[rhs_shape.NumDimensions() - i] : 1; + int64_t dimA = lhs_shape.NumDimensions() >= i ? lhs_shape[lhs_shape.NumDimensions() - i] : 1; + int64_t dimB = rhs_shape.NumDimensions() >= i ? rhs_shape[rhs_shape.NumDimensions() - i] : 1; if (dimA == dimB) { shared_dimension *= dimA; num_shared_dimension++; diff --git a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc index 1ee771e945..64172021e8 100644 --- a/onnxruntime/core/providers/webgpu/nn/layer_norm.cc +++ b/onnxruntime/core/providers/webgpu/nn/layer_norm.cc @@ -85,8 +85,7 @@ Status LayerNorm::ComputeInternal(onnxruntime::webgpu::ComputeContex auto* output = context.Output(0, x_shape); - size_t data_size = x_shape.Size(); - if (data_size == 0) { + if (x_shape.Size() == 0) { return Status::OK(); } diff --git a/onnxruntime/core/providers/webgpu/program_manager.h b/onnxruntime/core/providers/webgpu/program_manager.h index eded1cfa17..5572177001 100644 --- a/onnxruntime/core/providers/webgpu/program_manager.h +++ b/onnxruntime/core/providers/webgpu/program_manager.h @@ -3,10 +3,6 @@ #pragma once -#ifdef __EMSCRIPTEN__ -#include -#endif - #include #include diff --git a/onnxruntime/core/providers/webgpu/shader_helper.h b/onnxruntime/core/providers/webgpu/shader_helper.h index a4b96edc63..dac08f3bd9 100644 --- a/onnxruntime/core/providers/webgpu/shader_helper.h +++ b/onnxruntime/core/providers/webgpu/shader_helper.h @@ -5,10 +5,6 @@ #include -#ifdef __EMSCRIPTEN__ -#include -#endif - #include #include "core/framework/tensor_shape.h" diff --git a/onnxruntime/core/providers/webgpu/tensor/concat.cc b/onnxruntime/core/providers/webgpu/tensor/concat.cc index c708f24dcc..5ed8099fde 100644 --- a/onnxruntime/core/providers/webgpu/tensor/concat.cc +++ b/onnxruntime/core/providers/webgpu/tensor/concat.cc @@ -106,7 +106,8 @@ Status Concat::ComputeInternal(ComputeContext& context) const { uint32_t output_size = gsl::narrow_cast(prepare.output_tensor->Shape().Size()); - ConcatProgram program{prepare.axis}; + size_t axis = static_cast(prepare.axis); + ConcatProgram program{axis}; std::vector sizes_in_concat_axis; sizes_in_concat_axis.reserve(input_count); @@ -118,7 +119,7 @@ Status Concat::ComputeInternal(ComputeContext& context) const { } program.AddInput({input.tensor, ProgramTensorMetadataDependency::TypeAndRank}); - auto axis_size = input.tensor->Shape()[prepare.axis]; + auto axis_size = input.tensor->Shape()[axis]; sum += static_cast(axis_size); sizes_in_concat_axis.push_back(sum); } diff --git a/onnxruntime/core/providers/webgpu/tensor/flatten.h b/onnxruntime/core/providers/webgpu/tensor/flatten.h index 5fc49a844b..68f47eacd8 100644 --- a/onnxruntime/core/providers/webgpu/tensor/flatten.h +++ b/onnxruntime/core/providers/webgpu/tensor/flatten.h @@ -31,15 +31,8 @@ class Flatten final : public OpKernel { return Status(common::ONNXRUNTIME, common::FAIL, "Invalid value for axis, must be less than or equal to input_rank"); } - int64_t first_dim = 1; - for (int64_t i = 0; i < axis; i++) { - first_dim *= input_shape[i]; - } - - int64_t second_dim = 1; - for (int64_t i = axis; i < input_rank; i++) { - second_dim *= input_shape[i]; - } + int64_t first_dim = input_shape.SizeToDimension(static_cast(axis)); + int64_t second_dim = input_shape.SizeFromDimension(static_cast(axis)); TensorShape output_shape({first_dim, second_dim}); Tensor* output_tensor = context->Output(0, output_shape); @@ -59,4 +52,4 @@ class Flatten final : public OpKernel { }; } // namespace webgpu -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/tensor/gather_elements.cc b/onnxruntime/core/providers/webgpu/tensor/gather_elements.cc index 00d8caf262..4938cd7acf 100644 --- a/onnxruntime/core/providers/webgpu/tensor/gather_elements.cc +++ b/onnxruntime/core/providers/webgpu/tensor/gather_elements.cc @@ -59,7 +59,7 @@ Status GatherElements::ComputeInternal(ComputeContext& context) const { axis += input_rank; } - auto axis_dim_limit = input_shape[axis]; + auto axis_dim_limit = input_shape[static_cast(axis)]; auto output_dims = indices_shape.AsShapeVector(); TensorShape output_shape(output_dims); @@ -83,4 +83,4 @@ Status GatherElements::ComputeInternal(ComputeContext& context) const { } } // namespace webgpu -} // namespace onnxruntime \ No newline at end of file +} // namespace onnxruntime diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.cc b/onnxruntime/core/providers/webgpu/webgpu_context.cc index 46e2069a52..1c9a16bf36 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_context.cc @@ -4,10 +4,12 @@ #include #include +#if !defined(__wasm__) #include "dawn/dawn_proc.h" #if !defined(USE_EXTERNAL_DAWN) #include "dawn/native/DawnNative.h" #endif +#endif #include "core/common/common.h" #include "core/common/path_string.h" @@ -29,7 +31,7 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi std::call_once(init_flag_, [this, &buffer_cache_config, backend_type]() { // Create wgpu::Adapter if (adapter_ == nullptr) { -#if !defined(__EMSCRIPTEN__) && defined(_MSC_VER) && defined(DAWN_ENABLE_D3D12) && !defined(USE_EXTERNAL_DAWN) +#if !defined(__wasm__) && defined(_MSC_VER) && defined(DAWN_ENABLE_D3D12) && !defined(USE_EXTERNAL_DAWN) // If we are using the D3D12 backend on Windows and the build does not use external Dawn, dxil.dll and dxcompiler.dll are required. // // Dawn will try to load them later, but if they are in the different directory to the executable, it may fail to find them. @@ -54,15 +56,19 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi #endif wgpu::RequestAdapterOptions req_adapter_options = {}; - wgpu::DawnTogglesDescriptor adapter_toggles_desc = {}; - req_adapter_options.nextInChain = &adapter_toggles_desc; req_adapter_options.backendType = static_cast(backend_type); req_adapter_options.powerPreference = wgpu::PowerPreference::HighPerformance; +#if !defined(__wasm__) auto enabled_adapter_toggles = GetEnabledAdapterToggles(); + + wgpu::DawnTogglesDescriptor adapter_toggles_desc = {}; adapter_toggles_desc.enabledToggleCount = enabled_adapter_toggles.size(); adapter_toggles_desc.enabledToggles = enabled_adapter_toggles.data(); + req_adapter_options.nextInChain = &adapter_toggles_desc; +#endif + ORT_ENFORCE(wgpu::WaitStatus::Success == instance_.WaitAny(instance_.RequestAdapter( &req_adapter_options, wgpu::CallbackMode::WaitAnyOnly, @@ -78,6 +84,8 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi // Create wgpu::Device if (device_ == nullptr) { wgpu::DeviceDescriptor device_desc = {}; + +#if !defined(__wasm__) wgpu::DawnTogglesDescriptor device_toggles_desc = {}; device_desc.nextInChain = &device_toggles_desc; @@ -88,6 +96,7 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi auto disabled_device_toggles = GetDisabledDeviceToggles(); device_toggles_desc.disabledToggleCount = disabled_device_toggles.size(); device_toggles_desc.disabledToggles = disabled_device_toggles.data(); +#endif std::vector required_features = GetAvailableRequiredFeatures(adapter_); if (required_features.size() > 0) { @@ -135,9 +144,12 @@ void WebGpuContext::Initialize(const WebGpuBufferCacheConfig& buffer_cache_confi program_mgr_ = std::make_unique(Device(), DeviceLimits()); // set query type +#if !defined(__wasm__) if (device_.HasFeature(wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses)) { query_type_ = TimestampQueryType::InsidePasses; - } else if (device_.HasFeature(wgpu::FeatureName::TimestampQuery)) { + } else +#endif + if (device_.HasFeature(wgpu::FeatureName::TimestampQuery)) { query_type_ = TimestampQueryType::AtPasses; } else { query_type_ = TimestampQueryType::None; @@ -455,7 +467,9 @@ std::vector WebGpuContext::GetDisabledDeviceToggles() const { std::vector WebGpuContext::GetAvailableRequiredFeatures(const wgpu::Adapter& adapter) const { std::vector required_features; constexpr wgpu::FeatureName features[]{ +#if !defined(__wasm__) wgpu::FeatureName::ChromiumExperimentalTimestampQueryInsidePasses, +#endif wgpu::FeatureName::TimestampQuery, wgpu::FeatureName::ShaderF16, wgpu::FeatureName::Subgroups, @@ -530,7 +544,7 @@ void WebGpuContext::CollectProfilingData(profiling::Events& events) { ORT_ENFORCE(Wait(query_read_buffer.MapAsync(wgpu::MapMode::Read, 0, - query_read_buffer.GetSize(), + static_cast(query_read_buffer.GetSize()), wgpu::CallbackMode::WaitAnyOnly, [](wgpu::MapAsyncStatus status, wgpu::StringView message) { ORT_ENFORCE(status == wgpu::MapAsyncStatus::Success, "Failed to download data from buffer: ", std::string_view{message}); @@ -657,8 +671,14 @@ WebGpuContext& WebGpuContextFactory::CreateContext(const WebGpuContextConfig& co ORT_ENFORCE(instance == nullptr && adapter == nullptr && device == nullptr, "WebGPU EP default context (contextId=0) must not have custom WebGPU instance, adapter or device."); - std::call_once(init_default_flag_, [dawn_proc_table = config.dawn_proc_table]() { - // Step.1 - setup dawn proc table + std::call_once(init_default_flag_, [ +#if !defined(__wasm__) + dawn_proc_table = config.dawn_proc_table +#endif + ]() { + // Step.1 - setup dawn proc table (only for non-WASM build) + +#if !defined(__wasm__) const DawnProcTable* dawn_procs = reinterpret_cast(dawn_proc_table); #if defined(BUILD_DAWN_MONOLITHIC_LIBRARY) ORT_ENFORCE(dawn_procs == nullptr, "setting DawnProcTable is not allowed when dynamically linked to webgpu_dawn."); @@ -671,12 +691,17 @@ WebGpuContext& WebGpuContextFactory::CreateContext(const WebGpuContextConfig& co ORT_ENFORCE(dawn_procs != nullptr, "DawnProcTable must be provided."); #endif dawnProcSetProcs(dawn_procs); +#endif #endif // Step.2 - Create wgpu::Instance +#if !defined(__wasm__) wgpu::InstanceDescriptor instance_desc{}; instance_desc.features.timedWaitAnyEnable = true; default_instance_ = wgpu::CreateInstance(&instance_desc); +#else + default_instance_ = wgpu::CreateInstance(nullptr); +#endif ORT_ENFORCE(default_instance_ != nullptr, "Failed to create wgpu::Instance."); }); diff --git a/onnxruntime/core/providers/webgpu/webgpu_context.h b/onnxruntime/core/providers/webgpu/webgpu_context.h index 4724118a29..80c8c64ce7 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_context.h +++ b/onnxruntime/core/providers/webgpu/webgpu_context.h @@ -3,10 +3,6 @@ #pragma once -#ifdef __EMSCRIPTEN__ -#include -#endif - #include #include diff --git a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc index 7f327f8a81..dec7e48786 100644 --- a/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc +++ b/onnxruntime/core/providers/webgpu/webgpu_execution_provider.cc @@ -3,9 +3,6 @@ #include "core/providers/webgpu/webgpu_execution_provider.h" -#ifdef __EMSCRIPTEN__ -#include -#endif #include #include #include diff --git a/onnxruntime/test/wasm/karma.conf.js b/onnxruntime/test/wasm/karma.conf.js index d6830501d2..412e449622 100644 --- a/onnxruntime/test/wasm/karma.conf.js +++ b/onnxruntime/test/wasm/karma.conf.js @@ -38,6 +38,10 @@ const gtestReporter = {'reporter:gtest': ['type', function() { }; }]}; +// In Node.js v16 and below, 'localhost' is using IPv4, so need to listen to '0.0.0.0' +// In Node.js v17+, 'localhost' is using IPv6, so need to listen to '::' +const listenAddress = Number.parseInt(process.versions.node.split('.')[0]) >= 17 ? '::' : '0.0.0.0'; + module.exports = function(config) { config.set({ basePath: '.', @@ -60,6 +64,7 @@ module.exports = function(config) { browserDisconnectTimeout: 600000, // allow running tests for 30 minutes browserNoActivityTimeout: 30 * 60 * 1000, + listenAddress, customLaunchers: { ChromeTest: { base: 'ChromeCanary', diff --git a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml index 3ab1cd45ff..1df7407987 100644 --- a/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/linux-wasm-ci.yml @@ -26,6 +26,10 @@ parameters: type: boolean default: false +- name: BuildWebGPU + type: boolean + default: false + # In fact, it's only used on Linux for compiler cache. - name: BuildStaticLib type: boolean @@ -122,6 +126,24 @@ jobs: DisplayName: 'Build (simd + threads + JSEP)' WithCache: ${{ parameters.WithCache }} + - ${{ if eq(parameters.BuildWebGPU, true) }}: + # This step only verifies whether the build is successful. + # currently, we uses EMSDK 3.1.59, which is not compatible with Dawn's changes in its Emscripten fork. Closure compiler will not work for WebGPU build. + # Only enables in DEBUG build. + # + # TODO: when upgrading to a newer Emscripten version, we should fix this step. + - template: build-linux-wasm-step.yml + parameters: + Today: $(Today) + ${{ if eq(parameters.BuildStaticLib, true)}}: + AdditionalKey: wasm_inferencing_webgpu_exp | ${{ parameters.BuildConfig }} | static + ${{ else }}: + AdditionalKey: wasm_inferencing_webgpu_exp | ${{ parameters.BuildConfig }} + CacheDir: $(ORT_CACHE_DIR)/wasm_inferencing_webgpu + Arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)/wasm_inferencing_webgpu --use_webgpu --target onnxruntime_webassembly --skip_tests' + DisplayName: 'Build (simd + threads + WebGPU experimental)' + WithCache: ${{ parameters.WithCache }} + - ${{ if eq(parameters.SkipPublish, false) }}: - script: | cp $(Build.BinariesDirectory)/wasm_inferencing/${{ parameters.BuildConfig }}/ort-wasm-simd-threaded.wasm $(Build.ArtifactStagingDirectory) diff --git a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml index 3f44bcb222..d059921bb7 100644 --- a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml @@ -23,6 +23,10 @@ parameters: displayName: 'Build JSEP' type: boolean default: true +- name: BuildWebGPU + displayName: 'Build WebGPU (EP)' + type: boolean + default: true - name: WASMTemplate type: string @@ -98,6 +102,7 @@ stages: ExtraBuildArgs: '--enable_wasm_profiling ${{ parameters.ExtraBuildArgs }}' PoolName: ${{ parameters.PoolName }} BuildJsep: ${{ parameters.BuildJsep }} + BuildWebGPU: ${{ parameters.BuildWebGPU }} WithCache: ${{ parameters.WithCache }} - stage: Build_web_Debug @@ -128,6 +133,7 @@ stages: ExtraBuildArgs: '--target onnxruntime_webassembly --skip_tests --enable_wasm_api_exception_catching --disable_rtti ${{ parameters.ExtraBuildArgs }}' PoolName: ${{ parameters.PoolName }} BuildJsep: ${{ parameters.BuildJsep }} + BuildWebGPU: false WithCache: ${{ parameters.WithCache }} - ${{ if eq(parameters.BuildStaticLib, 'true') }}: