[Plugin EP] Add plugin EP APIs to retrieve ONNX operator schemas#27713
[Plugin EP] Add plugin EP APIs to retrieve ONNX operator schemas#27713adrianlizarraga merged 26 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds plugin Execution Provider (EP) APIs (C and C++) to query ONNX operator schemas from the global ONNX schema registry, along with unit tests validating the new wrapper behavior.
Changes:
- Extend
OrtEpApiwith functions to look up an ONNXOpSchemaand query basic schema metadata (since_version, inputs/outputs, type constraints). - Add C++ wrapper types/functions (
Ort::ConstOpSchema,Ort::GetOpSchema) over the newOrtEpApischema functions. - Add unit tests covering successful/unsuccessful schema lookup and basic schema property queries.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| onnxruntime/test/framework/ep_plugin_provider_test.cc | Adds unit tests for the new C++ OpSchema wrapper and lookup function. |
| onnxruntime/core/session/plugin_ep/ep_api.h | Declares new plugin EP API entry points for OpSchema lookup and metadata access. |
| onnxruntime/core/session/plugin_ep/ep_api.cc | Implements the OpSchema APIs using the ONNX schema registry and appends them to OrtEpApi. |
| onnxruntime/core/framework/error_code_helper.h | Introduces ORT_API_RETURN_IF macro for concise OrtStatus* error returns. |
| include/onnxruntime/core/session/onnxruntime_ep_c_api.h | Exposes the new OpSchema APIs in the public EP C API surface with documentation. |
| include/onnxruntime/core/session/onnxruntime_cxx_inline.h | Implements the inline C++ wrappers for ConstOpSchema and GetOpSchema. |
| include/onnxruntime/core/session/onnxruntime_cxx_api.h | Declares the new C++ wrapper type and free function in the public C++ API. |
| include/onnxruntime/core/session/onnxruntime_c_api.h | Adds the opaque runtime type declaration OrtOpSchema. |
Comments suppressed due to low confidence (1)
onnxruntime/core/session/plugin_ep/ep_api.cc:1005
- The
OrtEpApistruct has grown for version 1.25, but the slot/offsetstatic_asserts are only updated up through version 24. Add a newstatic_assertfor the new version boundary (e.g., validate the expected slot index forGetOpSchemaor the size/offset at the end of the 1.25 additions) to keep ABI/slot stability checks complete.
&OrtExecutionProviderApi::OpSchema_HasTypeConstraint,
};
// checks that we don't violate the rule that the functions must remain in the slots they were originally assigned
static_assert(offsetof(OrtEpApi, ReleaseEpDevice) / sizeof(void*) == 1,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
There was a problem hiding this comment.
Pull request overview
This PR introduces new Plugin EP (OrtEpApi) APIs to retrieve and query ONNX operator schemas from the global ONNX schema registry, and adds a C++ wrapper plus tests to validate the behavior.
Changes:
- Added new
OrtEpApiC APIs to fetch an operator schema (GetOpSchema) and query schema metadata (since_version, IO names/types, type constraints). - Added C++ convenience wrappers (
Ort::ConstOpSchema,Ort::GetOpSchema) over the new EP APIs. - Added unit tests validating schema lookup and basic schema properties for well-known ONNX ops.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| onnxruntime/test/framework/ep_plugin_provider_test.cc | Adds tests for the new C++ OpSchema wrapper and lookup API. |
| onnxruntime/core/session/plugin_ep/ep_api.h | Declares new OpSchema-related EP API entrypoints. |
| onnxruntime/core/session/plugin_ep/ep_api.cc | Implements OpSchema EP APIs and appends them to the OrtEpApi function table. |
| onnxruntime/core/framework/error_code_helper.h | Adds ORT_API_RETURN_IF helper macro for concise OrtStatus error returns. |
| include/onnxruntime/core/session/onnxruntime_ep_c_api.h | Extends the public OrtEpApi struct with the new OpSchema APIs and documentation. |
| include/onnxruntime/core/session/onnxruntime_cxx_inline.h | Provides inline implementations for the new ConstOpSchema C++ wrapper methods and Ort::GetOpSchema. |
| include/onnxruntime/core/session/onnxruntime_cxx_api.h | Declares the ConstOpSchema wrapper type and Ort::GetOpSchema API. |
| include/onnxruntime/core/session/onnxruntime_c_api.h | Adds the opaque runtime type declaration for OrtOpSchema. |
Comments suppressed due to low confidence (1)
onnxruntime/core/session/plugin_ep/ep_api.cc:1011
- The OrtEpApi struct is append-only and has per-version slot static_asserts below. Since new function pointers were added after the “End of Version 24” marker, please add/update the corresponding static_assert for Version 1.25 (e.g., based on the last new field) so ABI slot stability continues to be enforced for the new version.
// checks that we don't violate the rule that the functions must remain in the slots they were originally assigned
static_assert(offsetof(OrtEpApi, ReleaseEpDevice) / sizeof(void*) == 1,
"Size of version 22 API cannot change"); // initial version in ORT 1.22
static_assert(offsetof(OrtEpApi, GetSyncIdForLastWaitOnSyncStream) / sizeof(void*) == 15,
"Size of version 23 API cannot change");
static_assert(offsetof(OrtEpApi, GetEnvConfigEntries) / sizeof(void*) == 49,
"Size of version 24 API cannot change");
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
Replace the UB reinterpret_cast<onnx::OpSchema*> approach with a proper opaque struct OrtOpSchema that owns: - A pointer to the onnx::OpSchema from the global registry - Eagerly-built OrtOpSchemaTypeConstraints data Key changes: - GetOpSchema now allocates and returns an owning OrtOpSchema* - Add ReleaseOpSchema; remove ReleaseOpSchemaTypeConstraints - OpSchema_GetTypeConstraints returns a non-owning view (no allocation) - All OpSchema_Get* functions access schema->onnx_schema (no casts) - C++ wrapper: ConstOpSchema -> OpSchema (owning RAII) - C++ wrapper: OpSchemaTypeConstraints -> ConstOpSchemaTypeConstraints (non-owning view) - Rename abi_opschema_type_constraints.h -> abi_opschema.h Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace OrtOpSchemaTypeConstraints (plural container + index-based accessors) with OrtOpSchemaTypeConstraint (singular opaque entity per constraint). Key changes: - GetInputTypeStr/GetOutputTypeStr -> GetInputTypeConstraint/GetOutputTypeConstraint returning the constraint object directly (O(1) via lookup table) - Container-level APIs (TypeConstraints_GetName(container, i)) replaced by per-entity APIs (TypeConstraint_GetName(tc)) - OrtOpSchema gains input_to_constraint/output_to_constraint vectors for O(1) input/output -> constraint mapping - Pointer identity: shared constraints return same pointer (e.g., both inputs of Add return the same OrtOpSchemaTypeConstraint*) - Dropped GetTypeConstraints (array return) and FindByName - 15 API slots (was 16) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Aligns with ONNX terminology where the field is type_param_str in TypeConstraintParam struct. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR extends the EP Plugin ABI (OrtEpApi) with new APIs that let plugin execution providers query ONNX operator schemas (including type constraints) from ORT’s global schema registry, plus adds corresponding C++ wrapper types and unit tests.
Changes:
- Added
OrtEpApiv1.25 OpSchema query/release + schema/type-constraint accessor APIs. - Implemented the new APIs in the plugin EP bridge layer with eager precomputation of type-constraint metadata for O(1) access.
- Added C++ RAII wrappers (
Ort::OpSchema,Ort::ConstOpSchemaTypeConstraint) and unit tests validating schema lookup and type-constraint workflows.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| onnxruntime/core/session/abi_opschema.h | Introduces internal structs backing the opaque OpSchema/type-constraint handles. |
| include/onnxruntime/core/session/onnxruntime_ep_c_api.h | Adds new public EP C APIs and documentation for schema/type-constraint access. |
| onnxruntime/core/session/plugin_ep/ep_api.h | Declares internal implementations for the new EP OpSchema APIs. |
| onnxruntime/core/session/plugin_ep/ep_api.cc | Implements schema lookup + accessors and appends them to the v1.25 EP API table. |
| include/onnxruntime/core/session/onnxruntime_cxx_api.h | Adds C++ wrapper types and release wiring for OrtOpSchema. |
| include/onnxruntime/core/session/onnxruntime_cxx_inline.h | Implements the new C++ wrapper methods and Ort::GetOpSchema() helper. |
| onnxruntime/test/framework/ep_plugin_provider_test.cc | Adds unit tests for the new C++ wrapper + schema/type-constraint behavior. |
| onnxruntime/core/framework/error_code_helper.h | Adds ORT_API_RETURN_IF helper macro for concise OrtStatus returns. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
### Description Address some good leftover comments from PR that added EP APIs to retrieve operator schemas: #27713 ### Motivation and Context Clean up as promised
Description
Adds C/C++ APIs to the
OrtEpApithat allow plugin EPs to query ONNX operator schemas from ORT's global schema registry. This enables EPs to programmatically discover operator metadata (input/output names, type constraints, allowed types, since_version) needed to correctly build kernel definitions with proper type constraints.Motivation
Resolves #27680. Plugin EPs must provide exact type constraint names (e.g.,
"T","T1") and allowed types when callingKernelDefBuilder::AddTypeConstraint(). Without schema access, EPs must either hard-code these names or skip type constraints entirely, leading to potentially incorrect kernel selection and data type mismatches at runtime.Why can't an EP library just link to its own ONNX library? The ONNX
OpSchemaRegistryis a Meyers singleton (staticlocal inInstance()). Each shared library gets its own copy of that static variable: on Windows each DLL is isolated by default, on macOS two-level namespaces have the same effect, and on Linux behavior depends ondlopenflags (RTLD_LOCALisolates,RTLD_GLOBALcreates unpredictable interposition). Even when isolation doesn't occur, the EP's registry would lack ORT's contrib and internal schemas, and version mismatches between the EP's ONNX library and ORT's vendored copy could cause silent divergence. A C API through ORT is the only reliable, portable way to query the schemas ORT actually uses.Changes
New opaque types:
OrtOpSchema— owning opaque struct wrapping anonnx::OpSchema*with precomputed type constraint data. Allocated byGetOpSchema, released byReleaseOpSchema.OrtOpSchemaTypeConstraint— non-owning opaque entity representing a single type constraint (e.g., "T"). Lifetime is tied to the parentOrtOpSchema. Each constraint carries its name, allowed types, and input/output index mappings.New C APIs added to
OrtEpApi(Version 1.25, 15 functions):GetOpSchema""or"ai.onnx"for standard ONNX ops,"ai.onnx.ml"for ML ops,"com.microsoft"for contrib ops.ReleaseOpSchemaOrtOpSchemaallocated byGetOpSchema.OpSchema_GetSinceVersionOpSchema_GetNumInputs/GetNumOutputsOpSchema_GetInputName/GetOutputNameOpSchema_GetInputTypeConstraint/GetOutputTypeConstraintnullptrif the input/output has no type constraint. Shared constraints return the same pointer (pointer identity = shared type).OpSchema_GetTypeConstraintCountOpSchema_GetTypeConstraintOpSchemaTypeConstraint_GetTypeParamName"T","T1").OpSchemaTypeConstraint_GetAllowedTypes"tensor(float)").OpSchemaTypeConstraint_GetInputIndicesOpSchemaTypeConstraint_GetOutputIndicesC++ wrappers:
Ort::OpSchema— owning wrapper aroundOrtOpSchema*(move-only, auto-releases).Ort::ConstOpSchemaTypeConstraint— non-owning wrapper aroundconst OrtOpSchemaTypeConstraint*.Ort::GetOpSchema()— free function to query the registry.Design highlights:
GetOpSchema— all subsequent accessors are O(1) with no allocation.GetInputTypeConstraint/GetOutputTypeConstraintreturn the full constraint object directly (not just a string), enabling a 2-call workflow:GetInputTypeConstraint(0)→GetAllowedTypes().Adduse"T") return the sameOrtOpSchemaTypeConstraint*."ai.onnx"is normalized to""(the canonical ONNX domain) for transparent lookup.Tests: 14 unit tests covering known/unknown ops, version boundaries, wrong domains,
"ai.onnx"alias, schema properties (Add, Relu, LSTM), type constraint access, pointer identity for shared constraints, out-of-range errors, and the input→constraint→allowed-types workflow.Files
onnxruntime/core/session/abi_opschema.hOrtOpSchemaTypeConstraintandOrtOpSchema.include/.../onnxruntime_ep_c_api.honnxruntime/core/session/plugin_ep/ep_api.honnxruntime/core/session/plugin_ep/ep_api.ccinclude/.../onnxruntime_cxx_api.hinclude/.../onnxruntime_cxx_inline.honnxruntime/test/framework/ep_plugin_provider_test.cc