blob: d9d95e5c9211b7c7896e7e92f65ff634658a7c3d [file] [log] [blame]
David Monahan8a570462023-11-22 13:24:25 +00001//
David Monahanbd738082023-12-08 12:50:02 +00002// Copyright © 2022-2024 Arm Ltd and Contributors. All rights reserved.
David Monahan8a570462023-11-22 13:24:25 +00003// SPDX-License-Identifier: MIT
4//
5
6#include "GpuFsaLayerSupport.hpp"
7
8#include <armnn/Types.hpp>
9#include <armnn/utility/IgnoreUnused.hpp>
10#include <armnn/utility/PolymorphicDowncast.hpp>
11
12#if defined(ARMCOMPUTEGPUFSA_ENABLED)
Tracy Narinebc5a5d52024-02-06 15:22:41 +000013#include "layers/GpuFsaCast.hpp"
David Monahanbd738082023-12-08 12:50:02 +000014#include "layers/GpuFsaConvolution2d.hpp"
Tianle Chengfbfa49e2024-01-23 11:21:48 +000015#include "layers/GpuFsaDepthwiseConvolution2d.hpp"
Tracy Narinee7d27852024-01-26 09:13:19 +000016#include "layers/GpuFsaElementwiseBinaryAdd.hpp"
John Mcloughlin829e13e2024-01-31 11:00:27 +000017#include "layers/GpuFsaElementwiseBinarySub.hpp"
Teresa Charlina52bca22024-02-01 17:36:48 +000018#include "layers/GpuFsaPooling2d.hpp"
David Monahan8a570462023-11-22 13:24:25 +000019#endif
20
21#include <vector>
22
23namespace armnn
24{
25
26template<typename ... Args>
27bool IsGpuFsaBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
28{
29 IgnoreUnused(reasonIfUnsupported, (args)...);
30#if defined(ARMCOMPUTEGPUFSA_ENABLED)
31 return true;
32#else
33 if (reasonIfUnsupported)
34 {
35 reasonIfUnsupported.value() = "The armnn library has been built without CL support";
36 }
37 return false;
38#endif
39}
40
41#if defined(ARMCOMPUTEGPUFSA_ENABLED)
42#define FORWARD_GPUFSA_LAYER_SUPPORT_FUNC(expr) (expr)
43#else
44#define FORWARD_GPUFSA_LAYER_SUPPORT_FUNC(expr) IsGpuFsaBackendSupported(reasonIfUnsupported)
45#endif
46
47#if defined(ARMCOMPUTEGPUFSA_ENABLED)
48template<class FuncType, class... Args>
49inline bool CheckIsLayerSupported(FuncType&& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
50{
51 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
52 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
53 if (!supported && reasonIfUnsupported)
54 {
55 reasonIfUnsupported.value() = aclStatus.error_description();
56 }
57 return supported;
58}
59
60#define FORWARD_LAYER_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
61 return CheckIsLayerSupported(func, reasonIfUnsupported, __VA_ARGS__);
62#else
63#define FORWARD_LAYER_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
64 return IsGpuFsaBackendSupported(reasonIfUnsupported, __VA_ARGS__);
65#endif
66
67bool GpuFsaLayerSupport::IsLayerSupported(const LayerType& type,
68 const std::vector<TensorInfo>& infos,
69 const BaseDescriptor& descriptor,
70 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
71 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmInputParamsInfo,
72 Optional<std::string&> reasonIfUnsupported) const
73{
74 IgnoreUnused(lstmParamsInfo);
75 IgnoreUnused(quantizedLstmInputParamsInfo);
76
Tracy Narinebc5a5d52024-02-06 15:22:41 +000077 switch (type)
78 {
79 case LayerType::Cast:
80 {
81 if (infos.size() != 2)
82 {
83 throw InvalidArgumentException("Invalid number of cast TensorInfos. "
84 "TensorInfos should be of format: {input, output}.");
85 }
86 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaCastValidate,
87 reasonIfUnsupported,
88 infos[0],
89 infos[1]);
90 }
David Monahan8a570462023-11-22 13:24:25 +000091 case LayerType::Convolution2d:
92 {
93 if (infos.size() != 4)
94 {
95 throw InvalidArgumentException("Invalid number of Convolution2d TensorInfos. "
96 "TensorInfos should be of format: {input, output, weights, biases}.");
97 }
98
Tracy Narinee7d27852024-01-26 09:13:19 +000099 auto desc = PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor);
David Monahan8a570462023-11-22 13:24:25 +0000100 if (infos[3] == TensorInfo())
101 {
102 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaConvolution2dValidate,
103 reasonIfUnsupported,
104 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000105 *desc,
David Monahan8a570462023-11-22 13:24:25 +0000106 infos[2],
107 EmptyOptional());
108 }
109 else
110 {
111 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaConvolution2dValidate,
112 reasonIfUnsupported,
113 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000114 *desc,
David Monahan8a570462023-11-22 13:24:25 +0000115 infos[2],
116 infos[3]);
117 }
118 }
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000119 case LayerType::DepthwiseConvolution2d:
120 {
121 if (infos.size() != 4)
122 {
123 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2dDescriptor TensorInfos. "
124 "TensorInfos should be of format: {input, output, weights, biases}.");
125 }
126
Tracy Narinebc5a5d52024-02-06 15:22:41 +0000127 auto desc = PolymorphicDowncast<const DepthwiseConvolution2dDescriptor*>(&descriptor);
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000128 if (infos[3] == TensorInfo())
129 {
130 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaDepthwiseConvolution2dValidate,
131 reasonIfUnsupported,
132 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000133 *desc,
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000134 infos[2],
135 EmptyOptional());
136 }
137 else
138 {
139 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaDepthwiseConvolution2dValidate,
140 reasonIfUnsupported,
141 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000142 *desc,
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000143 infos[2],
144 infos[3]);
145 }
146 }
Tracy Narinee7d27852024-01-26 09:13:19 +0000147 case LayerType::ElementwiseBinary:
148 {
149 if (infos.size() != 3)
150 {
151 throw InvalidArgumentException("Invalid number of ElementwiseBinary TensorInfos. "
152 "TensorInfos should be of format: {input0, input1, output0}.");
153 }
154
Tracy Narinebc5a5d52024-02-06 15:22:41 +0000155 auto desc = PolymorphicDowncast<const ElementwiseBinaryDescriptor*>(&descriptor);
Tracy Narinee7d27852024-01-26 09:13:19 +0000156 if (desc->m_Operation == BinaryOperation::Add)
157 {
158 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaElementwiseBinaryAddValidate,
159 reasonIfUnsupported,
160 infos[0],
161 infos[1]);
162 }
John Mcloughlin829e13e2024-01-31 11:00:27 +0000163 else if (desc->m_Operation == BinaryOperation::Sub)
164 {
165 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaElementwiseBinarySubValidate,
166 reasonIfUnsupported,
167 infos[0],
168 infos[1]);
169 }
Tracy Narinee7d27852024-01-26 09:13:19 +0000170 else
171 {
172 throw InvalidArgumentException("Invalid ElementwiseBinary BinaryOperation operation.");
173 }
Teresa Charlina52bca22024-02-01 17:36:48 +0000174 }
175 case LayerType::Pooling2d:
176 {
177 if (infos.size() != 2)
178 {
179 throw InvalidArgumentException("Invalid number of Pooling2d TensorInfos. "
180 "TensorInfos should be of format: {input, output}.");
181 }
182
183 auto desc = PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor);
184
185 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaPooling2dValidate,
186 reasonIfUnsupported,
187 infos[0],
188 *desc);
Tracy Narinee7d27852024-01-26 09:13:19 +0000189 }
David Monahan8a570462023-11-22 13:24:25 +0000190 case LayerType::Constant:
191 case LayerType::Input:
192 case LayerType::Output:
193 return IsGpuFsaBackendSupported(reasonIfUnsupported, infos[0]);
194 default:
195 // Layers not supported in the GpuFsa backend.
196 return false;
197 }
198}
199
200} // namespace armnn