Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions cmake/onnxruntime_providers_webgpu.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@
if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
message(FATAL_ERROR "WebGPU EP shared library build is not supported on Emscripten. Please use static library build.")
endif()

# Configure precompiled headers for shared library build
# PCH ensures ep/_pch.h is included first and improves compilation speed
target_precompile_headers(onnxruntime_providers_webgpu PRIVATE
"${REPO_ROOT}/include/onnxruntime/ep/_pch.h"
)
endif()

set_target_properties(onnxruntime_providers_webgpu PROPERTIES CXX_STANDARD_REQUIRED ON)
Expand Down
13 changes: 13 additions & 0 deletions cmake/onnxruntime_unittests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,18 @@ function(onnxruntime_apply_test_target_workarounds target)
endif()
endfunction()

# Set environment variables for plugin EP tests when run via CTest.
function(onnxruntime_set_plugin_ep_test_environment target)
if(onnxruntime_USE_WEBGPU AND NOT onnxruntime_BUILD_WEBGPU_EP_STATIC_LIB)
set(ORT_PLUGIN_EP_JSON_CONFIG "{\"ep_library_registration_name\": \"WebGPU_PluginEP\", \"ep_library_path\": \"onnxruntime_providers_webgpu.dll\", \"selected_ep_name\": \"WebGpuExecutionProvider\"}")
set_tests_properties(${target} PROPERTIES
ENVIRONMENT "ORT_UNIT_TEST_MAIN_DYNAMIC_PLUGIN_EP_CONFIG_JSON=${ORT_PLUGIN_EP_JSON_CONFIG}"
)
# TODO: add for other plugin EPs if needed
# elseif()
endif()
endfunction()

function(onnxruntime_apply_emscripten_test_link_settings target)
if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
set_target_properties(${target} PROPERTIES LINK_DEPENDS ${TEST_SRC_DIR}/wasm/onnxruntime_test_adapter.js)
Expand Down Expand Up @@ -1239,6 +1251,7 @@ block()
)

onnxruntime_apply_test_target_workarounds(onnxruntime_provider_test)
onnxruntime_set_plugin_ep_test_environment(onnxruntime_provider_test)

# Expose QNN SDK headers to unit tests via an interface target
if(onnxruntime_USE_QNN)
Expand Down
7 changes: 7 additions & 0 deletions include/onnxruntime/ep/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## EP adapter

This folder contains a set of C++ header files. They are used specifically for allowing ONNX Runtime internal kernel-based EPs to use the plugin-style EP API while keep minimal changes to existing code.

### Usage

Make sure to include "ep/_pch.h" for all source code in the implementation. Using PCH compiler flag is recommended.
61 changes: 61 additions & 0 deletions include/onnxruntime/ep/_pch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#include "api.h"

Check warning on line 6 in include/onnxruntime/ep/_pch.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Include the directory when naming header files [build/include_subdir] [4] Raw Output: include/onnxruntime/ep/_pch.h:6: Include the directory when naming header files [build/include_subdir] [4]
#include "common.h"

Check warning on line 7 in include/onnxruntime/ep/_pch.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Include the directory when naming header files [build/include_subdir] [4] Raw Output: include/onnxruntime/ep/_pch.h:7: Include the directory when naming header files [build/include_subdir] [4]

// This header is only used when building WebGPU/CUDA EP as a shared library.
//
// This header file is used as a precompiled header so it is always included first.

#pragma push_macro("ORT_EP_API_ADAPTER_HEADER_INCLUDED")
#define ORT_EP_API_ADAPTER_HEADER_INCLUDED

#include "adapter/allocator.h"
#include "adapter/logging.h"
#include "adapter/ep.h"
#include "adapter/kernel_registry.h"

#pragma pop_macro("ORT_EP_API_ADAPTER_HEADER_INCLUDED")

//
// EP specific using declarations
//

