@@ -94,8 +94,8 @@ std::vector<const OrtEpDevice*> OrderDevices(const std::vector<const OrtEpDevice
9494 bool bIsDefaultCpuEp = IsDefaultCpuEp (b);
9595 if (!aIsDefaultCpuEp && !bIsDefaultCpuEp) {
9696 // neither are default CPU EP. both do/don't match vendor.
97- // TODO: implement tie-breaker for this scenario. arbitrarily prefer the first for now
98- return true ;
97+ // TODO: implement tie-breaker for this scenario. arbitrarily sort by ep name
98+ return a-> ep_name < b-> ep_name ;
9999 }
100100
101101 // one is the default CPU EP
@@ -104,31 +104,57 @@ std::vector<const OrtEpDevice*> OrderDevices(const std::vector<const OrtEpDevice
104104
105105 return sorted_devices;
106106}
107+
108+ OrtKeyValuePairs GetModelMetadata (const InferenceSession& session) {
109+ OrtKeyValuePairs metadata;
110+ auto status_and_metadata = session.GetModelMetadata ();
111+
112+ if (!status_and_metadata.first .IsOK ()) {
113+ return metadata;
114+ }
115+
116+ // use field names from onnx.proto
117+ const auto & model_metadata = *status_and_metadata.second ;
118+ metadata.Add (" producer_name" , model_metadata.producer_name );
119+ metadata.Add (" producer_version" , model_metadata.producer_version );
120+ metadata.Add (" domain" , model_metadata.domain );
121+ metadata.Add (" model_version" , std::to_string (model_metadata.version ));
122+ metadata.Add (" doc_string" , model_metadata.description );
123+ metadata.Add (" graph_name" , model_metadata.graph_name ); // name from main GraphProto
124+ metadata.Add (" graph_description" , model_metadata.graph_description ); // descriptions from main GraphProto
125+ for (const auto & entry : model_metadata.custom_metadata_map ) {
126+ metadata.Add (entry.first , entry.second );
127+ }
128+
129+ return metadata;
130+ }
107131} // namespace
108132
109133// Select execution providers based on the device policy and available devices and add to session
110134Status ProviderPolicyContext::SelectEpsForSession (const Environment& env, const OrtSessionOptions& options,
111135 InferenceSession& sess) {
112- ORT_ENFORCE (options.value .ep_selection_policy .delegate == nullptr ,
113- " EP selection delegate support is not implemented yet." );
114-
115136 // Get the list of devices from the environment and order them.
116137 // Ordered by preference within each type. NPU -> GPU -> NPU
117138 // TODO: Should environment.cc do the ordering?
118- const auto & execution_devices = OrderDevices (env.GetOrtEpDevices ());
139+ std::vector< const OrtEpDevice*> execution_devices = OrderDevices (env.GetOrtEpDevices ());
119140
120141 // The list of devices selected by policies
121142 std::vector<const OrtEpDevice*> devices_selected;
122143
123144 // Run the delegate if it was passed in lieu of any other policy
124145 if (options.value .ep_selection_policy .delegate ) {
125- auto policy_fn = options.value .ep_selection_policy .delegate ;
146+ auto model_metadata = GetModelMetadata (sess);
147+ OrtKeyValuePairs runtime_metadata; // TODO: where should this come from?
148+
126149 std::vector<const OrtEpDevice*> delegate_devices (execution_devices.begin (), execution_devices.end ());
127150 std::array<const OrtEpDevice*, 8 > selected_devices{nullptr };
128-
129151 size_t num_selected = 0 ;
130- auto * status = (*policy_fn)(delegate_devices.data (), delegate_devices.size (),
131- nullptr , nullptr , selected_devices.data (), selected_devices.size (), &num_selected);
152+
153+ EpSelectionDelegate delegate = options.value .ep_selection_policy .delegate ;
154+ auto * status = delegate (delegate_devices.data (), delegate_devices.size (),
155+ &model_metadata, &runtime_metadata,
156+ selected_devices.data (), selected_devices.size (), &num_selected,
157+ options.value .ep_selection_policy .state );
132158
133159 // return or fall-through for both these cases
134160 // going with explicit failure for now so it's obvious to user what is happening
@@ -142,6 +168,12 @@ Status ProviderPolicyContext::SelectEpsForSession(const Environment& env, const
142168 if (num_selected == 0 ) {
143169 return ORT_MAKE_STATUS (ONNXRUNTIME , FAIL , " EP selection delegate did not select anything." );
144170 }
171+
172+ // Copy the selected devices to the output vector
173+ devices_selected.reserve (num_selected);
174+ for (size_t i = 0 ; i < num_selected; ++i) {
175+ devices_selected.push_back (selected_devices[i]);
176+ }
145177 } else {
146178 // Create the selector for the chosen policy
147179 std::unique_ptr<IEpPolicySelector> selector;
0 commit comments