blob: dd5e8647b045c8b125338e6c8c462d53b56a1a1f [file] [log] [blame]
Pablo Tello1d1c0262017-12-08 16:02:38 +00001/*
Sheri Zhang7e20e292021-02-02 11:49:34 +00002 * Copyright (c) 2017-2021 Arm Limited.
Pablo Tello1d1c0262017-12-08 16:02:38 +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 */
Michalis Spyrouf4643372019-11-29 16:17:13 +000024#ifndef ARM_COMPUTE_TEST_CL_HELPER_H
25#define ARM_COMPUTE_TEST_CL_HELPER_H
Pablo Tello1d1c0262017-12-08 16:02:38 +000026
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +000027#include "arm_compute/runtime/CL/CLScheduler.h"
Pablo Tello1d1c0262017-12-08 16:02:38 +000028#include "arm_compute/runtime/CL/ICLSimpleFunction.h"
Sheri Zhang7e20e292021-02-02 11:49:34 +000029#include "arm_compute/runtime/CL/functions/CLFill.h"
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +000030#include "arm_compute/runtime/IFunction.h"
Sheri Zhang7e20e292021-02-02 11:49:34 +000031#include "src/core/CL/kernels/CLFillBorderKernel.h"
Georgios Pinitas7891a732021-08-20 21:39:25 +010032#include "src/gpu/cl/IClOperator.h"
33#include "src/gpu/cl/operators/ClFill.h"
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +010034
35#include "src/core/CL/ICLKernel.h"
Georgios Pinitas856f66e2021-04-22 21:13:21 +010036#include "support/Cast.h"
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +010037
Georgios Pinitas40f51a62020-11-21 03:04:18 +000038#include <memory>
Pablo Tello1d1c0262017-12-08 16:02:38 +000039
40namespace arm_compute
41{
42namespace test
43{
Georgios Pinitas856f66e2021-04-22 21:13:21 +010044/** This template synthetizes a simple IOperator which runs the given kernel K */
45template <typename K>
46class CLSynthetizeOperator : public opencl::IClOperator
47{
48public:
49 /** Configure the kernel.
50 *
51 * @param[in] args Configuration arguments.
52 */
53 template <typename... Args>
54 void configure(Args &&... args)
55 {
56 auto k = std::make_unique<K>();
57 k->configure(CLKernelLibrary::get().get_compile_context(), std::forward<Args>(args)...);
58 _kernel = std::move(k);
59 }
60 /** Configure the kernel setting the GPU target as well
61 *
62 * @param[in] gpu_target GPUTarget to set
63 * @param[in] args Configuration arguments.
64 */
65 template <typename... Args>
66 void configure(GPUTarget gpu_target, Args &&... args)
67 {
68 auto k = std::make_unique<K>();
69 k->set_target(gpu_target);
70 k->configure(CLKernelLibrary::get().get_compile_context(), std::forward<Args>(args)...);
71 _kernel = std::move(k);
72 }
73 /** Validate input arguments
74 *
75 * @param[in] args Configuration arguments.
76 */
77 template <typename... Args>
78 static Status validate(Args &&... args)
79 {
80 return K::validate(std::forward<Args>(args)...);
81 }
82};
83
84/** As above but this also initializes to zero the input tensor */
85template <typename K, int bordersize>
86class CLSynthetizeOperatorInitOutputWithZeroAndWithZeroConstantBorder : public opencl::IClOperator
87{
88public:
89 /** Configure the kernel.
90 *
91 * @param[in] first First input argument.
92 * @param[in] second Second input argument.
93 * @param[in] args Rest of the configuration arguments.
94 */
95 template <typename T, typename... Args>
96 void configure(T first, T second, Args &&... args)
97 {
98 auto cctx = CLKernelLibrary::get().get_compile_context();
99 auto k = std::make_unique<K>();
100 k->set_target(CLScheduler::get().target());
101 k->configure(cctx, first, second, std::forward<Args>(args)...);
102 _kernel = std::move(k);
103 _border_handler.configure(cctx, first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
104 _fill.configure(cctx, second, PixelValue());
105 }
106
107 // Inherited method overridden:
108 void run(ITensorPack &tensors) override final
109 {
110 ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The CL kernel or function isn't configured");
111
112 ITensorPack fill_pack = { { ACL_SRC, tensors.get_tensor(TensorType::ACL_DST) } };
113 _fill.run(fill_pack);
114 CLScheduler::get().enqueue_op(_border_handler, tensors);
115 CLScheduler::get().enqueue_op(*_kernel, tensors);
116 }
117
118private:
119 opencl::ClFill _fill{}; /**< Kernel to initialize the tensor */
120 CLFillBorderKernel _border_handler{}; /**< Kernel to handle borders */
121 std::unique_ptr<ICLKernel> _kernel{}; /**< Kernel to run */
122};
123
Alex Gildayc357c472018-03-21 13:54:09 +0000124/** This template synthetizes an ICLSimpleFunction which runs the given kernel K */
Pablo Tello1d1c0262017-12-08 16:02:38 +0000125template <typename K>
126class CLSynthetizeFunction : public ICLSimpleFunction
127{
128public:
Alex Gildayc357c472018-03-21 13:54:09 +0000129 /** Configure the kernel.
130 *
131 * @param[in] args Configuration arguments.
132 */
Pablo Tello1d1c0262017-12-08 16:02:38 +0000133 template <typename... Args>
134 void configure(Args &&... args)
135 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000136 auto k = std::make_unique<K>();
Pablo Tello1d1c0262017-12-08 16:02:38 +0000137 k->configure(std::forward<Args>(args)...);
138 _kernel = std::move(k);
139 }
Gian Marco Iodiced1f54762019-07-19 09:54:47 +0100140 /** Configure the kernel setting the GPU target as well
141 *
142 * @param[in] gpu_target GPUTarget to set
143 * @param[in] args Configuration arguments.
144 */
145 template <typename... Args>
146 void configure(GPUTarget gpu_target, Args &&... args)
147 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000148 auto k = std::make_unique<K>();
Gian Marco Iodiced1f54762019-07-19 09:54:47 +0100149 k->set_target(gpu_target);
150 k->configure(std::forward<Args>(args)...);
151 _kernel = std::move(k);
152 }
Pablo Tello4a626a72018-04-04 10:01:14 +0100153 /** Validate input arguments
154 *
155 * @param[in] args Configuration arguments.
156 */
157 template <typename... Args>
158 static Status validate(Args &&... args)
159 {
160 return K::validate(std::forward<Args>(args)...);
161 }
Pablo Tello1d1c0262017-12-08 16:02:38 +0000162};
163
Alex Gildayc357c472018-03-21 13:54:09 +0000164/** As above but this also setups a Zero border on the input tensor of the specified bordersize */
Pablo Tello1d1c0262017-12-08 16:02:38 +0000165template <typename K, int bordersize>
166class CLSynthetizeFunctionWithZeroConstantBorder : public ICLSimpleFunction
167{
168public:
Alex Gildayc357c472018-03-21 13:54:09 +0000169 /** Configure the kernel.
170 *
171 * @param[in] first First configuration argument.
172 * @param[in] args Rest of the configuration arguments.
173 */
Pablo Tello1d1c0262017-12-08 16:02:38 +0000174 template <typename T, typename... Args>
175 void configure(T first, Args &&... args)
176 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000177 auto k = std::make_unique<K>();
Pablo Tello1d1c0262017-12-08 16:02:38 +0000178 k->configure(first, std::forward<Args>(args)...);
179 _kernel = std::move(k);
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +0100180 _border_handler->configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
Pablo Tello1d1c0262017-12-08 16:02:38 +0000181 }
182};
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +0000183
184/** As above but this also initializes to zero the input tensor */
185template <typename K, int bordersize>
186class CLSynthetizeFunctionInitOutputWithZeroAndWithZeroConstantBorder : public IFunction
187{
188public:
189 /** Configure the kernel.
190 *
191 * @param[in] first First input argument.
192 * @param[in] second Second input argument.
193 * @param[in] args Rest of the configuration arguments.
194 */
195 template <typename T, typename... Args>
196 void configure(T first, T second, Args &&... args)
197 {
Georgios Pinitas40f51a62020-11-21 03:04:18 +0000198 auto k = std::make_unique<K>();
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +0000199 k->set_target(CLScheduler::get().target());
200 k->configure(first, second, std::forward<Args>(args)...);
201 _kernel = std::move(k);
Manuel Bottini55e16782019-01-15 13:21:57 +0000202 _border_handler.configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
Sheri Zhang7e20e292021-02-02 11:49:34 +0000203 _fill.configure(second, PixelValue());
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +0000204 }
205
206 // Inherited method overridden:
207 void run() override final
208 {
209 ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The CL kernel or function isn't configured");
210
Sheri Zhang7e20e292021-02-02 11:49:34 +0000211 _fill.run();
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +0000212 CLScheduler::get().enqueue(_border_handler, false);
213 CLScheduler::get().enqueue(*_kernel);
214 }
215
216private:
Sheri Zhang7e20e292021-02-02 11:49:34 +0000217 CLFill _fill{}; /**< Kernel to initialize the tensor */
Gian Marco Iodice5ba5e092018-12-06 17:13:09 +0000218 CLFillBorderKernel _border_handler{}; /**< Kernel to handle borders */
219 std::unique_ptr<ICLKernel> _kernel{}; /**< Kernel to run */
220};
Manuel Bottini7b237322021-07-14 17:07:23 +0100221
222/** As above but this also setups a Zero border on the input tensor of the kernel's bordersize */
223template <typename K>
224class ClSynthetizeOperatorWithBorder : public opencl::IClOperator
225{
226public:
227 /** Configure the kernel.
228 *
229 * @param[in] first First configuration argument.
230 * @param[in] args Rest of the configuration arguments.
231 */
232 template <typename T, typename... Args>
233 void configure(T first, Args &&... args)
234 {
235 auto k = std::make_unique<K>();
236 k->configure(CLKernelLibrary::get().get_compile_context(), first, std::forward<Args>(args)...);
237 _kernel = std::move(k);
238
239 auto b = std::make_unique<CLFillBorderKernel>();
240 b->configure(CLKernelLibrary::get().get_compile_context(), first, BorderSize(_kernel->border_size()), BorderMode::CONSTANT, PixelValue());
241 _border_handler = std::move(b);
242 }
243
244 void run(ITensorPack &tensors) override
245 {
246 CLScheduler::get().enqueue(*_border_handler);
247 CLScheduler::get().enqueue_op(*_kernel, tensors);
248 }
249
250private:
251 std::unique_ptr<ICLKernel> _border_handler{ nullptr }; /**< Kernel to handle borders */
252 std::unique_ptr<ICLKernel> _kernel{}; /**< Kernel to run */
253};
Pablo Tello1d1c0262017-12-08 16:02:38 +0000254} // namespace test
255} // namespace arm_compute
Michalis Spyrouf4643372019-11-29 16:17:13 +0000256#endif /* ARM_COMPUTE_TEST_CL_HELPER_H */