xref: /aosp_15_r20/external/ComputeLibrary/tests/CL/Helper.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1 /*
2  * Copyright (c) 2017-2021 Arm Limited.
3  *
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  */
24 #ifndef ARM_COMPUTE_TEST_CL_HELPER_H
25 #define ARM_COMPUTE_TEST_CL_HELPER_H
26 
27 #include "arm_compute/runtime/CL/CLScheduler.h"
28 #include "arm_compute/runtime/CL/ICLSimpleFunction.h"
29 #include "arm_compute/runtime/CL/functions/CLFill.h"
30 #include "arm_compute/runtime/IFunction.h"
31 #include "src/core/CL/kernels/CLFillBorderKernel.h"
32 #include "src/gpu/cl/IClOperator.h"
33 #include "src/gpu/cl/operators/ClFill.h"
34 
35 #include "src/core/CL/ICLKernel.h"
36 #include "support/Cast.h"
37 
38 #include <memory>
39 
40 namespace arm_compute
41 {
42 namespace test
43 {
44 /** This template synthetizes a simple IOperator which runs the given kernel K */
45 template <typename K>
46 class CLSynthetizeOperator : public opencl::IClOperator
47 {
48 public:
49     /** Configure the kernel.
50      *
51      * @param[in] args Configuration arguments.
52      */
53     template <typename... Args>
configure(Args &&...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>
configure(GPUTarget gpu_target,Args &&...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>
validate(Args &&...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 */
85 template <typename K, int bordersize>
86 class CLSynthetizeOperatorInitOutputWithZeroAndWithZeroConstantBorder : public opencl::IClOperator
87 {
88 public:
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>
configure(T first,T second,Args &&...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:
run(ITensorPack & tensors)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 
118 private:
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 
124 /** This template synthetizes an ICLSimpleFunction which runs the given kernel K */
125 template <typename K>
126 class CLSynthetizeFunction : public ICLSimpleFunction
127 {
128 public:
129     /** Configure the kernel.
130      *
131      * @param[in] args Configuration arguments.
132      */
133     template <typename... Args>
configure(Args &&...args)134     void configure(Args &&... args)
135     {
136         auto k = std::make_unique<K>();
137         k->configure(std::forward<Args>(args)...);
138         _kernel = std::move(k);
139     }
140     /** 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>
configure(GPUTarget gpu_target,Args &&...args)146     void configure(GPUTarget gpu_target, Args &&... args)
147     {
148         auto k = std::make_unique<K>();
149         k->set_target(gpu_target);
150         k->configure(std::forward<Args>(args)...);
151         _kernel = std::move(k);
152     }
153     /** Validate input arguments
154      *
155      * @param[in] args Configuration arguments.
156      */
157     template <typename... Args>
validate(Args &&...args)158     static Status validate(Args &&... args)
159     {
160         return K::validate(std::forward<Args>(args)...);
161     }
162 };
163 
164 /** As above but this also setups a Zero border on the input tensor of the specified bordersize */
165 template <typename K, int bordersize>
166 class CLSynthetizeFunctionWithZeroConstantBorder : public ICLSimpleFunction
167 {
168 public:
169     /** Configure the kernel.
170      *
171      * @param[in] first First configuration argument.
172      * @param[in] args  Rest of the configuration arguments.
173      */
174     template <typename T, typename... Args>
configure(T first,Args &&...args)175     void configure(T first, Args &&... args)
176     {
177         auto k = std::make_unique<K>();
178         k->configure(first, std::forward<Args>(args)...);
179         _kernel = std::move(k);
180         _border_handler->configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
181     }
182 };
183 
184 /** As above but this also initializes to zero the input tensor */
185 template <typename K, int bordersize>
186 class CLSynthetizeFunctionInitOutputWithZeroAndWithZeroConstantBorder : public IFunction
187 {
188 public:
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>
configure(T first,T second,Args &&...args)196     void configure(T first, T second, Args &&... args)
197     {
198         auto k = std::make_unique<K>();
199         k->set_target(CLScheduler::get().target());
200         k->configure(first, second, std::forward<Args>(args)...);
201         _kernel = std::move(k);
202         _border_handler.configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
203         _fill.configure(second, PixelValue());
204     }
205 
206     // Inherited method overridden:
run()207     void run() override final
208     {
209         ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The CL kernel or function isn't configured");
210 
211         _fill.run();
212         CLScheduler::get().enqueue(_border_handler, false);
213         CLScheduler::get().enqueue(*_kernel);
214     }
215 
216 private:
217     CLFill                     _fill{};           /**< Kernel to initialize the tensor */
218     CLFillBorderKernel         _border_handler{}; /**< Kernel to handle  borders */
219     std::unique_ptr<ICLKernel> _kernel{};         /**< Kernel to run */
220 };
221 
222 /** As above but this also setups a Zero border on the input tensor of the kernel's bordersize */
223 template <typename K>
224 class ClSynthetizeOperatorWithBorder : public opencl::IClOperator
225 {
226 public:
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>
configure(T first,Args &&...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 
run(ITensorPack & tensors)244     void run(ITensorPack &tensors) override
245     {
246         CLScheduler::get().enqueue(*_border_handler);
247         CLScheduler::get().enqueue_op(*_kernel, tensors);
248     }
249 
250 private:
251     std::unique_ptr<ICLKernel> _border_handler{ nullptr }; /**< Kernel to handle  borders */
252     std::unique_ptr<ICLKernel> _kernel{};                  /**< Kernel to run */
253 };
254 } // namespace test
255 } // namespace arm_compute
256 #endif /* ARM_COMPUTE_TEST_CL_HELPER_H */
257