blob: f3b93282e8ed35329b4208fc565e54ee3847c15e [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
Gary Antcliffefffbdbc2019-05-28 11:40:21 +01002 * Copyright (c) 2016-2019 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"
38
39#include <sstream>
40
41using namespace arm_compute;
42
43CLColorConvertKernel::CLColorConvertKernel()
44 : _input(nullptr), _output(nullptr), _multi_input(nullptr), _multi_output(nullptr)
45{
46}
47
48void CLColorConvertKernel::configure(const ICLTensor *input, ICLTensor *output)
49{
50 ARM_COMPUTE_ERROR_ON(input == nullptr);
51 ARM_COMPUTE_ERROR_ON(output == nullptr);
52
53 unsigned int num_elems_processed_per_iteration = 0;
54 switch(input->info()->format())
55 {
56 case Format::RGBA8888:
57 {
58 switch(output->info()->format())
59 {
60 case Format::RGB888:
61 num_elems_processed_per_iteration = 16;
62 break;
63 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010064 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +010065 break;
66 }
67 break;
68 }
69 case Format::UYVY422:
70 case Format::YUYV422:
71 {
72 switch(output->info()->format())
73 {
74 case Format::RGB888:
75 case Format::RGBA8888:
76 num_elems_processed_per_iteration = 8;
77 break;
78 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010079 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +010080 break;
81 }
82 break;
83 }
84 case Format::RGB888:
85 {
86 switch(output->info()->format())
87 {
88 case Format::RGBA8888:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010089 case Format::U8:
Anthony Barbier6ff3b192017-09-04 18:44:23 +010090 num_elems_processed_per_iteration = 16;
91 break;
92 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +010093 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +010094 break;
95 }
96 break;
97 }
98 default:
99 break;
100 }
101 ARM_COMPUTE_ERROR_ON_MSG(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
102 string_from_format(input->info()->format()).c_str(),
103 string_from_format(output->info()->format()).c_str());
104
105 std::stringstream kernel_name;
106
107 kernel_name << string_from_format(input->info()->format());
108 kernel_name << "_to_";
109 kernel_name << string_from_format(output->info()->format());
110 kernel_name << "_bt709";
111
112 _input = input;
113 _output = output;
114
115 // Create kernel
116 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
117
118 // Configure kernel window
119 Window win = calculate_max_window(*input->info(), Steps(num_elems_processed_per_iteration));
120 AccessWindowHorizontal input_access(input->info(), 0, num_elems_processed_per_iteration);
121 AccessWindowHorizontal output_access(output->info(), 0, num_elems_processed_per_iteration);
122
123 update_window_and_padding(win, input_access, output_access);
124
125 output_access.set_valid_region(win, input->info()->valid_region());
126
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100127 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100128
129 // Set config_id for enabling LWS tuning
130 _config_id = kernel_name.str();
131 _config_id += "_";
132 _config_id += lower_string(string_from_data_type(input->info()->data_type()));
133 _config_id += "_";
134 _config_id += support::cpp11::to_string(input->info()->dimension(0));
135 _config_id += "_";
136 _config_id += support::cpp11::to_string(input->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100137}
138
139void CLColorConvertKernel::configure(const ICLMultiImage *input, ICLImage *output)
140{
141 ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(output);
142 ARM_COMPUTE_ERROR_ON(output == nullptr);
143
144 unsigned int num_elems_processed_per_iteration = 0;
145
146 switch(input->info()->format())
147 {
148 case Format::NV12:
149 case Format::NV21:
150 case Format::IYUV:
151 {
152 switch(output->info()->format())
153 {
154 case Format::RGB888:
155 case Format::RGBA8888:
156 num_elems_processed_per_iteration = 4;
157 break;
158 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100159 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100160 break;
161 }
162 break;
163 }
164 default:
165 break;
166 }
167 ARM_COMPUTE_ERROR_ON_MSG(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
168 string_from_format(input->info()->format()).c_str(),
169 string_from_format(output->info()->format()).c_str());
170
171 std::stringstream kernel_name;
172
173 kernel_name << string_from_format(input->info()->format());
174 kernel_name << "_to_";
175 kernel_name << string_from_format(output->info()->format());
176 kernel_name << "_bt709";
177
178 _multi_input = input;
179 _output = output;
180
181 // Create kernel
182 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
183
184 // Configure kernel window
185 const bool has_two_planes = (input->info()->format() == Format::NV12) || (input->info()->format() == Format::NV21);
186 const float sub_sampling = (has_two_planes || (input->info()->format() == Format::IYUV)) ? 0.5f : 1;
187
188 Window win = calculate_max_window(*output->info(), Steps(num_elems_processed_per_iteration));
189 win.set_dimension_step(Window::DimY, 2);
190
191 AccessWindowHorizontal plane0_access(input->plane(0)->info(), 0, num_elems_processed_per_iteration);
192 AccessWindowRectangle plane1_access(input->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1,
193 sub_sampling, sub_sampling);
194 AccessWindowRectangle plane2_access(has_two_planes ? nullptr : input->plane(2)->info(), 0, 0, num_elems_processed_per_iteration, 1,
195 sub_sampling, sub_sampling);
196 AccessWindowHorizontal output_access(output->info(), 0, num_elems_processed_per_iteration);
197
198 update_window_and_padding(win,
199 plane0_access, plane1_access, plane2_access,
200 output_access);
201
202 ValidRegion intersect_region = intersect_valid_regions(input->plane(0)->info()->valid_region(), input->plane(1)->info()->valid_region(),
203 input->plane(2)->info()->valid_region());
204 output_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->info()->tensor_shape()));
205
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100206 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100207
208 // Set config_id for enabling LWS tuning
209 _config_id = kernel_name.str();
210 _config_id += "_";
211 _config_id += lower_string(string_from_data_type(input->plane(0)->info()->data_type()));
212 _config_id += "_";
213 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(0));
214 _config_id += "_";
215 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(1));
216 _config_id += "_";
217 _config_id += lower_string(string_from_data_type(input->plane(1)->info()->data_type()));
218 _config_id += "_";
219 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(0));
220 _config_id += "_";
221 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100222}
223
224void CLColorConvertKernel::configure(const ICLImage *input, ICLMultiImage *output)
225{
226 ARM_COMPUTE_ERROR_ON_TENSOR_NOT_2D(input);
227 ARM_COMPUTE_ERROR_ON(output == nullptr);
228
229 unsigned int num_elems_processed_per_iteration = 0;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100230 unsigned int num_elems_read_per_iteration_x = 0;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100231
232 bool has_two_planes = (output->info()->format() == Format::NV12) || (output->info()->format() == Format::NV21);
233 float sub_sampling = (has_two_planes || (output->info()->format() == Format::IYUV)) ? 0.5f : 1;
234
235 switch(input->info()->format())
236 {
237 case Format::RGB888:
238 case Format::RGBA8888:
239 {
240 switch(output->info()->format())
241 {
242 case Format::NV12:
243 case Format::IYUV:
244 num_elems_processed_per_iteration = 2;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100245 num_elems_read_per_iteration_x = 8;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100246 break;
247 case Format::YUV444:
248 num_elems_processed_per_iteration = 4;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100249 num_elems_read_per_iteration_x = 16;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100250 break;
251 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100252 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100253 break;
254 }
255 break;
256 }
257 case Format::UYVY422:
258 case Format::YUYV422:
259 {
260 switch(output->info()->format())
261 {
262 case Format::NV12:
263 case Format::IYUV:
264 num_elems_processed_per_iteration = 8;
Pablo Tello96fc1d62018-07-17 17:10:59 +0100265 num_elems_read_per_iteration_x = 8;
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100266 break;
267 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100268 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100269 break;
270 }
271 break;
272 }
273 default:
274 break;
275 }
Pablo Tello96fc1d62018-07-17 17:10:59 +0100276
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100277 ARM_COMPUTE_ERROR_ON_MSG(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
278 string_from_format(input->info()->format()).c_str(),
279 string_from_format(output->info()->format()).c_str());
280
281 std::stringstream kernel_name;
282
283 kernel_name << string_from_format(input->info()->format());
284 kernel_name << "_to_";
285 kernel_name << string_from_format(output->info()->format());
286 kernel_name << "_bt709";
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100287 _input = input;
288 _multi_output = output;
289
290 // Create kernel
291 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
292
293 // Configure kernel window
294 Window win = calculate_max_window(*input->info(), Steps(num_elems_processed_per_iteration));
295 if((input->info()->format() != Format::RGB888 || output->info()->format() != Format::YUV444) && (input->info()->format() != Format::RGBA8888 || output->info()->format() != Format::YUV444))
296 {
297 win.set_dimension_step(Window::DimY, 2);
298 }
299
300 AccessWindowHorizontal output_plane0_access(output->plane(0)->info(), 0, num_elems_processed_per_iteration);
301 AccessWindowRectangle output_plane1_access(output->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1, sub_sampling, sub_sampling);
302 AccessWindowRectangle output_plane2_access(has_two_planes ? nullptr : output->plane(2)->info(), 0, 0,
303 num_elems_processed_per_iteration, 1, sub_sampling, sub_sampling);
304
Pablo Tello96fc1d62018-07-17 17:10:59 +0100305 AccessWindowHorizontal input_access(input->info(), 0, num_elems_read_per_iteration_x);
306
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100307 update_window_and_padding(win,
Pablo Tello96fc1d62018-07-17 17:10:59 +0100308 input_access,
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100309 output_plane0_access,
310 output_plane1_access,
311 output_plane2_access);
312
313 ValidRegion input_region = input->info()->valid_region();
314
315 output_plane0_access.set_valid_region(win, ValidRegion(input_region.anchor, output->plane(0)->info()->tensor_shape()));
316 output_plane1_access.set_valid_region(win, ValidRegion(input_region.anchor, output->plane(1)->info()->tensor_shape()));
317 output_plane2_access.set_valid_region(win, ValidRegion(input_region.anchor, output->plane(2)->info()->tensor_shape()));
318
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100319 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100320
321 // Set config_id for enabling LWS tuning
322 _config_id = kernel_name.str();
323 _config_id += "_";
324 _config_id += lower_string(string_from_data_type(input->info()->data_type()));
325 _config_id += "_";
326 _config_id += support::cpp11::to_string(input->info()->dimension(0));
327 _config_id += "_";
328 _config_id += support::cpp11::to_string(input->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100329}
330
331void CLColorConvertKernel::configure(const ICLMultiImage *input, ICLMultiImage *output)
332{
333 unsigned int num_elems_processed_per_iteration = 0;
334 switch(input->info()->format())
335 {
336 case Format::NV12:
337 case Format::NV21:
338 {
339 switch(output->info()->format())
340 {
341 case Format::IYUV:
342 case Format::YUV444:
343 num_elems_processed_per_iteration = 16;
344 break;
345 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100346 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100347 break;
348 }
349 break;
350 }
351 case Format::IYUV:
352 {
353 switch(output->info()->format())
354 {
355 case Format::YUV444:
356 case Format::NV12:
357 num_elems_processed_per_iteration = 16;
358 break;
359 default:
Manuel Bottiniacaf21d2018-09-26 17:38:19 +0100360 ARM_COMPUTE_ERROR("Not supported");
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100361 break;
362 }
363 break;
364 }
365 default:
366 break;
367 }
368 ARM_COMPUTE_ERROR_ON_MSG(num_elems_processed_per_iteration == 0, "Conversion from %s to %s not supported",
369 string_from_format(input->info()->format()).c_str(),
370 string_from_format(output->info()->format()).c_str());
371
372 std::stringstream kernel_name;
373
374 kernel_name << string_from_format(input->info()->format());
375 kernel_name << "_to_";
376 kernel_name << string_from_format(output->info()->format());
377 kernel_name << "_bt709";
378
379 _multi_input = input;
380 _multi_output = output;
381
382 // Create kernel
383 bool has_two_input_planars = (input->info()->format() == Format::NV12) || (input->info()->format() == Format::NV21);
384 bool has_two_output_planars = (output->info()->format() == Format::NV12) || (output->info()->format() == Format::NV21);
385
386 float sub_sampling_input = (has_two_input_planars || (input->info()->format() == Format::IYUV)) ? 0.5f : 1;
387 float sub_sampling_output = (has_two_output_planars || (output->info()->format() == Format::IYUV)) ? 0.5f : 1;
388
389 _kernel = static_cast<cl::Kernel>(CLKernelLibrary::get().create_kernel(kernel_name.str()));
390
391 Window win = calculate_max_window(*input->cl_plane(0)->info(), Steps(num_elems_processed_per_iteration));
392 win.set_dimension_step(Window::DimY, 2);
393
394 AccessWindowHorizontal input_plane0_access(input->plane(0)->info(), 0, num_elems_processed_per_iteration);
395 AccessWindowRectangle input_plane1_access(input->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1,
396 sub_sampling_input, sub_sampling_input);
397 AccessWindowRectangle input_plane2_access(has_two_input_planars ? nullptr : input->plane(2)->info(), 0, 0, num_elems_processed_per_iteration, 1,
398 sub_sampling_input, sub_sampling_input);
399 AccessWindowHorizontal output_plane0_access(output->plane(0)->info(), 0, num_elems_processed_per_iteration);
400 AccessWindowRectangle output_plane1_access(output->plane(1)->info(), 0, 0, num_elems_processed_per_iteration, 1, sub_sampling_output, sub_sampling_output);
401 AccessWindowRectangle output_plane2_access(has_two_output_planars ? nullptr : output->plane(2)->info(), 0, 0,
402 num_elems_processed_per_iteration, 1, sub_sampling_output, sub_sampling_output);
403
404 update_window_and_padding(win,
405 input_plane0_access, input_plane1_access, input_plane2_access,
406 output_plane0_access, output_plane1_access, output_plane2_access);
407
408 ValidRegion intersect_region = intersect_valid_regions(input->plane(0)->info()->valid_region(), input->plane(1)->info()->valid_region(),
409 input->plane(2)->info()->valid_region());
410 output_plane0_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->plane(0)->info()->tensor_shape()));
411 output_plane1_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->plane(1)->info()->tensor_shape()));
412 output_plane2_access.set_valid_region(win, ValidRegion(intersect_region.anchor, output->plane(2)->info()->tensor_shape()));
413
Anthony Barbierb6eb3532018-08-08 13:20:04 +0100414 ICLKernel::configure_internal(win);
Gary Antcliffefffbdbc2019-05-28 11:40:21 +0100415
416 // Set config_id for enabling LWS tuning
417 _config_id = kernel_name.str();
418 _config_id += "_";
419 _config_id += lower_string(string_from_data_type(input->plane(0)->info()->data_type()));
420 _config_id += "_";
421 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(0));
422 _config_id += "_";
423 _config_id += support::cpp11::to_string(input->plane(0)->info()->dimension(1));
424 _config_id += "_";
425 _config_id += lower_string(string_from_data_type(input->plane(1)->info()->data_type()));
426 _config_id += "_";
427 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(0));
428 _config_id += "_";
429 _config_id += support::cpp11::to_string(input->plane(1)->info()->dimension(1));
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100430}
431
432void CLColorConvertKernel::run(const Window &window, cl::CommandQueue &queue)
433{
434 ARM_COMPUTE_ERROR_ON_UNCONFIGURED_KERNEL(this);
435 ARM_COMPUTE_ERROR_ON_INVALID_SUBWINDOW(ICLKernel::window(), window);
436
437 Window slice = window.first_slice_window_2D();
438
439 if(nullptr != _input && nullptr != _output)
440 {
441 do
442 {
443 unsigned int idx = 0;
444 add_2D_tensor_argument(idx, _input, slice);
445 add_2D_tensor_argument(idx, _output, slice);
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100446 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100447 }
448 while(window.slide_window_slice_2D(slice));
449 }
450 else if(nullptr != _input && nullptr != _multi_output)
451 {
452 Format format = _multi_output->info()->format();
453 do
454 {
455 Window win_uv(slice);
456
457 if((Format::NV12 == format) || (Format::NV21 == format) || (Format::IYUV == format))
458 {
459 win_uv.set(Window::DimX, Window::Dimension(win_uv.x().start() / 2, win_uv.x().end() / 2, win_uv.x().step() / 2));
460 win_uv.set(Window::DimY, Window::Dimension(win_uv.y().start() / 2, win_uv.y().end() / 2, 1));
461 }
462 unsigned int idx = 0;
463 add_2D_tensor_argument(idx, _input, slice);
464 add_2D_tensor_argument(idx, _multi_output->cl_plane(0), slice);
465 for(int i = 1; i < 3 && (0 != _multi_output->cl_plane(i)->info()->num_dimensions()); ++i)
466 {
467 add_2D_tensor_argument(idx, _multi_output->cl_plane(i), win_uv);
468 }
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100469 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100470 }
471 while(window.slide_window_slice_2D(slice));
472 }
473 else if(nullptr != _multi_input && nullptr != _output)
474 {
475 Format format = _multi_input->info()->format();
476 do
477 {
478 Window win_uv(slice);
479
480 if((Format::NV12 == format) || (Format::NV21 == format) || (Format::IYUV == format))
481 {
482 win_uv.set(Window::DimX, Window::Dimension(win_uv.x().start() / 2, win_uv.x().end() / 2, win_uv.x().step() / 2));
483 win_uv.set(Window::DimY, Window::Dimension(win_uv.y().start() / 2, win_uv.y().end() / 2, 1));
484 }
485
486 unsigned int idx = 0;
487 add_2D_tensor_argument(idx, _multi_input->cl_plane(0), slice);
488
489 for(int i = 1; i < 3 && (0 != _multi_input->cl_plane(i)->info()->num_dimensions()); ++i)
490 {
491 add_2D_tensor_argument(idx, _multi_input->cl_plane(i), win_uv);
492 }
493 add_2D_tensor_argument(idx, _output, slice);
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100494 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100495 }
496 while(window.slide_window_slice_2D(slice));
497 }
498 else if(nullptr != _multi_input && nullptr != _multi_output)
499 {
500 Format in_format = _multi_input->info()->format();
501 Format out_format = _multi_output->info()->format();
502 do
503 {
504 Window win_in_uv(slice);
505 if((Format::NV12 == in_format) || (Format::NV21 == in_format) || (Format::IYUV == in_format))
506 {
507 win_in_uv.set(Window::DimX, Window::Dimension(win_in_uv.x().start() / 2,
508 win_in_uv.x().end() / 2, win_in_uv.x().step() / 2));
509 win_in_uv.set(Window::DimY, Window::Dimension(win_in_uv.y().start() / 2, win_in_uv.y().end() / 2, 1));
510 }
511 unsigned int idx = 0;
512 add_2D_tensor_argument(idx, _multi_input->cl_plane(0), slice);
513 for(int i = 1; i < 3 && (0 != _multi_input->cl_plane(i)->info()->num_dimensions()); ++i)
514 {
515 add_2D_tensor_argument(idx, _multi_input->cl_plane(i), win_in_uv);
516 }
517
518 Window win_out_uv(slice);
519 if((Format::NV12 == out_format) || (Format::NV21 == out_format) || (Format::IYUV == out_format))
520 {
521 win_out_uv.set(Window::DimX, Window::Dimension(win_out_uv.x().start() / 2,
522 win_out_uv.x().end() / 2, win_out_uv.x().step() / 2));
523 win_out_uv.set(Window::DimY, Window::Dimension(win_out_uv.y().start() / 2, win_out_uv.y().end() / 2, 1));
524 }
525
526 add_2D_tensor_argument(idx, _multi_output->cl_plane(0), slice);
527 for(int i = 1; i < 3 && (0 != _multi_output->cl_plane(i)->info()->num_dimensions()); ++i)
528 {
529 add_2D_tensor_argument(idx, _multi_output->cl_plane(i), win_out_uv);
530 }
Michele Di Giorgio6b9f3882019-07-01 16:37:04 +0100531 enqueue(queue, *this, slice, lws_hint());
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100532 }
533 while(window.slide_window_slice_2D(slice));
534 }
535 else
536 {
537 ARM_COMPUTE_ERROR("Not supported");
538 }
539}