Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 15 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "onnxruntime_common_enums.h"

Check warning on line 36 in include/onnxruntime/core/session/onnxruntime_c_api.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/core/session/onnxruntime_c_api.h:36: Include the directory when naming header files [build/include_subdir] [4]

/** \brief The API version defined in this header
*
Expand Down Expand Up @@ -6480,6 +6481,20 @@
* \since Version 1.23.
*/
ORT_API2_STATUS(Graph_GetModelMetadata, _In_ const OrtGraph* graph, _Outptr_ OrtModelMetadata** out);

/** \brief Validate a compiled model's compatibility information for a specific EP device.
*
* \param[in] ep_device The EP device to validate against (e.g., from GetEpDevices
* \param[in] compatibility_info The compatibility info string produced when the model was compiled.
* \param[out] out_status The resulting compatibility status for the EP device.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.23.
*/
ORT_API2_STATUS(GetEpCompatibilityForDevice, _In_ const OrtEpDevice* ep_device,
_In_ const char* compatibility_info,
_Out_ OrtCompiledModelCompatibility* out_status);
};

/*
Expand Down
18 changes: 18 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_common_enums.h
Comment thread
adrastogi marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Shared public enums used by both onnxruntime_c_api.h and onnxruntime_ep_c_api.h
Comment thread Fixed
Comment thread
adrastogi marked this conversation as resolved.
Outdated
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

// Compatibility state of a compiled model relative to an execution provider.
typedef enum OrtCompiledModelCompatibility {
OrtCompiledModelCompatibility_EP_NOT_APPLICABLE = 0,
OrtCompiledModelCompatibility_EP_SUPPORTED_OPTIMAL,
OrtCompiledModelCompatibility_EP_SUPPORTED_PREFER_RECOMPILATION,
OrtCompiledModelCompatibility_EP_UNSUPPORTED,
} OrtCompiledModelCompatibility;

#ifdef __cplusplus
}
#endif
13 changes: 1 addition & 12 deletions include/onnxruntime/core/session/onnxruntime_ep_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

// Do not include this file directly. Please include "onnxruntime_c_api.h" instead.
#include "onnxruntime_common_enums.h"

Check warning on line 5 in include/onnxruntime/core/session/onnxruntime_ep_c_api.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/core/session/onnxruntime_ep_c_api.h:5: Include the directory when naming header files [build/include_subdir] [4]

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -482,18 +483,6 @@
OrtEpDataLayout_Default = OrtEpDataLayout_NCHW,
} OrtEpDataLayout;

/**
* \brief Enumeration describing the compatibility state of a compiled model relative to an execution provider.
*
* \since Version 1.23.
*/
typedef enum OrtCompiledModelCompatibility {
OrtCompiledModelCompatibility_EP_NOT_APPLICABLE = 0,
OrtCompiledModelCompatibility_EP_SUPPORTED_OPTIMAL,
OrtCompiledModelCompatibility_EP_SUPPORTED_PREFER_RECOMPILATION,
OrtCompiledModelCompatibility_EP_UNSUPPORTED,
} OrtCompiledModelCompatibility;

/**
* \brief The OrtEp struct provides functions to implement for an execution provider.
* \since Version 1.22.
Expand Down
36 changes: 36 additions & 0 deletions onnxruntime/core/session/onnxruntime_c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3423,6 +3423,41 @@ ORT_API_STATUS_IMPL(OrtApis::CopyTensors, _In_ const OrtEnv* env,
API_IMPL_END
}

#if !defined(ORT_MINIMAL_BUILD)
// Validate compiled model compatibility info for a specific EP device
ORT_API_STATUS_IMPL(OrtApis::GetEpCompatibilityForDevice, _In_ const OrtEpDevice* ep_device,
_In_ const char* compatibility_info,
_Out_ OrtCompiledModelCompatibility* out_status) {
API_IMPL_BEGIN
if (ep_device == nullptr || compatibility_info == nullptr || out_status == nullptr) {
return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "Invalid argument provided to GetEpCompatibilityForDevice.");
}
Comment thread
adrastogi marked this conversation as resolved.

OrtCompiledModelCompatibility status = OrtCompiledModelCompatibility_EP_NOT_APPLICABLE;
OrtStatus* ort_status = nullptr;
OrtEpFactory* factory = ep_device->GetMutableFactory();
if (factory && factory->ValidateCompiledModelCompatibilityInfo) {
ort_status = factory->ValidateCompiledModelCompatibilityInfo(factory, compatibility_info, &status);
}
if (ort_status != nullptr) {
return ToOrtStatus(ToStatusAndRelease(ort_status));
}

*out_status = status;
return nullptr;
API_IMPL_END
}
#else
// Minimal build stub
ORT_API_STATUS_IMPL(OrtApis::GetEpCompatibilityForDevice, _In_ const OrtEpDevice* /*ep_device*/,
_In_ const char* /*compatibility_info*/,
_Out_ OrtCompiledModelCompatibility* /*out_status*/) {
API_IMPL_BEGIN
return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, "This API in not supported in a minimal build.");
API_IMPL_END
}
#endif

