blob: c3422a2fb5cd656af5a7d60d999f4121b79ab78e [file] [log] [blame]
Sadik Armagan62483be2020-10-23 17:14:43 +01001//
Ryan OShea4c231de2023-01-17 15:19:20 +00002// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
Sadik Armagan62483be2020-10-23 17:14:43 +01003// SPDX-License-Identifier: MIT
4//
5
6#pragma once
7
Matthew Sloyan11572322023-03-16 10:17:51 +00008#include <ClassicDelegateUtils.hpp>
David Monahan1670b0c2020-11-18 14:40:27 +00009
Sadik Armagan62483be2020-10-23 17:14:43 +010010#include <tensorflow/lite/builtin_ops.h>
11#include <tensorflow/lite/c/builtin_op_data.h>
12#include <tensorflow/lite/c/common.h>
13#include <tensorflow/lite/minimal_logging.h>
14
15namespace armnnDelegate
16{
17
Sadik Armagan937565b2021-04-21 14:03:28 +010018TfLiteStatus VisitCastOperator(DelegateData& delegateData,
19 TfLiteContext* tfLiteContext,
20 TfLiteNode* tfLiteNode,
21 int nodeIndex,
22 int32_t operatorCode)
23{
24 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
25 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
26
27 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
28 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
29 if (!IsValid(tfLiteContext, tfLiteInputTensor, operatorCode, nodeIndex))
30 {
31 return kTfLiteError;
32 }
33
34 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
35 if (!IsValid(tfLiteContext, tfLiteOutputTensor, operatorCode, nodeIndex))
36 {
37 return kTfLiteError;
38 }
39
40 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
Sadik Armagan90a119b2022-08-05 16:12:49 +010041 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
Sadik Armagan937565b2021-04-21 14:03:28 +010042
43 bool isSupported = false;
Cathal Corbett53837672022-09-01 11:34:37 +010044 armnn::BackendId setBackend;
Sadik Armagan937565b2021-04-21 14:03:28 +010045 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
46 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +000047 FORWARD_LAYER_SUPPORT_FUNC("CAST",
Sadik Armagan937565b2021-04-21 14:03:28 +010048 tfLiteContext,
49 IsCastSupported,
50 delegateData.m_Backends,
51 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +010052 setBackend,
Sadik Armagan937565b2021-04-21 14:03:28 +010053 inputTensorInfo,
54 outInfo);
55 };
56
57 // If the m_Network is a nullptr, this signals that a prerequisite TfLite callback is required to clarify the
58 // support for the operator
59 // If supported, VisitCastOperator will be called again to add the layer to the network as seen further below
60 if (!delegateData.m_Network)
61 {
62 validateFunc(outputTensorInfo, isSupported);
63 return isSupported ? kTfLiteOk : kTfLiteError;
64 }
65
66 // Add a Cast layer
Mike Kelly07169c82023-08-02 13:23:09 +010067 auto layerName = GetLayerName(armnn::LayerType::Cast, nodeIndex);
68 armnn::IConnectableLayer* layer = delegateData.m_Network->AddCastLayer(layerName.c_str());
Cathal Corbett53837672022-09-01 11:34:37 +010069 layer->SetBackendId(setBackend);
Sadik Armagan937565b2021-04-21 14:03:28 +010070 ARMNN_ASSERT(layer != nullptr);
71
72 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
73 outputSlot.SetTensorInfo(outputTensorInfo);
74
Ryan OShea4c231de2023-01-17 15:19:20 +000075 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +010076 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Ryan OShea4c231de2023-01-17 15:19:20 +000077 {
78 return kTfLiteError;
79 }
80
Sadik Armagan937565b2021-04-21 14:03:28 +010081 // Connect
82 return Connect(layer, tfLiteNode, delegateData);
83}
84
Sadik Armagan62483be2020-10-23 17:14:43 +010085TfLiteStatus VisitReshapeOperator(DelegateData& delegateData,
86 TfLiteContext* tfLiteContext,
87 TfLiteNode* tfLiteNode,
88 int nodeIndex,
89 int32_t operatorCode)
90{
David Monahan1670b0c2020-11-18 14:40:27 +000091 auto numInputs = tfLiteNode->inputs->size;
Finn Williams6f9f9902020-11-13 13:23:15 +000092
David Monahan1670b0c2020-11-18 14:40:27 +000093 if (numInputs == 2)
94 {
95 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 2, nodeIndex));
96 }
97 else
98 {
99 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
100 }
101 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
102
103 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
104 const TfLiteTensor& tfLiteInputTensor0 = tfLiteTensors[tfLiteNode->inputs->data[0]];
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000105 if (!IsValid(tfLiteContext, tfLiteInputTensor0, operatorCode, nodeIndex))
David Monahan1670b0c2020-11-18 14:40:27 +0000106 {
David Monahan1670b0c2020-11-18 14:40:27 +0000107 return kTfLiteError;
108 }
109
110 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000111 if (!IsValid(tfLiteContext, tfLiteOutputTensor, operatorCode, nodeIndex))
David Monahan1670b0c2020-11-18 14:40:27 +0000112 {
David Monahan1670b0c2020-11-18 14:40:27 +0000113 return kTfLiteError;
114 }
115
116 const armnn::TensorInfo& inputTensorInfo0 = GetTensorInfoForTfLiteTensor(tfLiteInputTensor0);
Sadik Armagan90a119b2022-08-05 16:12:49 +0100117 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor, true);
David Monahan1670b0c2020-11-18 14:40:27 +0000118
119 armnn::ReshapeDescriptor reshapeDesc;
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000120 std::vector<int32_t> targetShape;
Finn Williamsf806c4d2021-02-22 15:13:12 +0000121
122 TfLiteReshapeParams* reshapeOptions = reinterpret_cast<TfLiteReshapeParams*>(tfLiteNode->builtin_data);
David Monahan1670b0c2020-11-18 14:40:27 +0000123
124 // The new shape can be defined by either a second input tensor or by a builtin option, we need to check for both.
Finn Williamsf806c4d2021-02-22 15:13:12 +0000125 // Options might be set without valid data. we need to check the dimensions are in a valid range.
126 if (reshapeOptions && reshapeOptions->num_dimensions > 0 && reshapeOptions->num_dimensions <= 8)
127 {
128 for (int i=0; i < reshapeOptions->num_dimensions; ++i)
129 {
130 targetShape.push_back(reshapeOptions->shape[i]);
131 }
132 }
133 else if (numInputs == 2)
David Monahan1670b0c2020-11-18 14:40:27 +0000134 {
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000135 // Get shape from the second input tensor
136 const TfLiteTensor& tfLiteShapeInputTensor = tfLiteTensors[tfLiteNode->inputs->data[1]];
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000137 if (!IsValid(tfLiteContext, tfLiteShapeInputTensor, operatorCode, nodeIndex))
David Monahane03d9c22020-11-20 09:58:54 +0000138 {
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000139 return kTfLiteError;
140 }
141
142 if (tfLiteShapeInputTensor.dims->size != 1)
143 {
144 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
145 "TfLiteArmnnDelegate: Target 'shape' input is not a 1D tensor in "
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000146 "operator #%d node #%d: Falling back to TfLiteOptions.",
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000147 operatorCode, nodeIndex);
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000148 }
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000149 else
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000150 {
Matthew Sloyanf00f6c22020-12-07 13:33:24 +0000151 // Get the shape data out of the input tensor
152 auto* shapeTensorDataPtr = tflite::GetTensorData<int32_t>(&tfLiteShapeInputTensor);
153 auto shapeTensorNumValues = tfLiteShapeInputTensor.dims->data[0];
154 for (auto i=0; i < shapeTensorNumValues; ++i)
155 {
156 targetShape.push_back(*(shapeTensorDataPtr+i));
157 }
David Monahane03d9c22020-11-20 09:58:54 +0000158 }
159 }
Finn Williamsf806c4d2021-02-22 15:13:12 +0000160 else
David Monahane03d9c22020-11-20 09:58:54 +0000161 {
Finn Williamsf806c4d2021-02-22 15:13:12 +0000162 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
163 "Target shape not defined in reshape parameters or input tensor. "
164 "At least one method required in operator #%d node #%d: ",
165 operatorCode, nodeIndex);
166 return kTfLiteError;
David Monahan1670b0c2020-11-18 14:40:27 +0000167 }
David Monahane03d9c22020-11-20 09:58:54 +0000168
Tianle Cheng20773482023-10-03 12:01:11 +0100169 // Check the target shape to check if there is zero in the shape.
170 if (std::find(targetShape.begin(), targetShape.end(), 0) != targetShape.end() &&
171 inputTensorInfo0.GetNumElements() != 0)
172 {
173 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
174 "TfLiteArmnnDelegate: Input to reshape is a tensor with elements, "
175 "but the requested shape has 0. "
176 "operator #%d node #%d: ",
177 operatorCode, nodeIndex);
178 return kTfLiteError;
179 }
180
David Monahane03d9c22020-11-20 09:58:54 +0000181 // Use the data to create the required tensor shape.
182 if (CreateOutputTensorShape(inputTensorInfo0, targetShape, reshapeDesc) != kTfLiteOk)
David Monahan1670b0c2020-11-18 14:40:27 +0000183 {
184 TF_LITE_MAYBE_KERNEL_LOG(tfLiteContext,
David Monahane03d9c22020-11-20 09:58:54 +0000185 "TfLiteArmnnDelegate: At most one component of shape can be -1 in: "
186 "operator #%d node #%d: ",
David Monahan1670b0c2020-11-18 14:40:27 +0000187 operatorCode, nodeIndex);
David Monahane03d9c22020-11-20 09:58:54 +0000188 return kTfLiteError;
189 }
190
191 if (reshapeDesc.m_TargetShape.GetNumElements() != inputTensorInfo0.GetNumElements())
192 {
Narumol Prangnawarat7f6c6672020-11-24 18:40:42 +0000193 TF_LITE_MAYBE_KERNEL_LOG(
194 tfLiteContext,
195 "TfLiteArmnnDelegate: Reshape, number of elements in output shape does not match input "
196 "operator #%d node #%d: ",
197 operatorCode, nodeIndex);
David Monahane03d9c22020-11-20 09:58:54 +0000198 return kTfLiteError;
David Monahan1670b0c2020-11-18 14:40:27 +0000199 }
200
201 bool isSupported = false;
Cathal Corbett53837672022-09-01 11:34:37 +0100202 armnn::BackendId setBackend;
David Monahan1670b0c2020-11-18 14:40:27 +0000203 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
204 {
Sadik Armaganbfa767c2022-02-09 14:58:03 +0000205 FORWARD_LAYER_SUPPORT_FUNC("RESHAPE",
David Monahan1670b0c2020-11-18 14:40:27 +0000206 tfLiteContext,
207 IsReshapeSupported,
208 delegateData.m_Backends,
209 isSupported,
Cathal Corbett53837672022-09-01 11:34:37 +0100210 setBackend,
David Monahan1670b0c2020-11-18 14:40:27 +0000211 inputTensorInfo0,
212 outInfo,
213 reshapeDesc);
214 };
215
216 if (!delegateData.m_Network)
217 {
218 validateFunc(outputTensorInfo, isSupported);
219 return isSupported ? kTfLiteOk : kTfLiteError;
220 }
221
Mike Kelly07169c82023-08-02 13:23:09 +0100222 auto layerName = GetLayerName(armnn::LayerType::Reshape, nodeIndex);
223 armnn::IConnectableLayer* layer = delegateData.m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
Cathal Corbett53837672022-09-01 11:34:37 +0100224 layer->SetBackendId(setBackend);
David Monahan1670b0c2020-11-18 14:40:27 +0000225 ARMNN_ASSERT(layer != nullptr);
226
227 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
228 outputSlot.SetTensorInfo(outputTensorInfo);
229
Ryan OShea4c231de2023-01-17 15:19:20 +0000230 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +0100231 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Ryan OShea4c231de2023-01-17 15:19:20 +0000232 {
233 return kTfLiteError;
234 }
235
David Monahan1670b0c2020-11-18 14:40:27 +0000236 // Connect
237 return Connect(layer, tfLiteNode, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100238}
239
240TfLiteStatus VisitSqueezeOperator(DelegateData& delegateData,
241 TfLiteContext* tfLiteContext,
242 TfLiteNode* tfLiteNode,
243 int nodeIndex,
244 int32_t operatorCode)
245{
Matthew Sloyan3504e422023-05-03 13:53:02 +0100246 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
247 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
Finn Williams6f9f9902020-11-13 13:23:15 +0000248
Matthew Sloyan3504e422023-05-03 13:53:02 +0100249 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
250 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
251 if (!IsValid(tfLiteContext, tfLiteInputTensor, operatorCode, nodeIndex))
252 {
253 return kTfLiteError;
254 }
255
256 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
257 if (!IsValid(tfLiteContext, tfLiteOutputTensor, operatorCode, nodeIndex))
258 {
259 return kTfLiteError;
260 }
261
262 auto* options = reinterpret_cast<TfLiteSqueezeParams*>(tfLiteNode->builtin_data);
263
264 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
265
266 std::vector<uint32_t> squeezeDim;
267 // A single negative dim index is interpreted as a negative index in python
268 // Meaning the index will be the shape size plus the negative index value
269 if (options->num_squeeze_dims == 1 && options->squeeze_dims[0] < 0)
270 {
271 int32_t dim = static_cast<int32_t>(inputTensorInfo.GetShape().GetNumDimensions()) + options->squeeze_dims[0];
272 squeezeDim.push_back(static_cast<uint32_t>(dim));
273 }
274 else
275 {
276 for (int32_t i = 0; i < options->num_squeeze_dims; ++i)
277 {
278 squeezeDim.push_back(static_cast<uint32_t>(options->squeeze_dims[i]));
279 }
280 }
281
282 armnn::TensorInfo outputTensorInfo = OutputShapeOfSqueeze(squeezeDim, inputTensorInfo);
283
284 armnn::ReshapeDescriptor reshapeDesc;
285 reshapeDesc.m_TargetShape = outputTensorInfo.GetShape();
286
287 bool isSupported = false;
288 armnn::BackendId setBackend;
289 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
290 {
291 FORWARD_LAYER_SUPPORT_FUNC("SQUEEZE",
292 tfLiteContext,
293 IsReshapeSupported,
294 delegateData.m_Backends,
295 isSupported,
296 setBackend,
297 inputTensorInfo,
298 outInfo,
299 reshapeDesc);
300 };
301
302 if (!delegateData.m_Network)
303 {
304 validateFunc(outputTensorInfo, isSupported);
305 return isSupported ? kTfLiteOk : kTfLiteError;
306 }
307
Mike Kelly07169c82023-08-02 13:23:09 +0100308 auto layerName = GetLayerName(armnn::LayerType::Reshape, nodeIndex, "Squeeze");
309 armnn::IConnectableLayer* layer = delegateData.m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
Matthew Sloyan3504e422023-05-03 13:53:02 +0100310 layer->SetBackendId(setBackend);
311 ARMNN_ASSERT(layer != nullptr);
312
313 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
314 outputSlot.SetTensorInfo(outputTensorInfo);
315
316 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +0100317 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Matthew Sloyan3504e422023-05-03 13:53:02 +0100318 {
319 return kTfLiteError;
320 }
321
322 // Connect
323 return Connect(layer, tfLiteNode, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100324}
325
326TfLiteStatus VisitExpandDimsOperator(DelegateData& delegateData,
327 TfLiteContext* tfLiteContext,
328 TfLiteNode* tfLiteNode,
329 int nodeIndex,
330 int32_t operatorCode)
331{
Matthew Sloyan3504e422023-05-03 13:53:02 +0100332 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 2, nodeIndex));
333 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
Finn Williams6f9f9902020-11-13 13:23:15 +0000334
Matthew Sloyan3504e422023-05-03 13:53:02 +0100335 const TfLiteTensor* tfLiteTensors = tfLiteContext->tensors;
336 const TfLiteTensor& tfLiteInputTensor = tfLiteTensors[tfLiteNode->inputs->data[0]];
337 if (!IsValid(tfLiteContext, tfLiteInputTensor, operatorCode, nodeIndex))
338 {
339 return kTfLiteError;
340 }
341
342 const TfLiteTensor& tfLiteAxisTensor = tfLiteTensors[tfLiteNode->inputs->data[1]];
343 if (!IsValid(tfLiteContext, tfLiteAxisTensor, operatorCode, nodeIndex))
344 {
345 return kTfLiteError;
346 }
347
348 const TfLiteTensor& tfLiteOutputTensor = tfLiteTensors[tfLiteNode->outputs->data[0]];
349 if (!IsValid(tfLiteContext, tfLiteOutputTensor, operatorCode, nodeIndex))
350 {
351 return kTfLiteError;
352 }
353
354 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteInputTensor);
355 armnn::TensorInfo outputTensorInfo = GetTensorInfoForTfLiteTensor(tfLiteOutputTensor);
356
357 auto* axisTensorData = tflite::GetTensorData<int32_t>(&tfLiteAxisTensor);
358 int32_t axis = axisTensorData[0];
359
360 int32_t inputDimSize = static_cast<int32_t>(inputTensorInfo.GetShape().GetNumDimensions());
361 if (axis > inputDimSize || axis < 0 - (inputDimSize + 1))
362 {
363 TF_LITE_MAYBE_KERNEL_LOG(
364 tfLiteContext,
365 "TfLiteArmnnOpaqueDelegate: Axis must be in range "
366 "[0 - (inputDimSize + 1), inputDimSize] inclusive.");
367 return kTfLiteError;
368 }
369
370 if(axis < 0)
371 {
372 axis = inputDimSize + axis + 1;
373 }
374
375 std::vector<unsigned int> shape(static_cast<unsigned int>(inputDimSize) + 1);
376 unsigned int inputShapeIndex = 0;
377 for (unsigned int i = 0; i < static_cast<unsigned int>(inputDimSize + 1); ++i)
378 {
379 if (i == static_cast<unsigned int>(axis))
380 {
381 shape[i] = 1;
382 }
383 else
384 {
385 shape[i] = inputTensorInfo.GetShape()[inputShapeIndex];
386 ++inputShapeIndex;
387 }
388 }
389
390 armnn::ReshapeDescriptor reshapeDesc;
391 reshapeDesc.m_TargetShape = armnn::TensorShape(static_cast<unsigned int>(inputDimSize + 1), shape.data());
392
393 bool isSupported = false;
394 armnn::BackendId setBackend;
395 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
396 {
397 FORWARD_LAYER_SUPPORT_FUNC("EXPAND_DIMS",
398 tfLiteContext,
399 IsReshapeSupported,
400 delegateData.m_Backends,
401 isSupported,
402 setBackend,
403 inputTensorInfo,
404 outInfo,
405 reshapeDesc);
406 };
407
408 if (!delegateData.m_Network)
409 {
410 validateFunc(outputTensorInfo, isSupported);
411 return isSupported ? kTfLiteOk : kTfLiteError;
412 }
413
Mike Kelly07169c82023-08-02 13:23:09 +0100414 auto layerName = GetLayerName(armnn::LayerType::Reshape, nodeIndex, "ExpandDims");
415 armnn::IConnectableLayer* layer = delegateData.m_Network->AddReshapeLayer(reshapeDesc, layerName.c_str());
Matthew Sloyan3504e422023-05-03 13:53:02 +0100416 layer->SetBackendId(setBackend);
417 ARMNN_ASSERT(layer != nullptr);
418
419 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
420 outputTensorInfo.SetShape(reshapeDesc.m_TargetShape);
421 outputSlot.SetTensorInfo(outputTensorInfo);
422
423 // try to connect the Constant Inputs if there are any
Mike Kelly07169c82023-08-02 13:23:09 +0100424 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Matthew Sloyan3504e422023-05-03 13:53:02 +0100425 {
426 return kTfLiteError;
427 }
428
429 // Connect
430 return Connect(layer, tfLiteNode, delegateData);
Sadik Armagan62483be2020-10-23 17:14:43 +0100431}
432
433} // namespace armnnDelegate