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