#define EP_SPECIFIC_USING_DECLARATIONS \
using FuncManager = onnxruntime::ep::adapter::FuncManager; \
using KernelCreatePtrFn = onnxruntime::ep::adapter::KernelCreatePtrFn; \
using KernelDefBuilder = onnxruntime::ep::adapter::KernelDefBuilder; \
using KernelRegistry = onnxruntime::ep::adapter::KernelRegistry; \
using KernelCreateInfo = onnxruntime::ep::adapter::KernelCreateInfo; \
using BuildKernelCreateInfoFn = onnxruntime::ep::adapter::KernelCreateInfo (*)(); \
using OpKernelInfo = onnxruntime::ep::adapter::OpKernelInfo; \
using OpKernelContext = onnxruntime::ep::adapter::OpKernelContext; \
using OpKernel = onnxruntime::ep::adapter::OpKernel; \
using DataTransferManager = onnxruntime::ep::adapter::DataTransferManager; \
namespace logging { \
using Logger = onnxruntime::ep::adapter::Logger; \
}

namespace onnxruntime {
namespace webgpu {
EP_SPECIFIC_USING_DECLARATIONS
} // namespace webgpu
namespace cuda {
EP_SPECIFIC_USING_DECLARATIONS
} // namespace cuda

#ifndef DISABLE_CONTRIB_OPS
namespace contrib {
namespace webgpu {
EP_SPECIFIC_USING_DECLARATIONS
} // namespace webgpu
namespace cuda {
EP_SPECIFIC_USING_DECLARATIONS
} // namespace cuda
} // namespace contrib
#endif

} // namespace onnxruntime
47 changes: 47 additions & 0 deletions include/onnxruntime/ep/adapter/allocator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#include "core/framework/allocator.h"

namespace onnxruntime {
namespace ep {
namespace adapter {

/// <summary>
/// A bridge class between the EP API OrtAllocator and an IAllocator implementation.
/// </summary>
class Allocator : public OrtAllocator {
public:
explicit Allocator(const OrtMemoryInfo* memory_info, AllocatorPtr impl)
: OrtAllocator{}, memory_info_(memory_info), impl_(impl) {
version = ORT_API_VERSION;
Alloc = AllocImpl;
Free = FreeImpl;
Info = InfoImpl;
}

private:
static void* ORT_API_CALL AllocImpl(OrtAllocator* this_ptr, size_t size) noexcept {
auto* allocator = static_cast<Allocator*>(this_ptr);
return allocator->impl_->Alloc(size);
}

static void ORT_API_CALL FreeImpl(OrtAllocator* this_ptr, void* p) noexcept {
auto* allocator = static_cast<Allocator*>(this_ptr);
allocator->impl_->Free(p);
}

static const OrtMemoryInfo* ORT_API_CALL InfoImpl(const OrtAllocator* this_ptr) noexcept {
auto* allocator = static_cast<const Allocator*>(this_ptr);
return allocator->memory_info_;
}

const OrtMemoryInfo* memory_info_;
AllocatorPtr impl_;
};

} // namespace adapter
} // namespace ep
} // namespace onnxruntime
54 changes: 54 additions & 0 deletions include/onnxruntime/ep/adapter/data_transfer_manager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED)
#error "This header should not be included directly. Include ep/_pch.h instead."
#endif

#include "core/common/status.h"
#include "core/common/common.h"
#include "core/framework/data_transfer.h"
#include "core/framework/tensor.h"

namespace onnxruntime {
namespace ep {
namespace adapter {

/// <summary>
/// An adapter class partially implementing the facade of `onnxruntime::DataTransferManager`.
/// </summary>
struct DataTransferManager {
explicit DataTransferManager(std::unique_ptr<IDataTransfer> impl) : impl_{std::move(impl)} {}

Check warning on line 23 in include/onnxruntime/ep/adapter/data_transfer_manager.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Add #include <utility> for move [build/include_what_you_use] [4] Raw Output: include/onnxruntime/ep/adapter/data_transfer_manager.h:23: Add #include <utility> for move [build/include_what_you_use] [4]

common::Status CopyTensor(const Tensor& src, Tensor& dst) const {
if (src.Shape().Size() != dst.Shape().Size()) {
return ORT_MAKE_STATUS(ONNXRUNTIME,
FAIL,
"Tensor size mismatch: source tensor size is ",
src.Shape().Size(),
", destination tensor size is ",
dst.Shape().Size());
}

if (impl_->CanCopy(src.Location().device, dst.Location().device)) {
return impl_->CopyTensor(src, dst);
}

return ORT_MAKE_STATUS(ONNXRUNTIME,
FAIL,
"There's no data transfer registered for copying tensors from ",
src.Location().device.ToString(),
" to ",
dst.Location().device.ToString());
}

private:
ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(DataTransferManager);
std::unique_ptr<IDataTransfer> impl_;

Check warning on line 49 in include/onnxruntime/ep/adapter/data_transfer_manager.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Add #include <memory> for unique_ptr<> [build/include_what_you_use] [4] Raw Output: include/onnxruntime/ep/adapter/data_transfer_manager.h:49: Add #include <memory> for unique_ptr<> [build/include_what_you_use] [4]
};

} // namespace adapter
} // namespace ep
} // namespace onnxruntime
58 changes: 58 additions & 0 deletions include/onnxruntime/ep/adapter/ep.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED)
#error "This header should not be included directly. Include ep/_pch.h instead."
#endif

