blob: b73b3e9088b7fdbc449a18a60a4a4543e7617f38 [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)
David Monahanbd738082023-12-08 12:50:02 +000013#include "layers/GpuFsaConvolution2d.hpp"
Tianle Chengfbfa49e2024-01-23 11:21:48 +000014#include "layers/GpuFsaDepthwiseConvolution2d.hpp"
Tracy Narinee7d27852024-01-26 09:13:19 +000015#include "layers/GpuFsaElementwiseBinaryAdd.hpp"
John Mcloughlin829e13e2024-01-31 11:00:27 +000016#include "layers/GpuFsaElementwiseBinarySub.hpp"
Teresa Charlina52bca22024-02-01 17:36:48 +000017#include "layers/GpuFsaPooling2d.hpp"
David Monahan8a570462023-11-22 13:24:25 +000018#endif
19
20#include <vector>
21
22namespace armnn
23{
24
25template<typename ... Args>
26bool IsGpuFsaBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
27{
28 IgnoreUnused(reasonIfUnsupported, (args)...);
29#if defined(ARMCOMPUTEGPUFSA_ENABLED)
30 return true;
31#else
32 if (reasonIfUnsupported)
33 {
34 reasonIfUnsupported.value() = "The armnn library has been built without CL support";
35 }
36 return false;
37#endif
38}
39
40#if defined(ARMCOMPUTEGPUFSA_ENABLED)
41#define FORWARD_GPUFSA_LAYER_SUPPORT_FUNC(expr) (expr)
42#else
43#define FORWARD_GPUFSA_LAYER_SUPPORT_FUNC(expr) IsGpuFsaBackendSupported(reasonIfUnsupported)
44#endif
45
46#if defined(ARMCOMPUTEGPUFSA_ENABLED)
47template<class FuncType, class... Args>
48inline bool CheckIsLayerSupported(FuncType&& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
49{
50 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
51 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
52 if (!supported && reasonIfUnsupported)
53 {
54 reasonIfUnsupported.value() = aclStatus.error_description();
55 }
56 return supported;
57}
58
59#define FORWARD_LAYER_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
60 return CheckIsLayerSupported(func, reasonIfUnsupported, __VA_ARGS__);
61#else
62#define FORWARD_LAYER_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
63 return IsGpuFsaBackendSupported(reasonIfUnsupported, __VA_ARGS__);
64#endif
65
66bool GpuFsaLayerSupport::IsLayerSupported(const LayerType& type,
67 const std::vector<TensorInfo>& infos,
68 const BaseDescriptor& descriptor,
69 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
70 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmInputParamsInfo,
71 Optional<std::string&> reasonIfUnsupported) const
72{
73 IgnoreUnused(lstmParamsInfo);
74 IgnoreUnused(quantizedLstmInputParamsInfo);
75
76 switch (type) {
77 case LayerType::Convolution2d:
78 {
79 if (infos.size() != 4)
80 {
81 throw InvalidArgumentException("Invalid number of Convolution2d TensorInfos. "
82 "TensorInfos should be of format: {input, output, weights, biases}.");
83 }
84
Tracy Narinee7d27852024-01-26 09:13:19 +000085 auto desc = PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor);
David Monahan8a570462023-11-22 13:24:25 +000086 if (infos[3] == TensorInfo())
87 {
88 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaConvolution2dValidate,
89 reasonIfUnsupported,
90 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +000091 *desc,
David Monahan8a570462023-11-22 13:24:25 +000092 infos[2],
93 EmptyOptional());
94 }
95 else
96 {
97 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaConvolution2dValidate,
98 reasonIfUnsupported,
99 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000100 *desc,
David Monahan8a570462023-11-22 13:24:25 +0000101 infos[2],
102 infos[3]);
103 }
104 }
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000105 case LayerType::DepthwiseConvolution2d:
106 {
107 if (infos.size() != 4)
108 {
109 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2dDescriptor TensorInfos. "
110 "TensorInfos should be of format: {input, output, weights, biases}.");
111 }
112
Tracy Narinee7d27852024-01-26 09:13:19 +0000113 auto desc = PolymorphicDowncast<const DepthwiseConvolution2dDescriptor *>(&descriptor);
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000114 if (infos[3] == TensorInfo())
115 {
116 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaDepthwiseConvolution2dValidate,
117 reasonIfUnsupported,
118 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000119 *desc,
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000120 infos[2],
121 EmptyOptional());
122 }
123 else
124 {
125 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaDepthwiseConvolution2dValidate,
126 reasonIfUnsupported,
127 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000128 *desc,
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000129 infos[2],
130 infos[3]);
131 }
132 }
Tracy Narinee7d27852024-01-26 09:13:19 +0000133 case LayerType::ElementwiseBinary:
134 {
135 if (infos.size() != 3)
136 {
137 throw InvalidArgumentException("Invalid number of ElementwiseBinary TensorInfos. "
138 "TensorInfos should be of format: {input0, input1, output0}.");
139 }
140
141 auto desc = PolymorphicDowncast<const ElementwiseBinaryDescriptor *>(&descriptor);
142 if (desc->m_Operation == BinaryOperation::Add)
143 {
144 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaElementwiseBinaryAddValidate,
145 reasonIfUnsupported,
146 infos[0],
147 infos[1]);
148 }
John Mcloughlin829e13e2024-01-31 11:00:27 +0000149 else if (desc->m_Operation == BinaryOperation::Sub)
150 {
151 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaElementwiseBinarySubValidate,
152 reasonIfUnsupported,
153 infos[0],
154 infos[1]);
155 }
Tracy Narinee7d27852024-01-26 09:13:19 +0000156 else
157 {
158 throw InvalidArgumentException("Invalid ElementwiseBinary BinaryOperation operation.");
159 }
Teresa Charlina52bca22024-02-01 17:36:48 +0000160 }
161 case LayerType::Pooling2d:
162 {
163 if (infos.size() != 2)
164 {
165 throw InvalidArgumentException("Invalid number of Pooling2d TensorInfos. "
166 "TensorInfos should be of format: {input, output}.");
167 }
168
169 auto desc = PolymorphicDowncast<const Pooling2dDescriptor*>(&descriptor);
170
171 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaPooling2dValidate,
172 reasonIfUnsupported,
173 infos[0],
174 *desc);
Tracy Narinee7d27852024-01-26 09:13:19 +0000175 }
David Monahan8a570462023-11-22 13:24:25 +0000176 case LayerType::Constant:
177 case LayerType::Input:
178 case LayerType::Output:
179 return IsGpuFsaBackendSupported(reasonIfUnsupported, infos[0]);
180 default:
181 // Layers not supported in the GpuFsa backend.
182 return false;
183 }
184}
185
186} // namespace armnn