blob: a1c5544a4e1c64db645678bcb3210fa5fae978d1 [file] [log] [blame]
Francis Murtaghc4fb0dd2023-03-16 17:01:56 +00001//
2// Copyright © 2023 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
Teresa Charlin42362962023-04-28 14:23:33 +01005
6#pragma once
7
8#include <OpaqueDelegateUtils.hpp>
9
10namespace armnnOpaqueDelegate
11{
12
13TfLiteStatus VisitSpaceToDepthOperator(DelegateData& delegateData,
14 TfLiteOpaqueContext* tfLiteContext,
15 TfLiteOpaqueNode* tfLiteNode,
16 int nodeIndex,
17 int32_t tfLiteSpaceDepthOperatorCode)
18{
19 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
20 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
21
22 // Gather input indices and use to get input tensor.
23 const int* inputTensors;
24 int numInputs;
25 if (TfLiteOpaqueNodeInputs(tfLiteNode, &inputTensors, &numInputs) != kTfLiteOk)
26 {
27 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
28 tfLiteContext,
29 "TfLiteArmnnOpaqueDelegate: Unable to gather input tensor indices from node #%d: ",
30 nodeIndex);
31 return kTfLiteError;
32 }
33 const TfLiteOpaqueTensor* tfLiteInputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, inputTensors[0]);
34 if (!IsValid(tfLiteContext, tfLiteInputTensor, tfLiteSpaceDepthOperatorCode, nodeIndex))
35 {
36 return kTfLiteError;
37 }
38
39 // Gather output indices and use to get output tensors.
40 const int* outputTensors;
41 int numOutputs;
42 if (TfLiteOpaqueNodeOutputs(tfLiteNode, &outputTensors, &numOutputs) != kTfLiteOk)
43 {
44 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
45 tfLiteContext,
46 "TfLiteArmnnOpaqueDelegate: Unable to gather output tensor indices from node #%d: ",
47 nodeIndex);
48 return kTfLiteError;
49 }
50
51 const TfLiteOpaqueTensor* tfLiteOutputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, outputTensors[0]);
52 if (!IsValid(tfLiteContext, tfLiteOutputTensor, tfLiteSpaceDepthOperatorCode, nodeIndex))
53 {
54 return kTfLiteError;
55 }
56
57 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteInputTensor);
58 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteOutputTensor, true);
59
60 armnn::SpaceToDepthDescriptor descriptor;
61 auto* nodeParameters = reinterpret_cast<TfLiteSpaceToDepthParams*>(TfLiteOpaqueNodeGetBuiltinData(tfLiteNode));
62 descriptor.m_BlockSize = nodeParameters->block_size;
63
64 bool isSupported = false;
65 armnn::BackendId setBackend;
66 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
67 {
68 FORWARD_LAYER_OPAQUE_SUPPORT_FUNC("SPACE_TO_DEPTH",
69 tfLiteContext,
70 IsSpaceToDepthSupported,
71 delegateData.m_Backends,
72 isSupported,
73 setBackend,
74 inputTensorInfo,
75 outInfo,
76 descriptor);
77 };
78
79 if (!delegateData.m_Network)
80 {
81 validateFunc(outputTensorInfo, isSupported);
82 return isSupported ? kTfLiteOk : kTfLiteError;
83 }
84
85 // Add a SpaceToDepth layer
Mike Kellya2806502023-08-03 10:42:11 +010086 auto layerName = GetName(armnn::LayerType::SpaceToDepth, nodeIndex);
87 armnn::IConnectableLayer* layer = delegateData.m_Network->AddSpaceToDepthLayer(descriptor, layerName.c_str());
Teresa Charlin42362962023-04-28 14:23:33 +010088 layer->SetBackendId(setBackend);
89 ARMNN_ASSERT(layer != nullptr);
90
91 // try to connect the Constant Inputs if there are any
Mike Kellya2806502023-08-03 10:42:11 +010092 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Teresa Charlin42362962023-04-28 14:23:33 +010093 {
94 return kTfLiteError;
95 }
96
97 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
98 outputSlot.SetTensorInfo(outputTensorInfo);
99
100 // Connect
101 return Connect(layer, tfLiteContext, tfLiteNode, delegateData);
102}
103
104TfLiteStatus VisitDepthToSpaceOperator(DelegateData& delegateData,
105 TfLiteOpaqueContext* tfLiteContext,
106 TfLiteOpaqueNode* tfLiteNode,
107 int nodeIndex,
108 int32_t tfLiteDepthSpaceOperatorCode)
109{
110 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
111 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
112
113 // Gather input indices and use to get input tensor.
114 const int* inputTensors;
115 int numInputs;
116 if (TfLiteOpaqueNodeInputs(tfLiteNode, &inputTensors, &numInputs) != kTfLiteOk)
117 {
118 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
119 tfLiteContext,
120 "TfLiteArmnnOpaqueDelegate: Unable to gather input tensor indices from node #%d: ",
121 nodeIndex);
122 return kTfLiteError;
123 }
124 const TfLiteOpaqueTensor* tfLiteInputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, inputTensors[0]);
125 if (!IsValid(tfLiteContext, tfLiteInputTensor, tfLiteDepthSpaceOperatorCode, nodeIndex))
126 {
127 return kTfLiteError;
128 }
129
130 // Gather output indices and use to get output tensors.
131 const int* outputTensors;
132 int numOutputs;
133 if (TfLiteOpaqueNodeOutputs(tfLiteNode, &outputTensors, &numOutputs) != kTfLiteOk)
134 {
135 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
136 tfLiteContext,
137 "TfLiteArmnnOpaqueDelegate: Unable to gather output tensor indices from node #%d: ",
138 nodeIndex);
139 return kTfLiteError;
140 }
141
142 const TfLiteOpaqueTensor* tfLiteOutputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, outputTensors[0]);
143 if (!IsValid(tfLiteContext, tfLiteOutputTensor, tfLiteDepthSpaceOperatorCode, nodeIndex))
144 {
145 return kTfLiteError;
146 }
147
148 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteInputTensor);
149 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteOutputTensor, true);
150
151 armnn::DepthToSpaceDescriptor descriptor;
152 auto* nodeParameters = reinterpret_cast<TfLiteSpaceToDepthParams*>(TfLiteOpaqueNodeGetBuiltinData(tfLiteNode));
153 descriptor.m_BlockSize = nodeParameters->block_size;
154
155 bool isSupported = false;
156 armnn::BackendId setBackend;
157 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
158 {
159 FORWARD_LAYER_OPAQUE_SUPPORT_FUNC("DEPTH_TO_SPACE",
160 tfLiteContext,
161 IsDepthToSpaceSupported,
162 delegateData.m_Backends,
163 isSupported,
164 setBackend,
165 inputTensorInfo,
166 outInfo,
167 descriptor);
168 };
169
170 if (!delegateData.m_Network)
171 {
172 validateFunc(outputTensorInfo, isSupported);
173 return isSupported ? kTfLiteOk : kTfLiteError;
174 }
175
176 // Add a DepthToSpace layer
Mike Kellya2806502023-08-03 10:42:11 +0100177 auto layerName = GetName(armnn::LayerType::DepthToSpace, nodeIndex);
178 armnn::IConnectableLayer* layer = delegateData.m_Network->AddDepthToSpaceLayer(descriptor, layerName.c_str());
Teresa Charlin42362962023-04-28 14:23:33 +0100179 layer->SetBackendId(setBackend);
180 ARMNN_ASSERT(layer != nullptr);
181
182 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
183 outputSlot.SetTensorInfo(outputTensorInfo);
184
185 // try to connect the Constant Inputs if there are any
Mike Kellya2806502023-08-03 10:42:11 +0100186 if (ProcessInputs(layer, delegateData, tfLiteContext, tfLiteNode, nodeIndex) != kTfLiteOk)
Teresa Charlin42362962023-04-28 14:23:33 +0100187 {
188 return kTfLiteError;
189 }
190
191 // Connect
192 return Connect(layer, tfLiteContext, tfLiteNode, delegateData);
193}
194
195} // namespace armnnOpaqueDelegate