blob: 5d407447576eb5fb8038b42bf0f143be34e9585e [file] [log] [blame]
Georgios Pinitasd8734b52017-12-22 15:27:52 +00001/*
Michele Di Giorgiod9eaf612020-07-08 11:12:57 +01002 * Copyright (c) 2018-2020 Arm Limited.
Georgios Pinitasd8734b52017-12-22 15:27:52 +00003 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010024#include "arm_compute/graph/backends/CL/CLFunctionFactory.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000025
26#include "arm_compute/core/utils/misc/Cast.h"
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010027#include "arm_compute/graph/Graph.h"
Gian Marco Iodice5dea19e2019-11-08 12:13:48 +000028#include "arm_compute/graph/GraphContext.h"
Georgios Pinitasda2491f2018-06-01 17:49:09 +010029#include "arm_compute/graph/backends/FunctionHelpers.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000030#include "arm_compute/runtime/CL/CLFunctions.h"
Isabella Gottardi7234ed82018-11-27 08:51:10 +000031#include "arm_compute/runtime/CPP/CPPFunctions.h"
Georgios Pinitasd8734b52017-12-22 15:27:52 +000032
Georgios Pinitasd8734b52017-12-22 15:27:52 +000033using namespace arm_compute::utils::cast;
34
35namespace arm_compute
36{
Georgios Pinitasd9eb2752018-04-03 13:44:29 +010037namespace graph
Georgios Pinitasd8734b52017-12-22 15:27:52 +000038{
39namespace backends
40{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010041/** Target specific information structure used to pass information to the layer templates */
42struct CLTargetInfo
Georgios Pinitasd8734b52017-12-22 15:27:52 +000043{
giuros01acce5042019-02-21 17:32:34 +000044 using TensorType = arm_compute::ICLTensor;
Michele Di Giorgiof932d2c2020-07-06 11:27:21 +010045 using SrcTensorType = const arm_compute::ICLTensor;
giuros01acce5042019-02-21 17:32:34 +000046 using TensorConcreteType = CLTensor;
Georgios Pinitasda2491f2018-06-01 17:49:09 +010047 static Target TargetType;
48};
49
50Target CLTargetInfo::TargetType = Target::CL;
51
52/** Collection of CL convolution functions */
53struct CLConvolutionLayerFunctions
Georgios Pinitasd8734b52017-12-22 15:27:52 +000054{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010055 using GenericConvolutionLayer = CLConvolutionLayer;
56 using GEMMConvolutionLayer = CLGEMMConvolutionLayer;
57 using DirectConvolutionLayer = CLDirectConvolutionLayer;
58 using WinogradConvolutionLayer = CLWinogradConvolutionLayer;
59};
Georgios Pinitasd8734b52017-12-22 15:27:52 +000060
Georgios Pinitasda2491f2018-06-01 17:49:09 +010061/** Collection of CL element-wise functions */
62struct CLEltwiseFunctions
Georgios Pinitasd8734b52017-12-22 15:27:52 +000063{
Georgios Pinitasda2491f2018-06-01 17:49:09 +010064 using Addition = CLArithmeticAddition;
65 using Subtraction = CLArithmeticSubtraction;
66 using Multiplication = CLPixelWiseMultiplication;
thecha01f8e35842020-07-28 17:28:17 +010067 using Maximum = CLElementwiseMax;
Georgios Pinitasda2491f2018-06-01 17:49:09 +010068};
giuros01acce5042019-02-21 17:32:34 +000069
Sheri Zhang16dddd22020-05-27 15:03:48 +010070/** Collection of CL unary element-wise functions */
71struct CLUnaryEltwiseFunctions
72{
73 using Exp = CLExpLayer;
74};
75
giuros01acce5042019-02-21 17:32:34 +000076/** Function and tensor types to be used inside a CL fused convolution/batch normalization layer */
77struct CLFusedLayerTypes
78{
Manuel Bottinibffb41e2019-06-20 16:00:27 +010079 using ConvolutionLayer = CLConvolutionLayer;
80 using DepthwiseConvolutionLayer = CLDepthwiseConvolutionLayer;
81 using FuseBatchNormalization = CLFuseBatchNormalization;
giuros01acce5042019-02-21 17:32:34 +000082};
83
Isabella Gottardi7234ed82018-11-27 08:51:10 +000084// TODO (isagot01): Remove once we support heterogeneous scheduling at function level
85/** Wrapper for the CPP Function in the OpenCL backend **/
86class CPPWrapperFunction : public IFunction
87{
88public:
89 /* Default constructor */
90 CPPWrapperFunction()
91 : _tensors(), _func(nullptr)
92 {
93 }
94
95 void run() override
96 {
97 for(auto &tensor : _tensors)
98 {
99 tensor->map(CLScheduler::get().queue());
100 }
101 _func->run();
102
103 for(auto &tensor : _tensors)
104 {
105 tensor->unmap(CLScheduler::get().queue());
106 }
107 }
108
109 void register_tensor(ICLTensor *tensor)
110 {
111 _tensors.push_back(tensor);
112 }
113
114 void register_function(std::unique_ptr<IFunction> function)
115 {
116 _func = std::move(function);
117 }
118
119private:
120 std::vector<arm_compute::ICLTensor *> _tensors;
121 std::unique_ptr<IFunction> _func;
122};
123
124namespace detail
125{
126// Specialized functions
127template <>
128std::unique_ptr<IFunction> create_detection_output_layer<CPPDetectionOutputLayer, CLTargetInfo>(DetectionOutputLayerNode &node)
129{
130 validate_node<CLTargetInfo>(node, 3 /* expected inputs */, 1 /* expected outputs */);
131
132 // Extract IO and info
133 CLTargetInfo::TensorType *input0 = get_backing_tensor<CLTargetInfo>(node.input(0));
134 CLTargetInfo::TensorType *input1 = get_backing_tensor<CLTargetInfo>(node.input(1));
135 CLTargetInfo::TensorType *input2 = get_backing_tensor<CLTargetInfo>(node.input(2));
136 CLTargetInfo::TensorType *output = get_backing_tensor<CLTargetInfo>(node.output(0));
137 const DetectionOutputLayerInfo detect_info = node.detection_output_info();
138
139 ARM_COMPUTE_ERROR_ON(input0 == nullptr);
140 ARM_COMPUTE_ERROR_ON(input1 == nullptr);
141 ARM_COMPUTE_ERROR_ON(input2 == nullptr);
142 ARM_COMPUTE_ERROR_ON(output == nullptr);
143
144 // Create and configure function
145 auto func = support::cpp14::make_unique<CPPDetectionOutputLayer>();
146 func->configure(input0, input1, input2, output, detect_info);
147
148 // Log info
149 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
150 << node.name()
151 << " Type: " << node.type()
152 << " Target: " << CLTargetInfo::TargetType
153 << " Data Type: " << input0->info()->data_type()
154 << " Input0 shape: " << input0->info()->tensor_shape()
155 << " Input1 shape: " << input1->info()->tensor_shape()
156 << " Input2 shape: " << input2->info()->tensor_shape()
157 << " Output shape: " << output->info()->tensor_shape()
158 << " DetectionOutputLayer info: " << detect_info
159 << std::endl);
160
161 auto wrap_function = support::cpp14::make_unique<CPPWrapperFunction>();
Giorgio Arena6e9d0e02020-01-03 15:02:04 +0000162
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000163 wrap_function->register_function(std::move(func));
164 wrap_function->register_tensor(input0);
165 wrap_function->register_tensor(input1);
166 wrap_function->register_tensor(input2);
167 wrap_function->register_tensor(output);
168
Georgios Pinitas0b192e82020-02-20 17:09:28 +0000169 return RETURN_UNIQUE_PTR(wrap_function);
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000170}
Isabella Gottardia7acb3c2019-01-08 13:48:44 +0000171template <>
172std::unique_ptr<IFunction> create_detection_post_process_layer<CPPDetectionPostProcessLayer, CLTargetInfo>(DetectionPostProcessLayerNode &node)
173{
174 validate_node<CLTargetInfo>(node, 3 /* expected inputs */, 4 /* expected outputs */);
175
176 // Extract IO and info
177 CLTargetInfo::TensorType *input0 = get_backing_tensor<CLTargetInfo>(node.input(0));
178 CLTargetInfo::TensorType *input1 = get_backing_tensor<CLTargetInfo>(node.input(1));
179 CLTargetInfo::TensorType *input2 = get_backing_tensor<CLTargetInfo>(node.input(2));
180 CLTargetInfo::TensorType *output0 = get_backing_tensor<CLTargetInfo>(node.output(0));
181 CLTargetInfo::TensorType *output1 = get_backing_tensor<CLTargetInfo>(node.output(1));
182 CLTargetInfo::TensorType *output2 = get_backing_tensor<CLTargetInfo>(node.output(2));
183 CLTargetInfo::TensorType *output3 = get_backing_tensor<CLTargetInfo>(node.output(3));
184 const DetectionPostProcessLayerInfo detect_info = node.detection_post_process_info();
185
186 ARM_COMPUTE_ERROR_ON(input0 == nullptr);
187 ARM_COMPUTE_ERROR_ON(input1 == nullptr);
188 ARM_COMPUTE_ERROR_ON(input2 == nullptr);
189 ARM_COMPUTE_ERROR_ON(output0 == nullptr);
190 ARM_COMPUTE_ERROR_ON(output1 == nullptr);
191 ARM_COMPUTE_ERROR_ON(output2 == nullptr);
192 ARM_COMPUTE_ERROR_ON(output3 == nullptr);
193
194 // Create and configure function
195 auto func = support::cpp14::make_unique<CPPDetectionPostProcessLayer>();
196 func->configure(input0, input1, input2, output0, output1, output2, output3, detect_info);
197
198 // Log info
199 ARM_COMPUTE_LOG_GRAPH_INFO("Instantiated "
200 << node.name()
201 << " Type: " << node.type()
202 << " Target: " << CLTargetInfo::TargetType
203 << " Data Type: " << input0->info()->data_type()
204 << " Input0 shape: " << input0->info()->tensor_shape()
205 << " Input1 shape: " << input1->info()->tensor_shape()
206 << " Input2 shape: " << input2->info()->tensor_shape()
207 << " Output0 shape: " << output0->info()->tensor_shape()
208 << " Output1 shape: " << output1->info()->tensor_shape()
209 << " Output2 shape: " << output2->info()->tensor_shape()
210 << " Output3 shape: " << output3->info()->tensor_shape()
211 << " DetectionPostProcessLayer info: " << detect_info
212 << std::endl);
213
214 auto wrap_function = support::cpp14::make_unique<CPPWrapperFunction>();
215
216 wrap_function->register_function(std::move(func));
217 wrap_function->register_tensor(input0);
218 wrap_function->register_tensor(input1);
219 wrap_function->register_tensor(input2);
220 wrap_function->register_tensor(output0);
221 wrap_function->register_tensor(output1);
222 wrap_function->register_tensor(output2);
223 wrap_function->register_tensor(output3);
224
Georgios Pinitas0b192e82020-02-20 17:09:28 +0000225 return RETURN_UNIQUE_PTR(wrap_function);
Isabella Gottardia7acb3c2019-01-08 13:48:44 +0000226}
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000227} // namespace detail
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000228
229std::unique_ptr<IFunction> CLFunctionFactory::create(INode *node, GraphContext &ctx)
230{
231 if(node == nullptr)
232 {
233 return nullptr;
234 }
235
236 NodeType type = node->type();
237 switch(type)
238 {
239 case NodeType::ActivationLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100240 return detail::create_activation_layer<CLActivationLayer, CLTargetInfo>(*polymorphic_downcast<ActivationLayerNode *>(node));
thecha01e8f05da2020-08-24 17:21:41 +0100241 case NodeType::ArgMinMaxLayer:
242 return detail::create_arg_min_max_layer<CLArgMinMaxLayer, CLTargetInfo>(*polymorphic_downcast<ArgMinMaxLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000243 case NodeType::BatchNormalizationLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100244 return detail::create_batch_normalization_layer<CLBatchNormalizationLayer, CLTargetInfo>(*polymorphic_downcast<BatchNormalizationLayerNode *>(node));
Manuel Bottinid2048ce2018-10-23 17:00:42 +0100245 case NodeType::BoundingBoxTransformLayer:
246 return detail::create_bounding_box_transform_layer<CLBoundingBoxTransform, CLTargetInfo>(*polymorphic_downcast<BoundingBoxTransformLayerNode *>(node));
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100247 case NodeType::ChannelShuffleLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100248 return detail::create_channel_shuffle_layer<CLChannelShuffleLayer, CLTargetInfo>(*polymorphic_downcast<ChannelShuffleLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000249 case NodeType::ConvolutionLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100250 return detail::create_convolution_layer<CLConvolutionLayerFunctions, CLTargetInfo>(*polymorphic_downcast<ConvolutionLayerNode *>(node), ctx);
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100251 case NodeType::DeconvolutionLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100252 return detail::create_deconvolution_layer<CLDeconvolutionLayer, CLTargetInfo>(*polymorphic_downcast<DeconvolutionLayerNode *>(node), ctx);
Georgios Pinitase2220552018-07-20 13:23:44 +0100253 case NodeType::ConcatenateLayer:
254 return detail::create_concatenate_layer<CLConcatenateLayer, CLTargetInfo>(*polymorphic_downcast<ConcatenateLayerNode *>(node));
thecha010a05e6a2020-08-28 18:40:38 +0100255 case NodeType::DepthToSpaceLayer:
256 return detail::create_depth_to_space_layer<CLDepthToSpaceLayer, CLTargetInfo>(*polymorphic_downcast<DepthToSpaceLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000257 case NodeType::DepthwiseConvolutionLayer:
Manuel Bottini05069f02019-09-26 17:18:26 +0100258 return detail::create_depthwise_convolution_layer<CLDepthwiseConvolutionLayer, CLTargetInfo>(*polymorphic_downcast<DepthwiseConvolutionLayerNode *>(node));
Isabella Gottardicd4e9ab2019-11-05 17:50:27 +0000259 case NodeType::DequantizationLayer:
260 return detail::create_dequantization_layer<CLDequantizationLayer, CLTargetInfo>(*polymorphic_downcast<DequantizationLayerNode *>(node));
Isabella Gottardi7234ed82018-11-27 08:51:10 +0000261 case NodeType::DetectionOutputLayer:
262 return detail::create_detection_output_layer<CPPDetectionOutputLayer, CLTargetInfo>(*polymorphic_downcast<DetectionOutputLayerNode *>(node));
Isabella Gottardia7acb3c2019-01-08 13:48:44 +0000263 case NodeType::DetectionPostProcessLayer:
264 return detail::create_detection_post_process_layer<CPPDetectionPostProcessLayer, CLTargetInfo>(*polymorphic_downcast<DetectionPostProcessLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000265 case NodeType::EltwiseLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100266 return detail::create_eltwise_layer<CLEltwiseFunctions, CLTargetInfo>(*polymorphic_downcast<EltwiseLayerNode *>(node));
Sheri Zhang16dddd22020-05-27 15:03:48 +0100267 case NodeType::UnaryEltwiseLayer:
268 return detail::create_unary_eltwise_layer<CLUnaryEltwiseFunctions, CLTargetInfo>(*polymorphic_downcast<UnaryEltwiseLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000269 case NodeType::FlattenLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100270 return detail::create_flatten_layer<CLFlattenLayer, CLTargetInfo>(*polymorphic_downcast<FlattenLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000271 case NodeType::FullyConnectedLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100272 return detail::create_fully_connected_layer<CLFullyConnectedLayer, CLTargetInfo>(*polymorphic_downcast<FullyConnectedLayerNode *>(node), ctx);
giuros01acce5042019-02-21 17:32:34 +0000273 case NodeType::FusedConvolutionBatchNormalizationLayer:
Gian Marco Iodice5dea19e2019-11-08 12:13:48 +0000274 return detail::create_fused_convolution_batch_normalization_layer<CLFusedLayerTypes, CLTargetInfo>(*polymorphic_downcast<FusedConvolutionBatchNormalizationNode *>(node), ctx);
Manuel Bottinibffb41e2019-06-20 16:00:27 +0100275 case NodeType::FusedDepthwiseConvolutionBatchNormalizationLayer:
Gian Marco Iodice5dea19e2019-11-08 12:13:48 +0000276 return detail::create_fused_depthwise_convolution_batch_normalization_layer<CLFusedLayerTypes, CLTargetInfo>(*polymorphic_downcast<FusedDepthwiseConvolutionBatchNormalizationNode *>(node), ctx);
Manuel Bottini5209be52019-02-13 16:34:56 +0000277 case NodeType::GenerateProposalsLayer:
278 return detail::create_generate_proposals_layer<CLGenerateProposalsLayer, CLTargetInfo>(*polymorphic_downcast<GenerateProposalsLayerNode *>(node), ctx);
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000279 case NodeType::NormalizationLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100280 return detail::create_normalization_layer<CLNormalizationLayer, CLTargetInfo>(*polymorphic_downcast<NormalizationLayerNode *>(node), ctx);
Michele Di Giorgio555d1102018-09-12 13:51:59 +0100281 case NodeType::NormalizePlanarYUVLayer:
282 return detail::create_normalize_planar_yuv_layer<CLNormalizePlanarYUVLayer, CLTargetInfo>(*polymorphic_downcast<NormalizePlanarYUVLayerNode *>(node));
Michele Di Giorgio4bb17332018-09-26 13:56:51 +0100283 case NodeType::PadLayer:
284 return detail::create_pad_layer<CLPadLayer, CLTargetInfo>(*polymorphic_downcast<PadLayerNode *>(node));
Georgios Pinitas57c48242018-08-02 13:41:49 +0100285 case NodeType::PermuteLayer:
286 return detail::create_permute_layer<CLPermute, CLTargetInfo>(*polymorphic_downcast<PermuteLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000287 case NodeType::PoolingLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100288 return detail::create_pooling_layer<CLPoolingLayer, CLTargetInfo>(*polymorphic_downcast<PoolingLayerNode *>(node));
Georgios Pinitasf8c47492020-02-04 17:39:59 +0000289 case NodeType::PReluLayer:
290 return detail::create_prelu_layer<CLPReluLayer, CLTargetInfo>(*polymorphic_downcast<PReluLayerNode *>(node));
Giorgio Arena6e9d0e02020-01-03 15:02:04 +0000291 case NodeType::PrintLayer:
292 return detail::create_print_layer<CLTargetInfo>(*polymorphic_downcast<PrintLayerNode *>(node));
Pablo Tello32521432018-11-15 14:43:10 +0000293 case NodeType::PriorBoxLayer:
294 return detail::create_priorbox_layer<CLPriorBoxLayer, CLTargetInfo>(*polymorphic_downcast<PriorBoxLayerNode *>(node));
Isabella Gottardi3db1ba92019-05-17 12:35:20 +0100295 case NodeType::QuantizationLayer:
296 return detail::create_quantization_layer<CLQuantizationLayer, CLTargetInfo>(*polymorphic_downcast<QuantizationLayerNode *>(node));
Gian Marco Iodice23e24792018-09-07 15:32:14 +0100297 case NodeType::ReorgLayer:
298 return detail::create_reorg_layer<CLReorgLayer, CLTargetInfo>(*polymorphic_downcast<ReorgLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000299 case NodeType::ReshapeLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100300 return detail::create_reshape_layer<CLReshapeLayer, CLTargetInfo>(*polymorphic_downcast<ReshapeLayerNode *>(node));
Georgios Pinitas087eaf62018-05-16 15:52:35 +0100301 case NodeType::ResizeLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100302 return detail::create_resize_layer<CLScale, CLTargetInfo>(*polymorphic_downcast<ResizeLayerNode *>(node));
Manuel Bottini3f9d4d72018-10-19 14:04:42 +0100303 case NodeType::ROIAlignLayer:
304 return detail::create_roi_align_layer<CLROIAlignLayer, CLTargetInfo>(*polymorphic_downcast<ROIAlignLayerNode *>(node));
Michele Di Giorgioc30b6682018-09-12 17:44:08 +0100305 case NodeType::SliceLayer:
306 return detail::create_slice_layer<CLSlice, CLTargetInfo>(*polymorphic_downcast<SliceLayerNode *>(node));
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000307 case NodeType::SoftmaxLayer:
Georgios Pinitasda2491f2018-06-01 17:49:09 +0100308 return detail::create_softmax_layer<CLSoftmaxLayer, CLTargetInfo>(*polymorphic_downcast<SoftmaxLayerNode *>(node), ctx);
Michele Di Giorgioec699752019-03-22 15:25:32 +0000309 case NodeType::StackLayer:
310 return detail::create_stack_layer<CLStackLayer, CLTargetInfo>(*polymorphic_downcast<StackLayerNode *>(node));
thecha012bfadd92020-08-12 17:25:51 +0100311 case NodeType::StridedSliceLayer:
312 return detail::create_strided_slice_layer<CLStridedSlice, CLTargetInfo>(*polymorphic_downcast<StridedSliceLayerNode *>(node));
Michalis Spyrou4e1c3f32018-09-20 17:14:03 +0100313 case NodeType::UpsampleLayer:
314 return detail::create_upsample_layer<CLUpsampleLayer, CLTargetInfo>(*polymorphic_downcast<UpsampleLayerNode *>(node), ctx);
Michalis Spyrou96f67692018-09-13 11:39:28 +0100315 case NodeType::YOLOLayer:
316 return detail::create_yolo_layer<CLYOLOLayer, CLTargetInfo>(*polymorphic_downcast<YOLOLayerNode *>(node), ctx);
Georgios Pinitasd8734b52017-12-22 15:27:52 +0000317 default:
318 return nullptr;
319 }
320}
321} // namespace backends
Georgios Pinitasd9eb2752018-04-03 13:44:29 +0100322} // namespace graph
Michele Di Giorgio555d1102018-09-12 13:51:59 +0100323} // namespace arm_compute