From 4712009f8a83592d6da5ea513ac482d6b666cfb7 Mon Sep 17 00:00:00 2001 From: Yulong Wang <7679871+fs-eire@users.noreply.github.com> Date: Thu, 4 May 2023 10:05:39 -0700 Subject: [PATCH] [js/web] add target ort.webgpu.min.js (#15780) ### Description add target ort.webgpu.min.js WebGPU is experimental feature, so I don't want to put webgpu into the ort.min.js file. This change adds 2 ways for users to access ort-web with webgpu: - using script tag: by URL `https://cdn.jsdelivr.net/npm/onnxruntime-web@1.15.0/dist/ort.webgpu.min.js` ( this URL is not ready yet ) - using `import()`: use `import { Tensor, InferenceSession } from 'onnxruntime-web/webgpu';` - 'onnxruntime-web/webgpu' instead of 'onnxruntime-web' --- js/web/.gitignore | 2 + js/web/.npmignore | 3 +- js/web/karma.conf.js | 4 ++ js/web/lib/wasm/wasm-factory.ts | 40 ++++++++++++++----- js/web/package.json | 9 ++++- js/web/script/pull-prebuilt-wasm-artifacts.ts | 4 ++ js/web/types.d.ts | 10 +++++ js/web/webpack.config.js | 28 ++++++++++--- .../azure-pipelines/templates/web-ci.yml | 1 + .../azure-pipelines/templates/win-wasm-ci.yml | 4 +- 10 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 js/web/types.d.ts diff --git a/js/web/.gitignore b/js/web/.gitignore index 438068ff32..5b9e31ad5e 100644 --- a/js/web/.gitignore +++ b/js/web/.gitignore @@ -15,6 +15,8 @@ test/**/*.js.map script/**/*.js script/**/*.js.map +!/types.d.ts + lib/wasm/binding/**/*.wasm !lib/wasm/binding/**/*.d.ts diff --git a/js/web/.npmignore b/js/web/.npmignore index e21a906c9a..8e08db5917 100644 --- a/js/web/.npmignore +++ b/js/web/.npmignore @@ -4,8 +4,7 @@ /dist/**/*.report.html -/types/**/*.d.ts -!/types/lib/**/*.d.ts +/types/ karma.conf.js tsconfig.json diff --git a/js/web/karma.conf.js b/js/web/karma.conf.js index 2a4e71e064..860a7d2e20 100644 --- a/js/web/karma.conf.js +++ b/js/web/karma.conf.js @@ -63,6 +63,8 @@ module.exports = function (config) { { pattern: 'dist/ort-wasm-threaded.wasm', included: false }, { pattern: 'dist/ort-wasm-simd.wasm', included: false }, { pattern: 'dist/ort-wasm-simd-threaded.wasm', included: false }, + { pattern: 'dist/ort-wasm-simd.jsep.wasm', included: false }, + { pattern: 'dist/ort-wasm-simd-threaded.jsep.wasm', included: false }, { pattern: 'dist/ort-wasm-threaded.worker.js', included: false }, ], proxies: { @@ -70,6 +72,8 @@ module.exports = function (config) { '/base/test/ort-wasm-threaded.wasm': '/base/dist/ort-wasm-threaded.wasm', '/base/test/ort-wasm-simd.wasm': '/base/dist/ort-wasm-simd.wasm', '/base/test/ort-wasm-simd-threaded.wasm': '/base/dist/ort-wasm-simd-threaded.wasm', + '/base/test/ort-wasm-simd.jsep.wasm': '/base/dist/ort-wasm-simd.jsep.wasm', + '/base/test/ort-wasm-simd-threaded.jsep.wasm': '/base/dist/ort-wasm-simd-threaded.jsep.wasm', '/base/test/ort-wasm-threaded.worker.js': '/base/dist/ort-wasm-threaded.worker.js', }, plugins: karmaPlugins, diff --git a/js/web/lib/wasm/wasm-factory.ts b/js/web/lib/wasm/wasm-factory.ts index 683e15e884..7648f0c473 100644 --- a/js/web/lib/wasm/wasm-factory.ts +++ b/js/web/lib/wasm/wasm-factory.ts @@ -6,11 +6,16 @@ import * as path from 'path'; import {OrtWasmModule} from './binding/ort-wasm'; import {OrtWasmThreadedModule} from './binding/ort-wasm-threaded'; -import ortWasmFactory from './binding/ort-wasm.js'; -const ortWasmFactoryThreaded: EmscriptenModuleFactory = - // eslint-disable-next-line @typescript-eslint/no-require-imports - !BUILD_DEFS.DISABLE_WASM_THREAD ? require('./binding/ort-wasm-threaded.js') : ortWasmFactory; +/* eslint-disable @typescript-eslint/no-require-imports */ +const ortWasmFactory: EmscriptenModuleFactory = + BUILD_DEFS.DISABLE_WEBGPU ? require('./binding/ort-wasm.js') : require('./binding/ort-wasm-simd.jsep.js'); + +const ortWasmFactoryThreaded: EmscriptenModuleFactory = !BUILD_DEFS.DISABLE_WASM_THREAD ? + (BUILD_DEFS.DISABLE_WEBGPU ? require('./binding/ort-wasm-threaded.js') : + require('./binding/ort-wasm-simd-threaded.jsep.js')) : + ortWasmFactory; +/* eslint-enable @typescript-eslint/no-require-imports */ let wasm: OrtWasmModule|undefined; let initialized = false; @@ -95,10 +100,10 @@ export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise const useThreads = numThreads > 1 && isMultiThreadSupported(); const useSimd = simd && isSimdSupported(); - const wasmPrefixOverride = typeof flags.wasmPaths === 'string' ? flags.wasmPaths : undefined; - const wasmFileName = getWasmFileName(false, useThreads); - const wasmOverrideFileName = getWasmFileName(useSimd, useThreads); - const wasmPathOverride = typeof flags.wasmPaths === 'object' ? flags.wasmPaths[wasmOverrideFileName] : undefined; + const wasmPaths = flags.wasmPaths; + const wasmPrefixOverride = typeof wasmPaths === 'string' ? wasmPaths : undefined; + const wasmFileName = getWasmFileName(useSimd, useThreads); + const wasmPathOverride = typeof wasmPaths === 'object' ? wasmPaths[wasmFileName] : undefined; let isTimeout = false; @@ -130,9 +135,22 @@ export const initializeWebAssembly = async(flags: Env.WebAssemblyFlags): Promise {type: 'text/javascript'})); } - if (fileName === wasmFileName) { - const prefix: string = wasmPrefixOverride ?? scriptDirectory; - return wasmPathOverride ?? prefix + wasmOverrideFileName; + if (fileName.endsWith('.wasm')) { + if (wasmPathOverride) { + return wasmPathOverride; + } + + const prefix = wasmPrefixOverride ?? scriptDirectory; + + if (!BUILD_DEFS.DISABLE_WEBGPU) { + if (wasmFileName === 'ort-wasm-simd.wasm') { + return prefix + 'ort-wasm-simd.jsep.wasm'; + } else if (wasmFileName === 'ort-wasm-simd-threaded.wasm') { + return prefix + 'ort-wasm-simd-threaded.jsep.wasm'; + } + } + + return prefix + wasmFileName; } return scriptDirectory + fileName; diff --git a/js/web/package.json b/js/web/package.json index 9f1c340190..c7d04227bd 100644 --- a/js/web/package.json +++ b/js/web/package.json @@ -66,6 +66,13 @@ "strip-json-comments": "^5.0.0" }, "main": "dist/ort-web.node.js", - "types": "./types/lib/index.d.ts", + "exports": { + ".": { + "node": "./dist/ort-web.node.js", + "default": "./dist/ort.min.js" + }, + "./webgpu": "./dist/ort.webgpu.min.js" + }, + "types": "./types.d.ts", "description": "A Javascript library for running ONNX models on browsers" } diff --git a/js/web/script/pull-prebuilt-wasm-artifacts.ts b/js/web/script/pull-prebuilt-wasm-artifacts.ts index bd6fa1af4f..8c2f24cbf7 100644 --- a/js/web/script/pull-prebuilt-wasm-artifacts.ts +++ b/js/web/script/pull-prebuilt-wasm-artifacts.ts @@ -112,10 +112,14 @@ downloadJson( extractFile(zip, WASM_FOLDER, 'ort-wasm-threaded.wasm', 'Release_wasm'); extractFile(zip, WASM_FOLDER, 'ort-wasm-simd.wasm', 'Release_wasm'); extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.wasm', 'Release_wasm'); + extractFile(zip, WASM_FOLDER, 'ort-wasm-simd.jsep.wasm', 'Release_wasm'); + extractFile(zip, WASM_FOLDER, 'ort-wasm-simd-threaded.jsep.wasm', 'Release_wasm'); extractFile(zip, JS_FOLDER, 'ort-wasm.js', 'Release_wasm'); extractFile(zip, JS_FOLDER, 'ort-wasm-threaded.js', 'Release_wasm'); extractFile(zip, JS_FOLDER, 'ort-wasm-threaded.worker.js', 'Release_wasm'); + extractFile(zip, JS_FOLDER, 'ort-wasm-simd.jsep.js', 'Release_wasm'); + extractFile(zip, JS_FOLDER, 'ort-wasm-simd-threaded.jsep.js', 'Release_wasm'); }); }); }); diff --git a/js/web/types.d.ts b/js/web/types.d.ts new file mode 100644 index 0000000000..c6cff64c8a --- /dev/null +++ b/js/web/types.d.ts @@ -0,0 +1,10 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +declare module 'onnxruntime-web' { + export * from 'onnxruntime-common'; +} + +declare module 'onnxruntime-web/webgpu' { + export * from 'onnxruntime-web'; +} diff --git a/js/web/webpack.config.js b/js/web/webpack.config.js index 1c842ddced..85d6ac3381 100644 --- a/js/web/webpack.config.js +++ b/js/web/webpack.config.js @@ -57,7 +57,7 @@ function defaultTerserPluginOptions(target) { const DEFAULT_BUILD_DEFS = { DISABLE_WEBGL: false, - DISABLE_WEBGPU: false, + DISABLE_WEBGPU: true, DISABLE_WASM: false, DISABLE_WASM_PROXY: false, DISABLE_WASM_THREAD: false, @@ -211,7 +211,8 @@ function buildTestRunnerConfig({ format = 'umd', target = 'es2017', mode = 'production', - devtool = 'source-map' + devtool = 'source-map', + build_defs = DEFAULT_BUILD_DEFS }) { const config = { target: ['web', target], @@ -244,7 +245,7 @@ function buildTestRunnerConfig({ } }, plugins: [ - new webpack.DefinePlugin({ BUILD_DEFS: DEFAULT_BUILD_DEFS }), + new webpack.DefinePlugin({ BUILD_DEFS: build_defs }), new webpack.WatchIgnorePlugin({ paths: [/\.js$/, /\.d\.ts$/] }), new NodePolyfillPlugin({ excludeAliases: ["console", "Buffer"] @@ -315,6 +316,13 @@ module.exports = () => { DISABLE_WASM_THREAD: true, } }), + // ort.webgpu.min.js + buildOrtConfig({ + suffix: '.webgpu.min', build_defs: { + ...DEFAULT_BUILD_DEFS, + DISABLE_WEBGPU: false, + } + }), // ort-web.min.js buildOrtWebConfig({ suffix: '.min' }), @@ -333,10 +341,20 @@ module.exports = () => { ); break; case 'dev': - builds.push(buildTestRunnerConfig({ suffix: '.dev', mode: 'development', devtool: 'inline-source-map' })); + builds.push(buildTestRunnerConfig({ + suffix: '.dev', mode: 'development', devtool: 'inline-source-map', build_defs: { + ...DEFAULT_BUILD_DEFS, + DISABLE_WEBGPU: false, + } + })); break; case 'perf': - builds.push(buildTestRunnerConfig({ suffix: '.perf' })); + builds.push(buildTestRunnerConfig({ + suffix: '.perf', build_defs: { + ...DEFAULT_BUILD_DEFS, + DISABLE_WEBGPU: false, + } + })); break; default: throw new Error(`unsupported bundle mode: ${bundleMode}`); 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 1b3ec6af24..f860251737 100644 --- a/tools/ci_build/github/azure-pipelines/templates/web-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/web-ci.yml @@ -61,6 +61,7 @@ stages: BuildConfig: 'Debug' ExtraBuildArgs: '--use_extensions --cmake_extra_defines onnxruntime_WEBASSEMBLY_DEFAULT_EXTENSION_FLAGS=ON ${{ parameters.ExtraBuildArgs }}' PoolName: ${{ parameters.PoolName }} + BuildJsep: ${{ parameters.BuildJsep }} - stage: Build_web_Debug dependsOn: Build_wasm_Debug diff --git a/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml b/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml index 94c6bc0abf..e6797b0737 100644 --- a/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml +++ b/tools/ci_build/github/azure-pipelines/templates/win-wasm-ci.yml @@ -104,14 +104,14 @@ jobs: displayName: 'Build (simd + JSEP)' inputs: scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)\wasm_simd_jsep --enable_wasm_simd --use_jsep --target onnxruntime_webassembly' + arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)\wasm_simd_jsep --enable_wasm_simd --use_jsep --target onnxruntime_webassembly --skip_tests' workingDirectory: '$(Build.BinariesDirectory)' - ${{ if eq(parameters.BuildJsep, true) }}: - task: PythonScript@0 displayName: 'Build (simd + threads + JSEP)' inputs: scriptPath: '$(Build.SourcesDirectory)\tools\ci_build\build.py' - arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)\wasm_simd_threads_jsep --enable_wasm_simd --enable_wasm_threads --use_jsep --target onnxruntime_webassembly' + arguments: '$(CommonBuildArgs) --build_dir $(Build.BinariesDirectory)\wasm_simd_threads_jsep --enable_wasm_simd --enable_wasm_threads --use_jsep --target onnxruntime_webassembly --skip_tests' workingDirectory: '$(Build.BinariesDirectory)' - ${{ if eq(parameters.SkipPublish, false) }}: - script: |