Skip to content

Commit

Permalink
Initial changes to support wasm64.
Browse files Browse the repository at this point in the history
  • Loading branch information
satyajandhyala committed Jul 5, 2024
1 parent 8c26898 commit 4e5cd1d
Show file tree
Hide file tree
Showing 16 changed files with 133 additions and 58 deletions.
1 change: 1 addition & 0 deletions cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ option(onnxruntime_WEBASSEMBLY_RUN_TESTS_IN_BROWSER "Enable this option to run t
option(onnxruntime_ENABLE_WEBASSEMBLY_DEBUG_INFO "Enable this option to turn on DWARF format debug info" OFF)
option(onnxruntime_ENABLE_WEBASSEMBLY_PROFILING "Enable this option to turn on WebAssembly profiling and preserve function names" OFF)
option(onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL "Enable this option to allow WebAssembly to output optimized model" OFF)
option(onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64 "Enable this option to allow WebAssembly to use 64bit memory" OFF)

# Enable bitcode for iOS
option(onnxruntime_ENABLE_BITCODE "Enable bitcode for iOS only" OFF)
Expand Down
12 changes: 10 additions & 2 deletions cmake/adjust_global_compile_flags.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
endif()

if (onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING)
string(APPEND CMAKE_C_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0")
string(APPEND CMAKE_CXX_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0")
string(APPEND CMAKE_C_FLAGS " -fwasm-exceptions")
string(APPEND CMAKE_CXX_FLAGS " -fwasm-exceptions")
# string(APPEND CMAKE_C_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0")
# string(APPEND CMAKE_CXX_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0")
endif()

# Build WebAssembly with multi-threads support.
Expand All @@ -63,6 +65,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
endif()
endif()

# Build WebAssembly with 64bit support.
if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64)
string(APPEND CMAKE_C_FLAGS " -sMEMORY64 -Wno-experimental")
string(APPEND CMAKE_CXX_FLAGS " -sMEMORY64 -Wno-experimental")
endif()

if (onnxruntime_EXTERNAL_TRANSFORMER_SRC_PATH)
add_definitions(-DORT_TRAINING_EXTERNAL_GRAPH_TRANSFORMERS=1)
endif()
Expand Down
65 changes: 57 additions & 8 deletions cmake/onnxruntime_webassembly.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,9 @@ else()
"${ONNXRUNTIME_ROOT}/wasm/api.cc"
"${ONNXRUNTIME_ROOT}/core/session/onnxruntime_c_api.cc"
)
set (WASM_API_EXCEPTION_CATCHING "-s DISABLE_EXCEPTION_CATCHING=0")
message(STATUS "onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING_ON_API set")
set_source_files_properties(${onnxruntime_webassembly_src_exc} PROPERTIES COMPILE_FLAGS ${WASM_API_EXCEPTION_CATCHING})
# set (WASM_API_EXCEPTION_CATCHING "-s DISABLE_EXCEPTION_CATCHING=0")
# message(STATUS "onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING_ON_API set")
# set_source_files_properties(${onnxruntime_webassembly_src_exc} PROPERTIES COMPILE_FLAGS ${WASM_API_EXCEPTION_CATCHING})
endif()

target_link_libraries(onnxruntime_webassembly PRIVATE
Expand All @@ -193,7 +193,7 @@ else()
re2::re2
)

set(EXPORTED_RUNTIME_METHODS "'stackAlloc','stackRestore','stackSave','UTF8ToString','stringToUTF8','lengthBytesUTF8'")
set(EXPORTED_RUNTIME_METHODS "'stackAlloc','stackRestore','stackSave','UTF8ToString','stringToUTF8','lengthBytesUTF8','setValue','getValue','FS'")

if (onnxruntime_USE_XNNPACK)
target_link_libraries(onnxruntime_webassembly PRIVATE XNNPACK)
Expand All @@ -215,18 +215,63 @@ else()
set(EXPORTED_FUNCTIONS "_malloc,_free")
endif()

if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64)
set(MAXIMUM_MEMORY "17179869184")
target_link_options(onnxruntime_webassembly PRIVATE
"SHELL:-s MEMORY64=1"
)
string(APPEND CMAKE_C_FLAGS " -sMEMORY64 -Wno-experimental")
string(APPEND CMAKE_CXX_FLAGS " -sMEMORY64 -Wno-experimental")
set(SMEMORY_FLAG "-sMEMORY64")

