blob: 86bb502da385448db8f5d11b9c5273603b9f67b5 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Matthew Bentham314d3e22023-06-23 10:53:52 +00002 * Copyright (c) 2016-2021, 2023 Arm Limited.
Anthony Barbier6ff3b192017-09-04 18:44:23 +01003 *
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 */
Sang-Hoon Parkbef7fa22020-10-21 15:58:54 +010024#include "src/core/CL/kernels/CLFillBorderKernel.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010025
26#include "arm_compute/core/CL/CLHelpers.h"
27#include "arm_compute/core/CL/CLKernelLibrary.h"
28#include "arm_compute/core/CL/ICLTensor.h"
29#include "arm_compute/core/CL/OpenCL.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030#include "arm_compute/core/TensorInfo.h"
31#include "arm_compute/core/Utils.h"
Matthew Bentham314d3e22023-06-23 10:53:52 +000032#include "arm_compute/core/utils/StringUtils.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010033#include "arm_compute/core/Validate.h"
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010034
Sang-Hoon Park68dd25f2020-10-19 16:00:11 +010035#include "src/core/helpers/WindowHelpers.h"
36#include "support/Cast.h"
Matthew Bentham758b5ba2020-03-05 23:37:48 +000037#include "support/StringSupport.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010038
Michele Di Giorgiof6f78762020-07-06 11:27:21 +010039namespace arm_compute
40{
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010041CLFillBorderKernel::CLFillBorderKernel() : ICLKernel(), _tensor(nullptr)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010042{
Giorgio Arena4a95bba2021-06-28 11:00:27 +010043 _type = CLKernelType::ELEMENTWISE;
Anthony Barbier6ff3b192017-09-04 18:44:23 +010044}
45
46bool CLFillBorderKernel::is_parallelisable() const
47{
48 return false;
49}
50
51template <class T>
52void CLFillBorderKernel::set_constant_border(unsigned int idx, const PixelValue &constant_border_value)
53{
54 T value;
55 constant_border_value.get(value);
56 ICLKernel::add_argument<T>(idx, static_cast<T>(value));
57}
58
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010059void CLFillBorderKernel::configure(ICLTensor *tensor,
60 BorderSize border_size,
61 BorderMode border_mode,
62 const PixelValue &constant_border_value)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010063{
Manuel Bottini4c6bd512020-04-08 10:15:51 +010064 configure(CLKernelLibrary::get().get_compile_context(), tensor, border_size, border_mode, constant_border_value);
65}
66
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010067void CLFillBorderKernel::configure(const CLCompileContext &compile_context,
68 ICLTensor *tensor,
69 BorderSize border_size,
70 BorderMode border_mode,
71 const PixelValue &constant_border_value)
Manuel Bottini4c6bd512020-04-08 10:15:51 +010072{
Michalis Spyrouad7515d2020-07-24 00:02:23 +010073 _tensor = tensor;
74 configure(compile_context, tensor->info(), border_size, border_mode, constant_border_value);
75}
Anthony Barbier6ff3b192017-09-04 18:44:23 +010076
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010077void CLFillBorderKernel::configure(const CLCompileContext &compile_context,
78 ITensorInfo *tensor,
79 BorderSize border_size,
80 BorderMode border_mode,
81 const PixelValue &constant_border_value)
Michalis Spyrouad7515d2020-07-24 00:02:23 +010082{
83 ARM_COMPUTE_ERROR_ON(tensor == nullptr);
84 ARM_COMPUTE_ERROR_ON(tensor->num_channels() != 1);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010085 auto padding_info = get_padding_info({tensor});
Michalis Spyrouad7515d2020-07-24 00:02:23 +010086
87 border_size.limit(tensor->padding());
Anthony Barbier6ff3b192017-09-04 18:44:23 +010088
89 // If there is no border: early exit
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +010090 if (border_size.empty() || border_mode == BorderMode::UNDEFINED)
Anthony Barbier6ff3b192017-09-04 18:44:23 +010091 {
92 return;
93 }
94
95 // Select appropriate kernel
96 std::string kernel_name = "fill_image_borders_" + lower_string(string_from_border_mode(border_mode));
97
Michalis Spyrouad7515d2020-07-24 00:02:23 +010098 const DataType dt = tensor->data_type();
Anthony Barbier6ff3b192017-09-04 18:44:23 +010099
100 // Define build options
Manuel Bottinib412fab2018-12-10 17:40:23 +0000101 CLBuildOptions build_opts;
Michele Di Giorgiof6f78762020-07-06 11:27:21 +0100102 build_opts.add_option("-DDATA_TYPE=" + get_cl_type_from_data_type(dt));
Manuel Bottinib412fab2018-12-10 17:40:23 +0000103 build_opts.add_option("-DBORDER_SIZE_TOP=" + support::cpp11::to_string(border_size.top));
104 build_opts.add_option("-DBORDER_SIZE_BOTTOM=" + support::cpp11::to_string(border_size.bottom));
105 build_opts.add_option("-DBORDER_SIZE_LEFT=" + support::cpp11::to_string(border_size.left));
106 build_opts.add_option("-DBORDER_SIZE_RIGHT=" + support::cpp11::to_string(border_size.right));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100107
108 // Create kernel
Manuel Bottini4c6bd512020-04-08 10:15:51 +0100109 _kernel = create_kernel(compile_context, kernel_name, build_opts.options());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100110
111 // Create static kernel arguments
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100112 const unsigned int valid_width = tensor->valid_region().shape[0];
113 const unsigned int valid_height = tensor->valid_region().shape[1];
114 const cl_int2 valid_region_coords = {{
115 static_cast<cl_int>(tensor->valid_region().anchor[0]),
116 static_cast<cl_int>(tensor->valid_region().anchor[1]),
117 }};
118 const unsigned int total_valid_width = border_size.left + valid_width + border_size.right;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100119
120 // Set static kernel arguments
Anthony Barbier7ff47a32017-07-11 16:54:04 +0100121 unsigned int idx = num_arguments_per_3D_tensor(); //Skip the tensor parameters
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100122 ICLKernel::add_argument<cl_uint>(idx, valid_width);
123 ICLKernel::add_argument<cl_uint>(idx, valid_height);
124 ICLKernel::add_argument<cl_int2>(idx, valid_region_coords);
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100125 if (BorderMode::CONSTANT == border_mode)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100126 {
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100127 switch (dt)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100128 {
129 case DataType::U8:
Chunosovd621bca2017-11-03 17:33:15 +0700130 case DataType::QASYMM8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100131 set_constant_border<uint8_t>(idx, constant_border_value);
132 break;
Georgios Pinitasac4e8732017-07-05 17:02:25 +0100133 case DataType::S8:
Manuel Bottini8481d832019-12-10 15:28:40 +0000134 case DataType::QASYMM8_SIGNED:
Georgios Pinitasac4e8732017-07-05 17:02:25 +0100135 set_constant_border<int8_t>(idx, constant_border_value);
136 break;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100137 case DataType::U16:
138 set_constant_border<uint16_t>(idx, constant_border_value);
139 break;
140 case DataType::S16:
141 set_constant_border<int16_t>(idx, constant_border_value);
142 break;
143 case DataType::U32:
144 set_constant_border<uint32_t>(idx, constant_border_value);
145 break;
146 case DataType::S32:
147 set_constant_border<int32_t>(idx, constant_border_value);
148 break;
149 case DataType::F32:
150 static_assert(sizeof(float) == 4, "Float must be 32 bit");
151 set_constant_border<float>(idx, constant_border_value);
152 break;
153 case DataType::F16:
Manuel Bottinib412fab2018-12-10 17:40:23 +0000154 static_assert(sizeof(cl_half) == sizeof(half), "Half must be same size as cl_half");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100155 static_assert(sizeof(cl_half) == 2, "Half must be 16 bit");
Manuel Bottinib412fab2018-12-10 17:40:23 +0000156 set_constant_border<half>(idx, constant_border_value);
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100157 break;
158 default:
159 ARM_COMPUTE_ERROR("Not handled");
160 }
161 }
162
163 // Configure kernel window
164 Window win;
165 win.set(Window::DimX, Window::Dimension(0, total_valid_width + valid_height));
166 win.set(Window::DimY, Window::Dimension(0, 1, 1));
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100167 win.use_tensor_dimensions(tensor->tensor_shape(), Window::DimZ);
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100168 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100169
170 // Set config_id for enabling LWS tuning
171 _config_id = kernel_name;
172 _config_id += "_";
173 _config_id += lower_string(string_from_data_type(dt));
174 _config_id += "_";
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100175 _config_id += support::cpp11::to_string(tensor->dimension(0));
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100176 _config_id += "_";
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100177 _config_id += support::cpp11::to_string(tensor->dimension(1));
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100178 _config_id += "_";
179 _config_id += lower_string(string_from_border_mode(border_mode));
Manuel Bottinib6869dd2020-12-16 15:34:25 +0000180 ARM_COMPUTE_ERROR_ON(has_padding_changed(padding_info));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100181}
182
Georgios Pinitas0499dff2020-07-31 22:21:38 +0100183void CLFillBorderKernel::run_op(ITensorPack &tensors, const Window &window, cl::CommandQueue &queue)
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100184{
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100185 // Border mode undefined or border width == 0
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100186 if (_kernel() == nullptr)
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100187 {
188 return;
189 }
190
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100191 const auto tensor =
192 utils::cast::polymorphic_downcast<const ICLTensor *>(tensors.get_const_tensor(TensorType::ACL_SRC));
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100193
194 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
195 ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(ICLKernel::window(), window);
196
197 Window collapsed = window.collapse_if_possible(ICLKernel::window(), Window::DimZ);
198 Window slice = collapsed.first_slice_window_3D();
199
200 do
201 {
202 unsigned int idx = 0;
203 add_3D_tensor_argument(idx, tensor, slice);
204 enqueue(queue, *this, slice, lws_hint());
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100205 } while (collapsed.slide_window_slice_3D(slice));
Michalis Spyrouad7515d2020-07-24 00:02:23 +0100206}
207
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100208void CLFillBorderKernel::run(const Window &window, cl::CommandQueue &queue)
209{
210 // Border mode undefined or border width == 0
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100211 if (_kernel() == nullptr)
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100212 {
213 return;
214 }
215
216 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
217 ARM_COMPUTE_ERROR_ON_MISMATCHING_WINDOWS(ICLKernel::window(), window);
218
Georgios Pinitase55b40a2018-09-13 17:20:04 +0100219 Window collapsed = window.collapse_if_possible(ICLKernel::window(), Window::DimZ);
220 Window slice = collapsed.first_slice_window_3D();
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100221
222 do
223 {
224 unsigned int idx = 0;
Anthony Barbier7ff47a32017-07-11 16:54:04 +0100225 add_3D_tensor_argument(idx, _tensor, slice);
Georgios Pinitas275f99c2019-08-23 12:44:11 +0100226 enqueue(queue, *this, slice, lws_hint());
Felix Thomasmathibalanafd38f02023-09-27 17:46:17 +0100227 } while (collapsed.slide_window_slice_3D(slice));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100228}
Michele Di Giorgiof6f78762020-07-06 11:27:21 +0100229} // namespace arm_compute