blob: 9cc61eb603d3e6c48efddae81ec6e8e5358fbeef [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
86 armnn::IConnectableLayer* layer = delegateData.m_Network->AddSpaceToDepthLayer(descriptor);
87 layer->SetBackendId(setBackend);
88 ARMNN_ASSERT(layer != nullptr);
89
90 // try to connect the Constant Inputs if there are any
91 if(ProcessInputs(layer,delegateData, tfLiteContext, tfLiteNode) != kTfLiteOk )
92 {
93 return kTfLiteError;
94 }
95
96 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
97 outputSlot.SetTensorInfo(outputTensorInfo);
98
99 // Connect
100 return Connect(layer, tfLiteContext, tfLiteNode, delegateData);
101}
102
103TfLiteStatus VisitDepthToSpaceOperator(DelegateData& delegateData,
104 TfLiteOpaqueContext* tfLiteContext,
105 TfLiteOpaqueNode* tfLiteNode,
106 int nodeIndex,
107 int32_t tfLiteDepthSpaceOperatorCode)
108{
109 TF_LITE_ENSURE_STATUS(ValidateNumInputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
110 TF_LITE_ENSURE_STATUS(ValidateNumOutputs(tfLiteContext, tfLiteNode, 1, nodeIndex));
111
112 // Gather input indices and use to get input tensor.
113 const int* inputTensors;
114 int numInputs;
115 if (TfLiteOpaqueNodeInputs(tfLiteNode, &inputTensors, &numInputs) != kTfLiteOk)
116 {
117 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
118 tfLiteContext,
119 "TfLiteArmnnOpaqueDelegate: Unable to gather input tensor indices from node #%d: ",
120 nodeIndex);
121 return kTfLiteError;
122 }
123 const TfLiteOpaqueTensor* tfLiteInputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, inputTensors[0]);
124 if (!IsValid(tfLiteContext, tfLiteInputTensor, tfLiteDepthSpaceOperatorCode, nodeIndex))
125 {
126 return kTfLiteError;
127 }
128
129 // Gather output indices and use to get output tensors.
130 const int* outputTensors;
131 int numOutputs;
132 if (TfLiteOpaqueNodeOutputs(tfLiteNode, &outputTensors, &numOutputs) != kTfLiteOk)
133 {
134 TF_LITE_OPAQUE_MAYBE_KERNEL_LOG(
135 tfLiteContext,
136 "TfLiteArmnnOpaqueDelegate: Unable to gather output tensor indices from node #%d: ",
137 nodeIndex);
138 return kTfLiteError;
139 }
140
141 const TfLiteOpaqueTensor* tfLiteOutputTensor = TfLiteOpaqueContextGetOpaqueTensor(tfLiteContext, outputTensors[0]);
142 if (!IsValid(tfLiteContext, tfLiteOutputTensor, tfLiteDepthSpaceOperatorCode, nodeIndex))
143 {
144 return kTfLiteError;
145 }
146
147 const armnn::TensorInfo& inputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteInputTensor);
148 const armnn::TensorInfo& outputTensorInfo = GetTensorInfoForTfLiteOpaqueTensor(tfLiteOutputTensor, true);
149
150 armnn::DepthToSpaceDescriptor descriptor;
151 auto* nodeParameters = reinterpret_cast<TfLiteSpaceToDepthParams*>(TfLiteOpaqueNodeGetBuiltinData(tfLiteNode));
152 descriptor.m_BlockSize = nodeParameters->block_size;
153
154 bool isSupported = false;
155 armnn::BackendId setBackend;
156 auto validateFunc = [&](const armnn::TensorInfo& outInfo, bool& isSupported)
157 {
158 FORWARD_LAYER_OPAQUE_SUPPORT_FUNC("DEPTH_TO_SPACE",
159 tfLiteContext,
160 IsDepthToSpaceSupported,
161 delegateData.m_Backends,
162 isSupported,
163 setBackend,
164 inputTensorInfo,
165 outInfo,
166 descriptor);
167 };
168
169 if (!delegateData.m_Network)
170 {
171 validateFunc(outputTensorInfo, isSupported);
172 return isSupported ? kTfLiteOk : kTfLiteError;
173 }
174
175 // Add a DepthToSpace layer
176 armnn::IConnectableLayer* layer = delegateData.m_Network->AddDepthToSpaceLayer(descriptor);
177 layer->SetBackendId(setBackend);
178 ARMNN_ASSERT(layer != nullptr);
179
180 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
181 outputSlot.SetTensorInfo(outputTensorInfo);
182
183 // try to connect the Constant Inputs if there are any
184 if(ProcessInputs(layer,delegateData, tfLiteContext, tfLiteNode) != kTfLiteOk )
185 {
186 return kTfLiteError;
187 }
188
189 // Connect
190 return Connect(layer, tfLiteContext, tfLiteNode, delegateData);
191}
192
193} // namespace armnnOpaqueDelegate