blob: f2eb848684abba881208fbfad09aea3140fbd6fa [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Matthew Bentham758b5ba2020-03-05 23:37:48 +00002 * Copyright (c) 2016-2020 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 */
24#include "arm_compute/core/CL/kernels/CLColorConvertKernel.h"
25
26#include "arm_compute/core/CL/CLKernelLibrary.h"
27#include "arm_compute/core/CL/ICLMultiImage.h"
28#include "arm_compute/core/CL/ICLTensor.h"
29#include "arm_compute/core/CL/OpenCL.h"
30#include "arm_compute/core/Error.h"
31#include "arm_compute/core/Helpers.h"
32#include "arm_compute/core/MultiImageInfo.h"
33#include "arm_compute/core/TensorInfo.h"
34#include "arm_compute/core/Types.h"
35#include "arm_compute/core/Utils.h"
36#include "arm_compute/core/Validate.h"
37#include "arm_compute/core/Window.h"
Matthew Bentham758b5ba2020-03-05 23:37:48 +000038#include "support/StringSupport.h"
Anthony Barbier6ff3b192017-09-04 18:44:23 +010039
40#include <sstream>
41
42using namespace arm_compute;
43
44CLColorConvertKernel::CLColorConvertKernel()
45 : _input(nullptr), _output(nullptr), _multi_input(nullptr), _multi_output(nullptr)
46{
47}
48
49void CLColorConvertKernel::configure(const ICLTensor *input, ICLTensor *output)
50{
51 ARM_COMPUTE_ERROR_ON(input == nullptr);
52 ARM_COMPUTE_ERROR_ON(output == nullptr);
53
54 unsigned int num_elems_processed_per_iteration = 0;
55 switch(input->info()->format())
56 {
57 case Format::RGBA8888:
58 {
59 switch(output->info()->format())
60 {
61 case Format::RGB888:
62 num_elems_processed_per_iteration = 16;
63 break;
64 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010065 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +010066 break;
67 }
68 break;
69 }
70 case Format::UYVY422:
71 case Format::YUYV422:
72 {
73 switch(output->info()->format())
74 {
75 case Format::RGB888:
76 case Format::RGBA8888:
77 num_elems_processed_per_iteration = 8;
78 break;
79 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010080 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +010081 break;
82 }
83 break;
84 }
85 case Format::RGB888:
86 {
87 switch(output->info()->format())
88 {
89 case Format::RGBA8888:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010090 case Format::U8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +010091 num_elems_processed_per_iteration = 16;
92 break;
93 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010094 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +010095 break;
96 }
97 break;
98 }
99 default:
100 break;
101 }
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100102 ARM_COMPUTE_ERROR_ON_MSG_VAR(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
103 string_from_format(input->info()->format()).c_str(),
104 string_from_format(output->info()->format()).c_str());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100105
106 std::stringstream kernel_name;
107
108 kernel_name << string_from_format(input->info()->format());
109 kernel_name << "_to_";
110 kernel_name << string_from_format(output->info()->format());
111 kernel_name << "_bt709";
112
113 _input = input;
114 _output = output;
115
116 // Create kernel
117 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
118
119 // Configure kernel window
120 Window win = calculate_max_window(*input->info(), Steps(num_elems_processed_per_iteration));
121 AccessWindowHorizontal input_access(input->info(), 0, num_elems_processed_per_iteration);
122 AccessWindowHorizontal output_access(output->info(), 0, num_elems_processed_per_iteration);
123
124 update_window_and_padding(win, input_access, output_access);
125
126 output_access.set_valid_region(win, input->info()->valid_region());
127
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100128 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100129
130 // Set config_id for enabling LWS tuning
131 _config_id = kernel_name.str();
132 _config_id += "_";
133 _config_id += lower_string(string_from_data_type(input->info()->data_type()));
134 _config_id += "_";
135 _config_id += support::cpp11::to_string(input->info()->dimension(0));
136 _config_id += "_";
137 _config_id += support::cpp11::to_string(input->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100138}
139
140void CLColorConvertKernel::configure(const ICLMultiImage *input, ICLImage *output)
141{
142 ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(output);
143 ARM_COMPUTE_ERROR_ON(output == nullptr);
144
145 unsigned int num_elems_processed_per_iteration = 0;
146
147 switch(input->info()->format())
148 {
149 case Format::NV12:
150 case Format::NV21:
151 case Format::IYUV:
152 {
153 switch(output->info()->format())
154 {
155 case Format::RGB888:
156 case Format::RGBA8888:
157 num_elems_processed_per_iteration = 4;
158 break;
159 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100160 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100161 break;
162 }
163 break;
164 }
165 default:
166 break;
167 }
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100168 ARM_COMPUTE_ERROR_ON_MSG_VAR(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
169 string_from_format(input->info()->format()).c_str(),
170 string_from_format(output->info()->format()).c_str());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100171
172 std::stringstream kernel_name;
173
174 kernel_name << string_from_format(input->info()->format());
175 kernel_name << "_to_";
176 kernel_name << string_from_format(output->info()->format());
177 kernel_name << "_bt709";
178
179 _multi_input = input;
180 _output = output;
181
182 // Create kernel
183 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
184
185 // Configure kernel window
186 const bool has_two_planes = (input->info()->format() == Format::NV12) || (input->info()->format() == Format::NV21);
187 const float sub_sampling = (has_two_planes || (input->info()->format() == Format::IYUV)) ? 0.5f : 1;
188
189 Window win = calculate_max_window(*output->info(), Steps(num_elems_processed_per_iteration));
190 win.set_dimension_step(Window::DimY, 2);
191
192 AccessWindowHorizontal plane0_access(input->plane(0)->info(), 0, num_elems_processed_per_iteration);
193 AccessWindowRectangle plane1_access(input->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1,
194 sub_sampling, sub_sampling);
195 AccessWindowRectangle plane2_access(has_two_planes ? nullptr : input->plane(2)->info(), 0, 0, num_elems_processed_per_iteration, 1,
196 sub_sampling, sub_sampling);
197 AccessWindowHorizontal output_access(output->info(), 0, num_elems_processed_per_iteration);
198
199 update_window_and_padding(win,
200 plane0_access, plane1_access, plane2_access,
201 output_access);
202
203 ValidRegion intersect_region = intersect_valid_regions(input->plane(0)->info()->valid_region(), input->plane(1)->info()->valid_region(),
204 input->plane(2)->info()->valid_region());
205 output_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->info()->tensor_shape()));
206
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100207 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100208
209 // Set config_id for enabling LWS tuning
210 _config_id = kernel_name.str();
211 _config_id += "_";
212 _config_id += lower_string(string_from_data_type(input->plane(0)->info()->data_type()));
213 _config_id += "_";
214 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(0));
215 _config_id += "_";
216 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(1));
217 _config_id += "_";
218 _config_id += lower_string(string_from_data_type(input->plane(1)->info()->data_type()));
219 _config_id += "_";
220 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(0));
221 _config_id += "_";
222 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100223}
224
225void CLColorConvertKernel::configure(const ICLImage *input, ICLMultiImage *output)
226{
227 ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(input);
228 ARM_COMPUTE_ERROR_ON(output == nullptr);
229
230 unsigned int num_elems_processed_per_iteration = 0;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100231 unsigned int num_elems_read_per_iteration_x = 0;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100232
233 bool has_two_planes = (output->info()->format() == Format::NV12) || (output->info()->format() == Format::NV21);
234 float sub_sampling = (has_two_planes || (output->info()->format() == Format::IYUV)) ? 0.5f : 1;
235
236 switch(input->info()->format())
237 {
238 case Format::RGB888:
239 case Format::RGBA8888:
240 {
241 switch(output->info()->format())
242 {
243 case Format::NV12:
244 case Format::IYUV:
245 num_elems_processed_per_iteration = 2;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100246 num_elems_read_per_iteration_x = 8;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100247 break;
248 case Format::YUV444:
249 num_elems_processed_per_iteration = 4;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100250 num_elems_read_per_iteration_x = 16;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100251 break;
252 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100253 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100254 break;
255 }
256 break;
257 }
258 case Format::UYVY422:
259 case Format::YUYV422:
260 {
261 switch(output->info()->format())
262 {
263 case Format::NV12:
264 case Format::IYUV:
265 num_elems_processed_per_iteration = 8;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100266 num_elems_read_per_iteration_x = 8;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100267 break;
268 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100269 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100270 break;
271 }
272 break;
273 }
274 default:
275 break;
276 }
Pablo Tello96fc1d62018-07-17 17:10:59 +0100277
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100278 ARM_COMPUTE_ERROR_ON_MSG_VAR(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
279 string_from_format(input->info()->format()).c_str(),
280 string_from_format(output->info()->format()).c_str());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100281
282 std::stringstream kernel_name;
283
284 kernel_name << string_from_format(input->info()->format());
285 kernel_name << "_to_";
286 kernel_name << string_from_format(output->info()->format());
287 kernel_name << "_bt709";
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100288 _input = input;
289 _multi_output = output;
290
291 // Create kernel
292 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
293
294 // Configure kernel window
295 Window win = calculate_max_window(*input->info(), Steps(num_elems_processed_per_iteration));
296 if((input->info()->format() != Format::RGB888 || output->info()->format() != Format::YUV444) && (input->info()->format() != Format::RGBA8888 || output->info()->format() != Format::YUV444))
297 {
298 win.set_dimension_step(Window::DimY, 2);
299 }
300
301 AccessWindowHorizontal output_plane0_access(output->plane(0)->info(), 0, num_elems_processed_per_iteration);
302 AccessWindowRectangle output_plane1_access(output->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1, sub_sampling, sub_sampling);
303 AccessWindowRectangle output_plane2_access(has_two_planes ? nullptr : output->plane(2)->info(), 0, 0,
304 num_elems_processed_per_iteration, 1, sub_sampling, sub_sampling);
305
Pablo Tello96fc1d62018-07-17 17:10:59 +0100306 AccessWindowHorizontal input_access(input->info(), 0, num_elems_read_per_iteration_x);
307
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100308 update_window_and_padding(win,
Pablo Tello96fc1d62018-07-17 17:10:59 +0100309 input_access,
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100310 output_plane0_access,
311 output_plane1_access,
312 output_plane2_access);
313
314 ValidRegion input_region = input->info()->valid_region();
315
316 output_plane0_access.set_valid_region(win, ValidRegion(input_region.anchor, output->plane(0)->info()->tensor_shape()));
317 output_plane1_access.set_valid_region(win, ValidRegion(input_region.anchor, output->plane(1)->info()->tensor_shape()));
318 output_plane2_access.set_valid_region(win, ValidRegion(input_region.anchor, output->plane(2)->info()->tensor_shape()));
319
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100320 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100321
322 // Set config_id for enabling LWS tuning
323 _config_id = kernel_name.str();
324 _config_id += "_";
325 _config_id += lower_string(string_from_data_type(input->info()->data_type()));
326 _config_id += "_";
327 _config_id += support::cpp11::to_string(input->info()->dimension(0));
328 _config_id += "_";
329 _config_id += support::cpp11::to_string(input->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100330}
331
332void CLColorConvertKernel::configure(const ICLMultiImage *input, ICLMultiImage *output)
333{
334 unsigned int num_elems_processed_per_iteration = 0;
335 switch(input->info()->format())
336 {
337 case Format::NV12:
338 case Format::NV21:
339 {
340 switch(output->info()->format())
341 {
342 case Format::IYUV:
343 case Format::YUV444:
344 num_elems_processed_per_iteration = 16;
345 break;
346 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100347 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100348 break;
349 }
350 break;
351 }
352 case Format::IYUV:
353 {
354 switch(output->info()->format())
355 {
356 case Format::YUV444:
357 case Format::NV12:
358 num_elems_processed_per_iteration = 16;
359 break;
360 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100361 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100362 break;
363 }
364 break;
365 }
366 default:
367 break;
368 }
Michalis Spyrou7c60c992019-10-10 14:33:47 +0100369 ARM_COMPUTE_ERROR_ON_MSG_VAR(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
370 string_from_format(input->info()->format()).c_str(),
371 string_from_format(output->info()->format()).c_str());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100372
373 std::stringstream kernel_name;
374
375 kernel_name << string_from_format(input->info()->format());
376 kernel_name << "_to_";
377 kernel_name << string_from_format(output->info()->format());
378 kernel_name << "_bt709";
379
380 _multi_input = input;
381 _multi_output = output;
382
383 // Create kernel
384 bool has_two_input_planars = (input->info()->format() == Format::NV12) || (input->info()->format() == Format::NV21);
385 bool has_two_output_planars = (output->info()->format() == Format::NV12) || (output->info()->format() == Format::NV21);
386
387 float sub_sampling_input = (has_two_input_planars || (input->info()->format() == Format::IYUV)) ? 0.5f : 1;
388 float sub_sampling_output = (has_two_output_planars || (output->info()->format() == Format::IYUV)) ? 0.5f : 1;
389
390 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
391
392 Window win = calculate_max_window(*input->cl_plane(0)->info(), Steps(num_elems_processed_per_iteration));
393 win.set_dimension_step(Window::DimY, 2);
394
395 AccessWindowHorizontal input_plane0_access(input->plane(0)->info(), 0, num_elems_processed_per_iteration);
396 AccessWindowRectangle input_plane1_access(input->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1,
397 sub_sampling_input, sub_sampling_input);
398 AccessWindowRectangle input_plane2_access(has_two_input_planars ? nullptr : input->plane(2)->info(), 0, 0, num_elems_processed_per_iteration, 1,
399 sub_sampling_input, sub_sampling_input);
400 AccessWindowHorizontal output_plane0_access(output->plane(0)->info(), 0, num_elems_processed_per_iteration);
401 AccessWindowRectangle output_plane1_access(output->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1, sub_sampling_output, sub_sampling_output);
402 AccessWindowRectangle output_plane2_access(has_two_output_planars ? nullptr : output->plane(2)->info(), 0, 0,
403 num_elems_processed_per_iteration, 1, sub_sampling_output, sub_sampling_output);
404
405 update_window_and_padding(win,
406 input_plane0_access, input_plane1_access, input_plane2_access,
407 output_plane0_access, output_plane1_access, output_plane2_access);
408
409 ValidRegion intersect_region = intersect_valid_regions(input->plane(0)->info()->valid_region(), input->plane(1)->info()->valid_region(),
410 input->plane(2)->info()->valid_region());
411 output_plane0_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->plane(0)->info()->tensor_shape()));
412 output_plane1_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->plane(1)->info()->tensor_shape()));
413 output_plane2_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->plane(2)->info()->tensor_shape()));
414
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100415 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100416
417 // Set config_id for enabling LWS tuning
418 _config_id = kernel_name.str();
419 _config_id += "_";
420 _config_id += lower_string(string_from_data_type(input->plane(0)->info()->data_type()));
421 _config_id += "_";
422 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(0));
423 _config_id += "_";
424 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(1));
425 _config_id += "_";
426 _config_id += lower_string(string_from_data_type(input->plane(1)->info()->data_type()));
427 _config_id += "_";
428 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(0));
429 _config_id += "_";
430 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100431}
432
433void CLColorConvertKernel::run(const Window &window, cl::CommandQueue &queue)
434{
435 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
436 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICLKernel::window(), window);
437
438 Window slice = window.first_slice_window_2D();
439
440 if(nullptr != _input && nullptr != _output)
441 {
442 do
443 {
444 unsigned int idx = 0;
445 add_2D_tensor_argument(idx, _input, slice);
446 add_2D_tensor_argument(idx, _output, slice);
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100447 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100448 }
449 while(window.slide_window_slice_2D(slice));
450 }
451 else if(nullptr != _input && nullptr != _multi_output)
452 {
453 Format format = _multi_output->info()->format();
454 do
455 {
456 Window win_uv(slice);
457
458 if((Format::NV12 == format) || (Format::NV21 == format) || (Format::IYUV == format))
459 {
460 win_uv.set(Window::DimX, Window::Dimension(win_uv.x().start() / 2, win_uv.x().end() / 2, win_uv.x().step() / 2));
461 win_uv.set(Window::DimY, Window::Dimension(win_uv.y().start() / 2, win_uv.y().end() / 2, 1));
462 }
463 unsigned int idx = 0;
464 add_2D_tensor_argument(idx, _input, slice);
465 add_2D_tensor_argument(idx, _multi_output->cl_plane(0), slice);
466 for(int i = 1; i < 3 && (0 != _multi_output->cl_plane(i)->info()->num_dimensions()); ++i)
467 {
468 add_2D_tensor_argument(idx, _multi_output->cl_plane(i), win_uv);
469 }
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100470 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100471 }
472 while(window.slide_window_slice_2D(slice));
473 }
474 else if(nullptr != _multi_input && nullptr != _output)
475 {
476 Format format = _multi_input->info()->format();
477 do
478 {
479 Window win_uv(slice);
480
481 if((Format::NV12 == format) || (Format::NV21 == format) || (Format::IYUV == format))
482 {
483 win_uv.set(Window::DimX, Window::Dimension(win_uv.x().start() / 2, win_uv.x().end() / 2, win_uv.x().step() / 2));
484 win_uv.set(Window::DimY, Window::Dimension(win_uv.y().start() / 2, win_uv.y().end() / 2, 1));
485 }
486
487 unsigned int idx = 0;
488 add_2D_tensor_argument(idx, _multi_input->cl_plane(0), slice);
489
490 for(int i = 1; i < 3 && (0 != _multi_input->cl_plane(i)->info()->num_dimensions()); ++i)
491 {
492 add_2D_tensor_argument(idx, _multi_input->cl_plane(i), win_uv);
493 }
494 add_2D_tensor_argument(idx, _output, slice);
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100495 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100496 }
497 while(window.slide_window_slice_2D(slice));
498 }
499 else if(nullptr != _multi_input && nullptr != _multi_output)
500 {
501 Format in_format = _multi_input->info()->format();
502 Format out_format = _multi_output->info()->format();
503 do
504 {
505 Window win_in_uv(slice);
506 if((Format::NV12 == in_format) || (Format::NV21 == in_format) || (Format::IYUV == in_format))
507 {
508 win_in_uv.set(Window::DimX, Window::Dimension(win_in_uv.x().start() / 2,
509 win_in_uv.x().end() / 2, win_in_uv.x().step() / 2));
510 win_in_uv.set(Window::DimY, Window::Dimension(win_in_uv.y().start() / 2, win_in_uv.y().end() / 2, 1));
511 }
512 unsigned int idx = 0;
513 add_2D_tensor_argument(idx, _multi_input->cl_plane(0), slice);
514 for(int i = 1; i < 3 && (0 != _multi_input->cl_plane(i)->info()->num_dimensions()); ++i)
515 {
516 add_2D_tensor_argument(idx, _multi_input->cl_plane(i), win_in_uv);
517 }
518
519 Window win_out_uv(slice);
520 if((Format::NV12 == out_format) || (Format::NV21 == out_format) || (Format::IYUV == out_format))
521 {
522 win_out_uv.set(Window::DimX, Window::Dimension(win_out_uv.x().start() / 2,
523 win_out_uv.x().end() / 2, win_out_uv.x().step() / 2));
524 win_out_uv.set(Window::DimY, Window::Dimension(win_out_uv.y().start() / 2, win_out_uv.y().end() / 2, 1));
525 }
526
527 add_2D_tensor_argument(idx, _multi_output->cl_plane(0), slice);
528 for(int i = 1; i < 3 && (0 != _multi_output->cl_plane(i)->info()->num_dimensions()); ++i)
529 {
530 add_2D_tensor_argument(idx, _multi_output->cl_plane(i), win_out_uv);
531 }
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100532 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100533 }
534 while(window.slide_window_slice_2D(slice));
535 }
536 else
537 {
538 ARM_COMPUTE_ERROR("Not supported");
539 }
540}