target_compile_options(onnx PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_common PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_session PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_framework PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(nsync_cpp PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(nsync_cpp PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnx_proto PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(protoc PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(libprotobuf-lite PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_providers PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_optimizer PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_mlas PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_optimizer PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_graph PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_flatbuffers PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(onnxruntime_util PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(re2 PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(absl_base PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(absl_hash PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(absl_raw_hash_set PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(absl_throw_delegate PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(absl_city PRIVATE ${SMEMORY_FLAG} -Wno-experimental)
target_compile_options(absl_low_level_hash PRIVATE ${SMEMORY_FLAG} -Wno-experimental)

target_link_options(onnxruntime_webassembly PRIVATE
--post-js "${ONNXRUNTIME_ROOT}/wasm/js_post_js_64.js"
)
else ()
set(MAXIMUM_MEMORY "4294967296")
target_link_options(onnxruntime_webassembly PRIVATE
--post-js "${ONNXRUNTIME_ROOT}/wasm/js_post_js.js"
)
endif ()

target_link_options(onnxruntime_webassembly PRIVATE
"SHELL:-s EXPORTED_RUNTIME_METHODS=[${EXPORTED_RUNTIME_METHODS}]"
"SHELL:-s EXPORTED_FUNCTIONS=${EXPORTED_FUNCTIONS}"
"SHELL:-s MAXIMUM_MEMORY=4294967296"
"SHELL:-s MAXIMUM_MEMORY=${MAXIMUM_MEMORY}"
"SHELL:-s EXIT_RUNTIME=0"
"SHELL:-s ALLOW_MEMORY_GROWTH=1"
"SHELL:-s MODULARIZE=1"
"SHELL:-s EXPORT_ALL=0"
"SHELL:-s VERBOSE=0"
"SHELL:-s FILESYSTEM=0"
"SHELL:-s FILESYSTEM=1"
"SHELL:-s INCOMING_MODULE_JS_API=[preRun,locateFile,arguments,onExit,wasmMemory,buffer,instantiateWasm,mainScriptUrlOrBlob]"
"SHELL:-s WASM_BIGINT=1"
"SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=0"
"SHELL:-s SIGNATURE_CONVERSIONS=OrtRun:_pppppppp,OrtGetTensorData:_ppppp,OrtCreateTensor:p_pppp,OrtCreateSession:pppp,OrtReleaseSession:_p,OrtGetInputOutputCount:pppp,OrtCreateSessionOptions:pp__p_ppppp,OrtAddSessionConfigEntry:pppp,OrtReleaseSessionOptions:_p,OrtAppendExecutionProvider:ppp,OrtAddSessionConfigEntry:pppp,OrtGetInputName:ppp,OrtGetOutputName:ppp,OrtCreateRunOptions:ppp_p,OrtReleaseRunOptions:pp,OrtReleaseTensor:_p,OrtFree:_p,OrtGetLastError:_pp,JsepOutput:pp_p"
${WASM_API_EXCEPTION_CATCHING}
--no-entry
"SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre.js\""
Expand All @@ -241,8 +286,11 @@ else()
target_compile_definitions(onnxruntime_webassembly PRIVATE USE_JSEP=1)
target_link_options(onnxruntime_webassembly PRIVATE
"SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js\""
"SHELL:-s ASYNCIFY=1"
"SHELL:-s ASYNCIFY=2"
"SHELL:-s JSPI"
"SHELL:-s ASYNCIFY_IGNORE_INDIRECT=1"
"SHELL:-s ASYNCIFY_STACK_SIZE=65536"
"SHELL:-s ASYNCIFY_EXPORTS=['OrtRun']"
)
set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js)
endif()
Expand Down Expand Up @@ -279,7 +327,8 @@ else()
endif()

# Set link flag to enable exceptions support, this will override default disabling exception throwing behavior when disable exceptions.
target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s DISABLE_EXCEPTION_THROWING=0")
# target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s DISABLE_EXCEPTION_THROWING=0")
# target_link_options(onnxruntime_webassembly PRIVATE "-fwasm-exceptions")

if (onnxruntime_ENABLE_WEBASSEMBLY_PROFILING)
target_link_options(onnxruntime_webassembly PRIVATE --profiling --profiling-funcs)
Expand Down
8 changes: 4 additions & 4 deletions js/web/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ if (!BUILD_DEFS.DISABLE_WASM) {
const wasmBackend = BUILD_DEFS.DISABLE_TRAINING ? require('./backend-wasm-inference').wasmBackend :
require('./backend-wasm-training').wasmBackend;
if (!BUILD_DEFS.DISABLE_JSEP) {
registerBackend('webgpu', wasmBackend, 5);
registerBackend('webnn', wasmBackend, 5);
registerBackend('webgpu', wasmBackend, 1);
registerBackend('webnn', wasmBackend, 1);
}
registerBackend('cpu', wasmBackend, 10);
registerBackend('wasm', wasmBackend, 10);
registerBackend('cpu', wasmBackend, 1);
registerBackend('wasm', wasmBackend, 1);
}

Object.defineProperty(env.versions, 'web', {value: version, enumerable: true});
43 changes: 24 additions & 19 deletions js/web/lib/wasm/jsep/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

import {Env} from 'onnxruntime-common';

import type {OrtWasmModule} from '../wasm-types';
import {DataType, getTensorElementSize} from '../wasm-common';
import type {OrtWasmModule} from '../wasm-types';

import {WebGpuBackend} from './backend-webgpu';
import {LOG_DEBUG} from './log';
Expand Down Expand Up @@ -68,24 +68,24 @@ class ComputeContextImpl implements ComputeContext {
private customDataSize = 0;
constructor(private module: OrtWasmModule, private backend: WebGpuBackend, contextDataOffset: number) {
this.adapterInfo = backend.adapterInfo;
const heapU32 = module.HEAPU32;
const heap = module.PTR_SIZE === 4 ? module.HEAPU32 : module.HEAPU64;

// extract context data
let dataIndex = (contextDataOffset >>> 2);
this.opKernelContext = heapU32[dataIndex++];
const inputCount = heapU32[dataIndex++];
this.outputCount = heapU32[dataIndex++];
this.customDataOffset = heapU32[dataIndex++];
this.customDataSize = heapU32[dataIndex++];
let dataIndex = module.PTR_SIZE === 8 ? (contextDataOffset / 2 ** 3) : (contextDataOffset >> 2);
this.opKernelContext = Number(heap[dataIndex++]);
const inputCount = Number(heap[dataIndex++]);
this.outputCount = Number(heap[dataIndex++]);
this.customDataOffset = Number(heap[dataIndex++]);
this.customDataSize = Number(heap[dataIndex++]);

const inputs: TensorView[] = [];
for (let i = 0; i < inputCount; i++) {
const dataType = heapU32[dataIndex++];
const data = heapU32[dataIndex++];
const dim = heapU32[dataIndex++];
const dataType = Number(heap[dataIndex++]);
const data = Number(heap[dataIndex++]);
const dim = Number(heap[dataIndex++]);
const dims: number[] = [];
for (let d = 0; d < dim; d++) {
dims.push(heapU32[dataIndex++]);
dims.push(Number(heap[dataIndex++]));
}
inputs.push(new TensorViewImpl(module, dataType, data, dims));
}
Expand Down Expand Up @@ -127,11 +127,11 @@ class ComputeContextImpl implements ComputeContext {
output(index: number, dims: readonly number[]): number {
const stack = this.module.stackSave();
try {
const data = this.module.stackAlloc((1 + dims.length) * 4 /* sizeof(size_t) */);
let offset = data >> 2;
this.module.HEAPU32[offset++] = dims.length;
const ptrSize = this.module.PTR_SIZE;
const data = this.module.stackAlloc((1 + dims.length) * ptrSize /* sizeof(size_t) */);
this.module.setValue(data, dims.length, '*');
for (let i = 0; i < dims.length; i++) {
this.module.HEAPU32[offset++] = dims[i];
this.module.setValue(data + ptrSize * (i + 1), dims[i], '*');
}
return this.module._JsepOutput!(this.opKernelContext, index, data);
} catch (e) {
Expand Down Expand Up @@ -193,10 +193,15 @@ export const init =
// jsepCopy(src, dst, size, isSourceGpu)
(src: number, dst: number, size: number, isSourceGpu = false) => {
if (isSourceGpu) {
LOG_DEBUG('verbose', () => `[WebGPU] jsepCopyGpuToGpu: src=${src}, dst=${dst}, size=${size}`);
LOG_DEBUG(
'verbose',
() => `[WebGPU] jsepCopyGpuToGpu: src=${Number(src)}, dst=${Number(dst)}, size=${Number(size)}`);
backend.memcpy(src, dst);
} else {
LOG_DEBUG('verbose', () => `[WebGPU] jsepCopyCpuToGpu: dataOffset=${src}, gpuDataId=${dst}, size=${size}`);
LOG_DEBUG(
'verbose',
() => `[WebGPU] jsepCopyCpuToGpu: dataOffset=${Number(src)}, gpuDataId=${Number(dst)}, size=${
Number(size)}`);
const data = module.HEAPU8.subarray(src >>> 0, (src >>> 0) + size);
backend.upload(dst, data);
}
Expand Down Expand Up @@ -226,7 +231,7 @@ export const init =
'verbose',
() => `[WebGPU] jsepRun: sessionHandle=${sessionHandle}, kernel=${kernel}, contextDataOffset=${
contextDataOffset}`);
const context = new ComputeContextImpl(module, backend, contextDataOffset);
const context = new ComputeContextImpl(module, backend, Number(contextDataOffset));
return backend.computeKernel(kernel, context, errors);
},
// jsepCaptureBegin
Expand Down
7 changes: 4 additions & 3 deletions js/web/lib/wasm/jsep/webgpu/gpu-data-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const bucketArr: number[] = [];
/**
* normalize the buffer size so that it fits the 128-bits (16 bytes) alignment.
*/
const calcNormalizedBufferSize = (size: number) => Math.ceil(size / 16) * 16;
const calcNormalizedBufferSize = (size: number) => Math.ceil(Number(size) / 16) * 16;

/**
* calculate the buffer size so that it fits into buckets.
Expand Down Expand Up @@ -342,7 +342,7 @@ class GpuDataManagerImpl implements GpuDataManager {
}

const gpuData = {id: createNewGpuDataId(), type: GpuDataType.default, buffer: gpuBuffer};
this.storageCache.set(gpuData.id, {gpuData, originalSize: size});
this.storageCache.set(gpuData.id, {gpuData, originalSize: Number(size)});

LOG_DEBUG('verbose', () => `[WebGPU] GpuDataManager.create(size=${size}) => id=${gpuData.id}`);
return gpuData;
Expand All @@ -352,7 +352,8 @@ class GpuDataManagerImpl implements GpuDataManager {
return this.storageCache.get(id)?.gpuData;
}

release(id: GpuDataId): number {
release(idInput: GpuDataId): number {
const id = typeof idInput === 'bigint' ? Number(idInput) : idInput;
const cachedData = this.storageCache.get(id);
if (!cachedData) {
throw new Error('releasing data does not exist');
Expand Down
11 changes: 11 additions & 0 deletions js/web/lib/wasm/wasm-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,26 @@ export interface OrtTrainingAPIs {
_OrtTrainingReleaseSession(trainingHandle: number): void;
}

export type FSNode = {
contents: Uint8Array;
usedBytes: number;
}

/**
* The interface of the WebAssembly module for ONNX Runtime, compiled from C++ source code by Emscripten.
*/
export interface OrtWasmModule extends EmscriptenModule, OrtInferenceAPIs, Partial<OrtTrainingAPIs>,
Partial<JSEP.Module> {
HEAP64: BigInt64Array;
HEAPU64: BigUint64Array;
PTR_SIZE: number;
FS: {create(path: string): FSNode; chdir(path: string): void; unlink(path: string|FSNode): void};
// #region emscripten functions
stackSave(): number;
stackRestore(stack: number): void;
stackAlloc(size: number): number;
getValue(ptr: number, type: string): number;
setValue(ptr: number, value: number, type: string): void;

UTF8ToString(offset: number, maxBytesToRead?: number): string;
lengthBytesUTF8(str: string): number;
Expand Down
22 changes: 11 additions & 11 deletions onnxruntime/core/providers/js/js_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,16 @@ class JsKernel : public OpKernel {
temp_data_size += sizeof(size_t) * 3;
}
}
uint32_t* p_serialized_kernel_context = reinterpret_cast<uint32_t*>(alloc->Alloc(temp_data_size));
uintptr_t* p_serialized_kernel_context = reinterpret_cast<uintptr_t*>(alloc->Alloc(temp_data_size));
if (p_serialized_kernel_context == nullptr) {
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Failed to allocate memory for serialized kernel context.");
}

p_serialized_kernel_context[0] = reinterpret_cast<uint32_t>(context);
p_serialized_kernel_context[1] = static_cast<uint32_t>(context->InputCount());
p_serialized_kernel_context[2] = static_cast<uint32_t>(context->OutputCount());
p_serialized_kernel_context[3] = reinterpret_cast<uint32_t>(custom_data_ptr);
p_serialized_kernel_context[4] = static_cast<uint32_t>(custom_data_size);
p_serialized_kernel_context[0] = reinterpret_cast<uintptr_t>(context);
p_serialized_kernel_context[1] = static_cast<uintptr_t>(context->InputCount());
p_serialized_kernel_context[2] = static_cast<uintptr_t>(context->OutputCount());
p_serialized_kernel_context[3] = reinterpret_cast<uintptr_t>(custom_data_ptr);
p_serialized_kernel_context[4] = static_cast<uintptr_t>(custom_data_size);
size_t index = 5;
for (int i = 0; i < context->InputCount(); i++) {
const auto* input_ptr = context->Input<Tensor>(i);
Expand All @@ -130,11 +130,11 @@ class JsKernel : public OpKernel {
p_serialized_kernel_context[index++] = 0;
continue;
}
p_serialized_kernel_context[index++] = static_cast<uint32_t>(input_ptr->GetElementType());
p_serialized_kernel_context[index++] = reinterpret_cast<uint32_t>(input_ptr->DataRaw());
p_serialized_kernel_context[index++] = static_cast<uint32_t>(input_ptr->Shape().NumDimensions());
p_serialized_kernel_context[index++] = static_cast<uintptr_t>(input_ptr->GetElementType());
p_serialized_kernel_context[index++] = reinterpret_cast<uintptr_t>(input_ptr->DataRaw());
p_serialized_kernel_context[index++] = static_cast<uintptr_t>(input_ptr->Shape().NumDimensions());
for (size_t d = 0; d < input_ptr->Shape().NumDimensions(); d++) {
p_serialized_kernel_context[index++] = static_cast<uint32_t>(input_ptr->Shape()[d]);
p_serialized_kernel_context[index++] = static_cast<uintptr_t>(input_ptr->Shape()[d]);
}
}

Expand Down Expand Up @@ -201,7 +201,7 @@ class JsKernel : public OpKernel {

int status_code = EM_ASM_INT(
{ return Module.jsepRunKernel($0, $1, Module.jsepSessionState.sessionHandle, Module.jsepSessionState.errors); },
this, reinterpret_cast<uint32_t>(p_serialized_kernel_context));
this, reinterpret_cast<uintptr_t>(p_serialized_kernel_context));

LOGS_DEFAULT(VERBOSE) << "outputs = " << context->OutputCount() << ". Y.data="
<< (size_t)(context->Output<Tensor>(0)->DataRaw()) << ".";
Expand Down
2 changes: 1 addition & 1 deletion onnxruntime/core/providers/js/operators/reduce.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace js {
JSEP_INIT_KERNEL_ATTRIBUTE(ReduceKernel, ({ \
"keepDims" : !!$1, \
"noopWithEmptyAxes" : !!$2, \
"axes" : $3 ? (Array.from(HEAP32.subarray($3, $4))) : [], \
"axes" : $3 ? (Array.from(HEAP32.subarray($3, Number($4)))) : [], \
}), \
static_cast<int32_t>(keepdims_), \
static_cast<int32_t>(noop_with_empty_axes_), \
Expand Down
2 changes: 1 addition & 1 deletion onnxruntime/core/providers/js/operators/resize.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Resize : public JsKernel, public UpsampleBase {
std::transform(axes_.begin(), axes_.end(), std::back_inserter(axes), [](auto& axis) { return gsl::narrow_cast<int32_t>(axis); });
JSEP_INIT_KERNEL_ATTRIBUTE(Resize, ({
"antialias" : $1,
"axes" : $2 ? Array.from(HEAP32.subarray($2, $3)) : [],
"axes" : $2 ? Array.from(HEAP32.subarray($2, Number($3))) : [],
"coordinateTransformMode" : UTF8ToString($4),
"cubicCoeffA" : $5,
"excludeOutside" : $6,
Expand Down
Loading

0 comments on commit 4e5cd1d

Please sign in to comment.