blob: 2e5c7d5a5380c5ebeba7671a40553767102afaec [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"
David Monahan8a570462023-11-22 13:24:25 +000017#endif
18
19#include <vector>
20
21namespace armnn
22{
23
24template<typename ... Args>
25bool IsGpuFsaBackendSupported(Optional<std::string&> reasonIfUnsupported, Args... args)
26{
27 IgnoreUnused(reasonIfUnsupported, (args)...);
28#if defined(ARMCOMPUTEGPUFSA_ENABLED)
29 return true;
30#else
31 if (reasonIfUnsupported)
32 {
33 reasonIfUnsupported.value() = "The armnn library has been built without CL support";
34 }
35 return false;
36#endif
37}
38
39#if defined(ARMCOMPUTEGPUFSA_ENABLED)
40#define FORWARD_GPUFSA_LAYER_SUPPORT_FUNC(expr) (expr)
41#else
42#define FORWARD_GPUFSA_LAYER_SUPPORT_FUNC(expr) IsGpuFsaBackendSupported(reasonIfUnsupported)
43#endif
44
45#if defined(ARMCOMPUTEGPUFSA_ENABLED)
46template<class FuncType, class... Args>
47inline bool CheckIsLayerSupported(FuncType&& func, Optional<std::string&> reasonIfUnsupported, Args&&... args)
48{
49 arm_compute::Status aclStatus = func(std::forward<Args>(args)...);
50 const bool supported = (aclStatus.error_code() == arm_compute::ErrorCode::OK);
51 if (!supported && reasonIfUnsupported)
52 {
53 reasonIfUnsupported.value() = aclStatus.error_description();
54 }
55 return supported;
56}
57
58#define FORWARD_LAYER_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
59 return CheckIsLayerSupported(func, reasonIfUnsupported, __VA_ARGS__);
60#else
61#define FORWARD_LAYER_VALIDATE_FUNC(func, reasonIfUnsupported, ...) \
62 return IsGpuFsaBackendSupported(reasonIfUnsupported, __VA_ARGS__);
63#endif
64
65bool GpuFsaLayerSupport::IsLayerSupported(const LayerType& type,
66 const std::vector<TensorInfo>& infos,
67 const BaseDescriptor& descriptor,
68 const Optional<LstmInputParamsInfo>& lstmParamsInfo,
69 const Optional<QuantizedLstmInputParamsInfo>& quantizedLstmInputParamsInfo,
70 Optional<std::string&> reasonIfUnsupported) const
71{
72 IgnoreUnused(lstmParamsInfo);
73 IgnoreUnused(quantizedLstmInputParamsInfo);
74
75 switch (type) {
76 case LayerType::Convolution2d:
77 {
78 if (infos.size() != 4)
79 {
80 throw InvalidArgumentException("Invalid number of Convolution2d TensorInfos. "
81 "TensorInfos should be of format: {input, output, weights, biases}.");
82 }
83
Tracy Narinee7d27852024-01-26 09:13:19 +000084 auto desc = PolymorphicDowncast<const Convolution2dDescriptor*>(&descriptor);
David Monahan8a570462023-11-22 13:24:25 +000085 if (infos[3] == TensorInfo())
86 {
87 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaConvolution2dValidate,
88 reasonIfUnsupported,
89 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +000090 *desc,
David Monahan8a570462023-11-22 13:24:25 +000091 infos[2],
92 EmptyOptional());
93 }
94 else
95 {
96 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaConvolution2dValidate,
97 reasonIfUnsupported,
98 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +000099 *desc,
David Monahan8a570462023-11-22 13:24:25 +0000100 infos[2],
101 infos[3]);
102 }
103 }
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000104 case LayerType::DepthwiseConvolution2d:
105 {
106 if (infos.size() != 4)
107 {
108 throw InvalidArgumentException("Invalid number of DepthwiseConvolution2dDescriptor TensorInfos. "
109 "TensorInfos should be of format: {input, output, weights, biases}.");
110 }
111
Tracy Narinee7d27852024-01-26 09:13:19 +0000112 auto desc = PolymorphicDowncast<const DepthwiseConvolution2dDescriptor *>(&descriptor);
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000113 if (infos[3] == TensorInfo())
114 {
115 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaDepthwiseConvolution2dValidate,
116 reasonIfUnsupported,
117 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000118 *desc,
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000119 infos[2],
120 EmptyOptional());
121 }
122 else
123 {
124 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaDepthwiseConvolution2dValidate,
125 reasonIfUnsupported,
126 infos[0],
Tracy Narinee7d27852024-01-26 09:13:19 +0000127 *desc,
Tianle Chengfbfa49e2024-01-23 11:21:48 +0000128 infos[2],
129 infos[3]);
130 }
131 }
Tracy Narinee7d27852024-01-26 09:13:19 +0000132 case LayerType::ElementwiseBinary:
133 {
134 if (infos.size() != 3)
135 {
136 throw InvalidArgumentException("Invalid number of ElementwiseBinary TensorInfos. "
137 "TensorInfos should be of format: {input0, input1, output0}.");
138 }
139
140 auto desc = PolymorphicDowncast<const ElementwiseBinaryDescriptor *>(&descriptor);
141 if (desc->m_Operation == BinaryOperation::Add)
142 {
143 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaElementwiseBinaryAddValidate,
144 reasonIfUnsupported,
145 infos[0],
146 infos[1]);
147 }
John Mcloughlin829e13e2024-01-31 11:00:27 +0000148 else if (desc->m_Operation == BinaryOperation::Sub)
149 {
150 FORWARD_LAYER_VALIDATE_FUNC(GpuFsaElementwiseBinarySubValidate,
151 reasonIfUnsupported,
152 infos[0],
153 infos[1]);
154 }
Tracy Narinee7d27852024-01-26 09:13:19 +0000155 else
156 {
157 throw InvalidArgumentException("Invalid ElementwiseBinary BinaryOperation operation.");
158 }
159 return false;
160 }
David Monahan8a570462023-11-22 13:24:25 +0000161 case LayerType::Constant:
162 case LayerType::Input:
163 case LayerType::Output:
164 return IsGpuFsaBackendSupported(reasonIfUnsupported, infos[0]);
165 default:
166 // Layers not supported in the GpuFsa backend.
167 return false;
168 }
169}
170
171} // namespace armnn