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