#else // defined(ORT_MINIMAL_BUILD)
ORT_API_STATUS_IMPL(OrtApis::RegisterExecutionProviderLibrary, _In_ OrtEnv* /*env*/, _In_ const char* /*registration_name*/,
const ORTCHAR_T* /*path*/) {
Expand Down Expand Up @@ -4108,6 +4143,7 @@ static constexpr OrtApi ort_api_1_to_23 = {
&OrtApis::CopyTensors,

&OrtApis::Graph_GetModelMetadata,
&OrtApis::GetEpCompatibilityForDevice,
};

// OrtApiBase can never change as there is no way to know what version of OrtApiBase is returned by OrtGetApiBase.
Expand Down
5 changes: 5 additions & 0 deletions onnxruntime/core/session/ort_apis.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,11 @@ ORT_API_STATUS_IMPL(ValueInfo_IsFromOuterScope, _In_ const OrtValueInfo* value_i
// OrtGraph
ORT_API_STATUS_IMPL(Graph_GetName, _In_ const OrtGraph* graph, _Outptr_ const char** graph_name);
ORT_API_STATUS_IMPL(Graph_GetModelMetadata, _In_ const OrtGraph* graph, _Outptr_ OrtModelMetadata** out);

// EP Compatibility Info APIs
ORT_API_STATUS_IMPL(GetEpCompatibilityForDevice, _In_ const OrtEpDevice* ep_device,
_In_ const char* compatibility_info,
_Out_ OrtCompiledModelCompatibility* out_status);
ORT_API_STATUS_IMPL(Graph_GetModelPath, _In_ const OrtGraph* graph, _Outptr_ const ORTCHAR_T** model_path);
ORT_API_STATUS_IMPL(Graph_GetOnnxIRVersion, _In_ const OrtGraph* graph, _Out_ int64_t* onnx_ir_version);
ORT_API_STATUS_IMPL(Graph_GetNumOperatorSets, _In_ const OrtGraph* graph, _Out_ size_t* num_operator_sets);
Expand Down
88 changes: 88 additions & 0 deletions onnxruntime/test/framework/ep_compatibility_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,91 @@ TEST_F(EpCompatibilityTest, TestSessionOptionConfiguration) {
EXPECT_TRUE(has_config);
EXPECT_EQ(config_value, "0");
}

// -----------------------------
// C API unit tests
// -----------------------------

namespace {

// Helper to create an OrtEnv and fetch a CPU EP device pointer via the C API.
// Returns a pair of (env, cpu_device). Caller releases env via api->ReleaseEnv.
static std::pair<OrtEnv*, const OrtEpDevice*> CreateEnvAndGetCpuEpDevice(const OrtApi* api) {
OrtEnv* env = nullptr;
EXPECT_EQ(nullptr, api->CreateEnv(ORT_LOGGING_LEVEL_WARNING, "EpCompatCapiTest", &env));
EXPECT_NE(env, nullptr);

const OrtEpDevice* const* devices = nullptr;
size_t num_devices = 0;
EXPECT_EQ(nullptr, api->GetEpDevices(env, &devices, &num_devices));
EXPECT_GT(num_devices, 0u);

const OrtEpDevice* cpu_device = nullptr;
for (size_t i = 0; i < num_devices; ++i) {
const char* name = api->EpDevice_EpName(devices[i]);
if (name && std::string(name) == "CPUExecutionProvider") {
cpu_device = devices[i];
break;
}
}

// Fallback: just pick the first device if CPU wasn't found (environment-dependent builds).
if (!cpu_device && num_devices > 0) {
cpu_device = devices[0];
}

EXPECT_NE(cpu_device, nullptr);
return {env, cpu_device};
}

} // namespace

TEST(EpCompatibilityCapiTest, InvalidArguments) {
const OrtApi* api = OrtGetApiBase()->GetApi(ORT_API_VERSION);
ASSERT_NE(api, nullptr);

OrtCompiledModelCompatibility out_status = OrtCompiledModelCompatibility_EP_NOT_APPLICABLE;

// ep_device == nullptr
OrtStatus* st = api->GetEpCompatibilityForDevice(nullptr, "info", &out_status);
ASSERT_NE(st, nullptr);
EXPECT_EQ(api->GetErrorCode(st), ORT_INVALID_ARGUMENT);
api->ReleaseStatus(st);

// Prepare a valid device
auto [env, device] = CreateEnvAndGetCpuEpDevice(api);
ASSERT_NE(env, nullptr);
ASSERT_NE(device, nullptr);

// compatibility_info == nullptr
st = api->GetEpCompatibilityForDevice(device, nullptr, &out_status);
ASSERT_NE(st, nullptr);
EXPECT_EQ(api->GetErrorCode(st), ORT_INVALID_ARGUMENT);
api->ReleaseStatus(st);

// out_status == nullptr
st = api->GetEpCompatibilityForDevice(device, "some-info", nullptr);
ASSERT_NE(st, nullptr);
EXPECT_EQ(api->GetErrorCode(st), ORT_INVALID_ARGUMENT);
api->ReleaseStatus(st);

api->ReleaseEnv(env);
}

TEST(EpCompatibilityCapiTest, CpuEpReturnsNotApplicableIfNoValidation) {
const OrtApi* api = OrtGetApiBase()->GetApi(ORT_API_VERSION);
ASSERT_NE(api, nullptr);

auto [env, device] = CreateEnvAndGetCpuEpDevice(api);
ASSERT_NE(env, nullptr);
ASSERT_NE(device, nullptr);

OrtCompiledModelCompatibility out_status = static_cast<OrtCompiledModelCompatibility>(-1);
OrtStatus* st = api->GetEpCompatibilityForDevice(device, "arbitrary-compat-string", &out_status);
ASSERT_EQ(st, nullptr) << (st ? api->GetErrorMessage(st) : "");

// For providers that don't implement validation, API should return EP_NOT_APPLICABLE.
EXPECT_EQ(out_status, OrtCompiledModelCompatibility_EP_NOT_APPLICABLE);

api->ReleaseEnv(env);
}
Loading