xref: /aosp_15_r20/external/ComputeLibrary/tests/CL/Helper.h (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1*c217d954SCole Faust /*
2*c217d954SCole Faust  * Copyright (c) 2017-2021 Arm Limited.
3*c217d954SCole Faust  *
4*c217d954SCole Faust  * SPDX-License-Identifier: MIT
5*c217d954SCole Faust  *
6*c217d954SCole Faust  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*c217d954SCole Faust  * of this software and associated documentation files (the "Software"), to
8*c217d954SCole Faust  * deal in the Software without restriction, including without limitation the
9*c217d954SCole Faust  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*c217d954SCole Faust  * sell copies of the Software, and to permit persons to whom the Software is
11*c217d954SCole Faust  * furnished to do so, subject to the following conditions:
12*c217d954SCole Faust  *
13*c217d954SCole Faust  * The above copyright notice and this permission notice shall be included in all
14*c217d954SCole Faust  * copies or substantial portions of the Software.
15*c217d954SCole Faust  *
16*c217d954SCole Faust  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*c217d954SCole Faust  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*c217d954SCole Faust  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*c217d954SCole Faust  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*c217d954SCole Faust  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21*c217d954SCole Faust  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*c217d954SCole Faust  * SOFTWARE.
23*c217d954SCole Faust  */
24*c217d954SCole Faust #ifndef ARM_COMPUTE_TEST_CL_HELPER_H
25*c217d954SCole Faust #define ARM_COMPUTE_TEST_CL_HELPER_H
26*c217d954SCole Faust 
27*c217d954SCole Faust #include "arm_compute/runtime/CL/CLScheduler.h"
28*c217d954SCole Faust #include "arm_compute/runtime/CL/ICLSimpleFunction.h"
29*c217d954SCole Faust #include "arm_compute/runtime/CL/functions/CLFill.h"
30*c217d954SCole Faust #include "arm_compute/runtime/IFunction.h"
31*c217d954SCole Faust #include "src/core/CL/kernels/CLFillBorderKernel.h"
32*c217d954SCole Faust #include "src/gpu/cl/IClOperator.h"
33*c217d954SCole Faust #include "src/gpu/cl/operators/ClFill.h"
34*c217d954SCole Faust 
35*c217d954SCole Faust #include "src/core/CL/ICLKernel.h"
36*c217d954SCole Faust #include "support/Cast.h"
37*c217d954SCole Faust 
38*c217d954SCole Faust #include <memory>
39*c217d954SCole Faust 
40*c217d954SCole Faust namespace arm_compute
41*c217d954SCole Faust {
42*c217d954SCole Faust namespace test
43*c217d954SCole Faust {
44*c217d954SCole Faust /** This template synthetizes a simple IOperator which runs the given kernel K */
45*c217d954SCole Faust template <typename K>
46*c217d954SCole Faust class CLSynthetizeOperator : public opencl::IClOperator
47*c217d954SCole Faust {
48*c217d954SCole Faust public:
49*c217d954SCole Faust     /** Configure the kernel.
50*c217d954SCole Faust      *
51*c217d954SCole Faust      * @param[in] args Configuration arguments.
52*c217d954SCole Faust      */
53*c217d954SCole Faust     template <typename... Args>
configure(Args &&...args)54*c217d954SCole Faust     void configure(Args &&... args)
55*c217d954SCole Faust     {
56*c217d954SCole Faust         auto k = std::make_unique<K>();
57*c217d954SCole Faust         k->configure(CLKernelLibrary::get().get_compile_context(), std::forward<Args>(args)...);
58*c217d954SCole Faust         _kernel = std::move(k);
59*c217d954SCole Faust     }
60*c217d954SCole Faust     /** Configure the kernel setting the GPU target as well
61*c217d954SCole Faust      *
62*c217d954SCole Faust      * @param[in] gpu_target GPUTarget to set
63*c217d954SCole Faust      * @param[in] args       Configuration arguments.
64*c217d954SCole Faust      */
65*c217d954SCole Faust     template <typename... Args>
configure(GPUTarget gpu_target,Args &&...args)66*c217d954SCole Faust     void configure(GPUTarget gpu_target, Args &&... args)
67*c217d954SCole Faust     {
68*c217d954SCole Faust         auto k = std::make_unique<K>();
69*c217d954SCole Faust         k->set_target(gpu_target);
70*c217d954SCole Faust         k->configure(CLKernelLibrary::get().get_compile_context(), std::forward<Args>(args)...);
71*c217d954SCole Faust         _kernel = std::move(k);
72*c217d954SCole Faust     }
73*c217d954SCole Faust     /** Validate input arguments
74*c217d954SCole Faust      *
75*c217d954SCole Faust      * @param[in] args Configuration arguments.
76*c217d954SCole Faust      */
77*c217d954SCole Faust     template <typename... Args>
validate(Args &&...args)78*c217d954SCole Faust     static Status validate(Args &&... args)
79*c217d954SCole Faust     {
80*c217d954SCole Faust         return K::validate(std::forward<Args>(args)...);
81*c217d954SCole Faust     }
82*c217d954SCole Faust };
83*c217d954SCole Faust 
84*c217d954SCole Faust /** As above but this also initializes to zero the input tensor */
85*c217d954SCole Faust template <typename K, int bordersize>
86*c217d954SCole Faust class CLSynthetizeOperatorInitOutputWithZeroAndWithZeroConstantBorder : public opencl::IClOperator
87*c217d954SCole Faust {
88*c217d954SCole Faust public:
89*c217d954SCole Faust     /** Configure the kernel.
90*c217d954SCole Faust      *
91*c217d954SCole Faust      * @param[in] first  First input argument.
92*c217d954SCole Faust      * @param[in] second Second input argument.
93*c217d954SCole Faust      * @param[in] args   Rest of the configuration arguments.
94*c217d954SCole Faust      */
95*c217d954SCole Faust     template <typename T, typename... Args>
configure(T first,T second,Args &&...args)96*c217d954SCole Faust     void configure(T first, T second, Args &&... args)
97*c217d954SCole Faust     {
98*c217d954SCole Faust         auto cctx = CLKernelLibrary::get().get_compile_context();
99*c217d954SCole Faust         auto k    = std::make_unique<K>();
100*c217d954SCole Faust         k->set_target(CLScheduler::get().target());
101*c217d954SCole Faust         k->configure(cctx, first, second, std::forward<Args>(args)...);
102*c217d954SCole Faust         _kernel = std::move(k);
103*c217d954SCole Faust         _border_handler.configure(cctx, first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
104*c217d954SCole Faust         _fill.configure(cctx, second, PixelValue());
105*c217d954SCole Faust     }
106*c217d954SCole Faust 
107*c217d954SCole Faust     // Inherited method overridden:
run(ITensorPack & tensors)108*c217d954SCole Faust     void run(ITensorPack &tensors) override final
109*c217d954SCole Faust     {
110*c217d954SCole Faust         ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The CL kernel or function isn't configured");
111*c217d954SCole Faust 
112*c217d954SCole Faust         ITensorPack fill_pack = { { ACL_SRC, tensors.get_tensor(TensorType::ACL_DST) } };
113*c217d954SCole Faust         _fill.run(fill_pack);
114*c217d954SCole Faust         CLScheduler::get().enqueue_op(_border_handler, tensors);
115*c217d954SCole Faust         CLScheduler::get().enqueue_op(*_kernel, tensors);
116*c217d954SCole Faust     }
117*c217d954SCole Faust 
118*c217d954SCole Faust private:
119*c217d954SCole Faust     opencl::ClFill             _fill{};           /**< Kernel to initialize the tensor */
120*c217d954SCole Faust     CLFillBorderKernel         _border_handler{}; /**< Kernel to handle  borders */
121*c217d954SCole Faust     std::unique_ptr<ICLKernel> _kernel{};         /**< Kernel to run */
122*c217d954SCole Faust };
123*c217d954SCole Faust 
124*c217d954SCole Faust /** This template synthetizes an ICLSimpleFunction which runs the given kernel K */
125*c217d954SCole Faust template <typename K>
126*c217d954SCole Faust class CLSynthetizeFunction : public ICLSimpleFunction
127*c217d954SCole Faust {
128*c217d954SCole Faust public:
129*c217d954SCole Faust     /** Configure the kernel.
130*c217d954SCole Faust      *
131*c217d954SCole Faust      * @param[in] args Configuration arguments.
132*c217d954SCole Faust      */
133*c217d954SCole Faust     template <typename... Args>
configure(Args &&...args)134*c217d954SCole Faust     void configure(Args &&... args)
135*c217d954SCole Faust     {
136*c217d954SCole Faust         auto k = std::make_unique<K>();
137*c217d954SCole Faust         k->configure(std::forward<Args>(args)...);
138*c217d954SCole Faust         _kernel = std::move(k);
139*c217d954SCole Faust     }
140*c217d954SCole Faust     /** Configure the kernel setting the GPU target as well
141*c217d954SCole Faust      *
142*c217d954SCole Faust      * @param[in] gpu_target GPUTarget to set
143*c217d954SCole Faust      * @param[in] args       Configuration arguments.
144*c217d954SCole Faust      */
145*c217d954SCole Faust     template <typename... Args>
configure(GPUTarget gpu_target,Args &&...args)146*c217d954SCole Faust     void configure(GPUTarget gpu_target, Args &&... args)
147*c217d954SCole Faust     {
148*c217d954SCole Faust         auto k = std::make_unique<K>();
149*c217d954SCole Faust         k->set_target(gpu_target);
150*c217d954SCole Faust         k->configure(std::forward<Args>(args)...);
151*c217d954SCole Faust         _kernel = std::move(k);
152*c217d954SCole Faust     }
153*c217d954SCole Faust     /** Validate input arguments
154*c217d954SCole Faust      *
155*c217d954SCole Faust      * @param[in] args Configuration arguments.
156*c217d954SCole Faust      */
157*c217d954SCole Faust     template <typename... Args>
validate(Args &&...args)158*c217d954SCole Faust     static Status validate(Args &&... args)
159*c217d954SCole Faust     {
160*c217d954SCole Faust         return K::validate(std::forward<Args>(args)...);
161*c217d954SCole Faust     }
162*c217d954SCole Faust };
163*c217d954SCole Faust 
164*c217d954SCole Faust /** As above but this also setups a Zero border on the input tensor of the specified bordersize */
165*c217d954SCole Faust template <typename K, int bordersize>
166*c217d954SCole Faust class CLSynthetizeFunctionWithZeroConstantBorder : public ICLSimpleFunction
167*c217d954SCole Faust {
168*c217d954SCole Faust public:
169*c217d954SCole Faust     /** Configure the kernel.
170*c217d954SCole Faust      *
171*c217d954SCole Faust      * @param[in] first First configuration argument.
172*c217d954SCole Faust      * @param[in] args  Rest of the configuration arguments.
173*c217d954SCole Faust      */
174*c217d954SCole Faust     template <typename T, typename... Args>
configure(T first,Args &&...args)175*c217d954SCole Faust     void configure(T first, Args &&... args)
176*c217d954SCole Faust     {
177*c217d954SCole Faust         auto k = std::make_unique<K>();
178*c217d954SCole Faust         k->configure(first, std::forward<Args>(args)...);
179*c217d954SCole Faust         _kernel = std::move(k);
180*c217d954SCole Faust         _border_handler->configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
181*c217d954SCole Faust     }
182*c217d954SCole Faust };
183*c217d954SCole Faust 
184*c217d954SCole Faust /** As above but this also initializes to zero the input tensor */
185*c217d954SCole Faust template <typename K, int bordersize>
186*c217d954SCole Faust class CLSynthetizeFunctionInitOutputWithZeroAndWithZeroConstantBorder : public IFunction
187*c217d954SCole Faust {
188*c217d954SCole Faust public:
189*c217d954SCole Faust     /** Configure the kernel.
190*c217d954SCole Faust      *
191*c217d954SCole Faust      * @param[in] first  First input argument.
192*c217d954SCole Faust      * @param[in] second Second input argument.
193*c217d954SCole Faust      * @param[in] args   Rest of the configuration arguments.
194*c217d954SCole Faust      */
195*c217d954SCole Faust     template <typename T, typename... Args>
configure(T first,T second,Args &&...args)196*c217d954SCole Faust     void configure(T first, T second, Args &&... args)
197*c217d954SCole Faust     {
198*c217d954SCole Faust         auto k = std::make_unique<K>();
199*c217d954SCole Faust         k->set_target(CLScheduler::get().target());
200*c217d954SCole Faust         k->configure(first, second, std::forward<Args>(args)...);
201*c217d954SCole Faust         _kernel = std::move(k);
202*c217d954SCole Faust         _border_handler.configure(first, BorderSize(bordersize), BorderMode::CONSTANT, PixelValue());
203*c217d954SCole Faust         _fill.configure(second, PixelValue());
204*c217d954SCole Faust     }
205*c217d954SCole Faust 
206*c217d954SCole Faust     // Inherited method overridden:
run()207*c217d954SCole Faust     void run() override final
208*c217d954SCole Faust     {
209*c217d954SCole Faust         ARM_COMPUTE_ERROR_ON_MSG(!_kernel, "The CL kernel or function isn't configured");
210*c217d954SCole Faust 
211*c217d954SCole Faust         _fill.run();
212*c217d954SCole Faust         CLScheduler::get().enqueue(_border_handler, false);
213*c217d954SCole Faust         CLScheduler::get().enqueue(*_kernel);
214*c217d954SCole Faust     }
215*c217d954SCole Faust 
216*c217d954SCole Faust private:
217*c217d954SCole Faust     CLFill                     _fill{};           /**< Kernel to initialize the tensor */
218*c217d954SCole Faust     CLFillBorderKernel         _border_handler{}; /**< Kernel to handle  borders */
219*c217d954SCole Faust     std::unique_ptr<ICLKernel> _kernel{};         /**< Kernel to run */
220*c217d954SCole Faust };
221*c217d954SCole Faust 
222*c217d954SCole Faust /** As above but this also setups a Zero border on the input tensor of the kernel's bordersize */
223*c217d954SCole Faust template <typename K>
224*c217d954SCole Faust class ClSynthetizeOperatorWithBorder : public opencl::IClOperator
225*c217d954SCole Faust {
226*c217d954SCole Faust public:
227*c217d954SCole Faust     /** Configure the kernel.
228*c217d954SCole Faust      *
229*c217d954SCole Faust      * @param[in] first First configuration argument.
230*c217d954SCole Faust      * @param[in] args  Rest of the configuration arguments.
231*c217d954SCole Faust      */
232*c217d954SCole Faust     template <typename T, typename... Args>
configure(T first,Args &&...args)233*c217d954SCole Faust     void configure(T first, Args &&... args)
234*c217d954SCole Faust     {
235*c217d954SCole Faust         auto k = std::make_unique<K>();
236*c217d954SCole Faust         k->configure(CLKernelLibrary::get().get_compile_context(), first, std::forward<Args>(args)...);
237*c217d954SCole Faust         _kernel = std::move(k);
238*c217d954SCole Faust 
239*c217d954SCole Faust         auto b = std::make_unique<CLFillBorderKernel>();
240*c217d954SCole Faust         b->configure(CLKernelLibrary::get().get_compile_context(), first, BorderSize(_kernel->border_size()), BorderMode::CONSTANT, PixelValue());
241*c217d954SCole Faust         _border_handler = std::move(b);
242*c217d954SCole Faust     }
243*c217d954SCole Faust 
run(ITensorPack & tensors)244*c217d954SCole Faust     void run(ITensorPack &tensors) override
245*c217d954SCole Faust     {
246*c217d954SCole Faust         CLScheduler::get().enqueue(*_border_handler);
247*c217d954SCole Faust         CLScheduler::get().enqueue_op(*_kernel, tensors);
248*c217d954SCole Faust     }
249*c217d954SCole Faust 
250*c217d954SCole Faust private:
251*c217d954SCole Faust     std::unique_ptr<ICLKernel> _border_handler{ nullptr }; /**< Kernel to handle  borders */
252*c217d954SCole Faust     std::unique_ptr<ICLKernel> _kernel{};                  /**< Kernel to run */
253*c217d954SCole Faust };
254*c217d954SCole Faust } // namespace test
255*c217d954SCole Faust } // namespace arm_compute
256*c217d954SCole Faust #endif /* ARM_COMPUTE_TEST_CL_HELPER_H */
257