#include "data_transfer_manager.h"

Check warning on line 10 in include/onnxruntime/ep/adapter/ep.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Include the directory when naming header files [build/include_subdir] [4] Raw Output: include/onnxruntime/ep/adapter/ep.h:10: Include the directory when naming header files [build/include_subdir] [4]

#include "core/framework/execution_provider.h"

namespace onnxruntime {
namespace ep {
namespace adapter {

/// <summary>
/// Wrapper around IExecutionProvider to expose via OrtEp.
/// </summary>
class Ep : public OrtEp {
protected:
explicit Ep(IExecutionProvider* impl, AllocatorPtr temp_space_cpu_allocator, AllocatorPtr temp_space_allocator)
: OrtEp{},
impl_(impl),
data_transfer_manager_{impl->GetDataTransfer()},
profiler_{impl->GetProfiler()},
temp_space_cpu_allocator_{temp_space_cpu_allocator},
temp_space_allocator_{temp_space_allocator} {
}

public:
inline IExecutionProvider* EpImpl() const noexcept {
return impl_.get();
}
inline const DataTransferManager& GetDataTransferManager() const noexcept {
return data_transfer_manager_;
}
[[nodiscard]] Status GetTempSpaceCPUAllocator(AllocatorPtr* output) const {
*output = temp_space_cpu_allocator_;
return Status::OK();
}
[[nodiscard]] Status GetTempSpaceAllocator(AllocatorPtr* output) const {
*output = temp_space_allocator_;
return Status::OK();
}

private:
std::unique_ptr<IExecutionProvider> impl_;
DataTransferManager data_transfer_manager_;
std::unique_ptr<profiling::EpProfiler> profiler_;

Check warning on line 51 in include/onnxruntime/ep/adapter/ep.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Add #include <memory> for unique_ptr<> [build/include_what_you_use] [4] Raw Output: include/onnxruntime/ep/adapter/ep.h:51: Add #include <memory> for unique_ptr<> [build/include_what_you_use] [4]
AllocatorPtr temp_space_cpu_allocator_;
AllocatorPtr temp_space_allocator_;
};

} // namespace adapter
} // namespace ep
} // namespace onnxruntime
37 changes: 37 additions & 0 deletions include/onnxruntime/ep/adapter/kernel_def.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED)
#error "This header should not be included directly. Include ep/_pch.h instead."
#endif

#include <memory>

namespace onnxruntime {
namespace ep {
namespace adapter {

/// <summary>
/// An adapter class partially implementing the facade of `onnxruntime::KernelDef`.
/// </summary>
class KernelDef {
public:
explicit KernelDef(const OrtKernelInfo* kernel_info) : kernel_info_{kernel_info} {}

const std::string OpName() const {
return kernel_info_.GetNodeName();
}

const std::string Domain() const {

Check warning on line 27 in include/onnxruntime/ep/adapter/kernel_def.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Add #include <string> for string [build/include_what_you_use] [4] Raw Output: include/onnxruntime/ep/adapter/kernel_def.h:27: Add #include <string> for string [build/include_what_you_use] [4]
return kernel_info_.GetOperatorDomain();
}

private:
const Ort::ConstKernelInfo kernel_info_;
};

} // namespace adapter
} // namespace ep
} // namespace onnxruntime
Loading
Loading