| 289 | } |
| 290 | |
| 291 | TfLiteIntArray* ArmnnOpaqueDelegate::IdentifyOperatorsToDelegate(TfLiteOpaqueContext* tfLiteContext) |
| 292 | { |
| 293 | TfLiteIntArray* executionPlan = nullptr; |
| 294 | if (TfLiteOpaqueContextGetExecutionPlan(tfLiteContext, &executionPlan) != kTfLiteOk) |
| 295 | { |
| 296 | TF_LITE_OPAQUE_KERNEL_LOG(tfLiteContext, "TfLiteArmnnOpaqueDelegate: Unable to get graph execution plan."); |
| 297 | return nullptr; |
| 298 | } |
| 299 | |
| 300 | // Execution plan size and data are stored as independent variables here so that they are not invalidated by further |
| 301 | // Opaque API calls. There is no guarantee that the execution plan's size or data won't change. |
| 302 | const int executionPlanSize = executionPlan->size; |
| 303 | const int* executionPlanData = executionPlan->data; |
| 304 | |
| 305 | // Delegate data with null network |
| 306 | DelegateData delegateData(m_Options.GetBackends()); |
| 307 | |
| 308 | TfLiteIntArray* nodesToDelegate = TfLiteIntArrayCreate(executionPlanSize); |
| 309 | if (nodesToDelegate == nullptr) |
| 310 | { |
| 311 | TF_LITE_OPAQUE_KERNEL_LOG(tfLiteContext, |
| 312 | "TfLiteArmnnOpaqueDelegate: Unable to create int array from execution plan."); |
| 313 | return nullptr; |
| 314 | } |
| 315 | nodesToDelegate->size = 0; |
| 316 | |
| 317 | std::set<int32_t> unsupportedOperators; |
| 318 | |
| 319 | for (int i = 0; i < executionPlanSize; ++i) |
| 320 | { |
| 321 | const int nodeIndex = executionPlanData[i]; |
| 322 | |
| 323 | // If TfLiteOpaqueNodes can be delegated to ArmNN |
| 324 | TfLiteOpaqueNode* tfLiteNode = nullptr; |
| 325 | TfLiteRegistrationExternal* tfLiteRegistration = nullptr; |
| 326 | |
| 327 | if (TfLiteOpaqueContextGetNodeAndRegistration( |
| 328 | tfLiteContext, nodeIndex, &tfLiteNode, &tfLiteRegistration) != kTfLiteOk) |
| 329 | { |
| 330 | TF_LITE_OPAQUE_KERNEL_LOG(tfLiteContext, |
| 331 | "TfLiteArmnnOpaqueDelegate: Unable to get node and registration for node %d.", |
| 332 | nodeIndex); |
| 333 | continue; |
| 334 | } |
| 335 | |
| 336 | TfLiteStatus visitStatus; |
| 337 | try |
| 338 | { |
| 339 | visitStatus = ArmnnSubgraph::VisitNode( |
| 340 | delegateData, tfLiteContext, tfLiteRegistration, tfLiteNode, nodeIndex); |
| 341 | } |
| 342 | catch(std::exception& ex) |
| 343 | { |
| 344 | ARMNN_LOG(error) << "ArmNN Failed to visit node with error: " << ex.what(); |
| 345 | visitStatus = kTfLiteError; |
| 346 | TF_LITE_OPAQUE_KERNEL_LOG(tfLiteContext, |
| 347 | "Exception text: %s", |
| 348 | ex.what()); |