| 1167 | } |
| 1168 | |
| 1169 | TfLiteStatus Subgraph::ModifyGraphWithDelegate(TfLiteDelegate* delegate) { |
| 1170 | // Restore delegation state if applicable. |
| 1171 | TF_LITE_ENSURE_STATUS(RedoAllDelegates()); |
| 1172 | |
| 1173 | if (state_ == kStateInvokableAndImmutable) { |
| 1174 | ReportError( |
| 1175 | "ModifyGraphWithDelegate is disallowed when graph is immutable."); |
| 1176 | return kTfLiteError; |
| 1177 | } |
| 1178 | |
| 1179 | if (!(delegate->flags & kTfLiteDelegateFlagsAllowDynamicTensors)) { |
| 1180 | int last_execution_plan_index_prepared; |
| 1181 | TF_LITE_ENSURE_OK(&context_, PrepareOpsStartingAt( |
| 1182 | 0, &last_execution_plan_index_prepared)); |
| 1183 | if (has_dynamic_tensors_) { |
| 1184 | // Make sure that we are in a defined ready state before returning. |
| 1185 | // Plan and allocate tensors before returning. |
| 1186 | TF_LITE_ENSURE_OK(&context_, EnsureMemoryAllocations()); |
| 1187 | ReportError( |
| 1188 | "Attempting to use a delegate that only supports static-sized " |
| 1189 | "tensors with a graph that has dynamic-sized tensors."); |
| 1190 | return kTfLiteError; |
| 1191 | } |
| 1192 | } |
| 1193 | |
| 1194 | const bool was_invokable_before_delegate = state_ == kStateInvokable; |
| 1195 | if (delegates_applied_.empty()) { |
| 1196 | // This is the first delegate being applied, so remember original execution |
| 1197 | // plan. |
| 1198 | // TODO(b/119623453): Restore execution plan to this state if delegate |
| 1199 | // application fails. |
| 1200 | pre_delegation_execution_plan_ = execution_plan_; |
| 1201 | } |
| 1202 | |
| 1203 | // TODO(aselle): Consider if it is worth storing pointers to delegates. |
| 1204 | // Setup additional context interface. |
| 1205 | SwitchToDelegateContext(); |
| 1206 | |
| 1207 | auto reset_delegation_if_not_ok = [this](TfLiteStatus status) { |
| 1208 | if (status != kTfLiteOk) { |
| 1209 | // This will undo all delegate nodes currently in the graph. |
| 1210 | TF_LITE_ENSURE_STATUS(this->UndoAllDelegates()); |
| 1211 | // This will call AllocateTensors, thus-reapplying any (successfully |
| 1212 | // applied) previous delegates. |
| 1213 | TF_LITE_ENSURE_STATUS(this->EnsureMemoryAllocations()); |
| 1214 | ReportError( |
| 1215 | "Restored previous execution plan after delegate application " |
| 1216 | "failure."); |
| 1217 | return kTfLiteError; |
| 1218 | } |
| 1219 | return kTfLiteOk; |
| 1220 | }; |
| 1221 | |
| 1222 | TfLiteStatus status = delegate->Prepare(&context_, delegate); |
| 1223 | |
| 1224 | // Remove additional context info. |
| 1225 | SwitchToKernelContext(); |
| 1226 | |