blob: e628e9bd5b89d1333bacb40178e3a29ecb05c454 [file] [log] [blame]
Anthony Barbier6ff3b192017-09-04 18:44:23 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
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 "helpers.h"
25#include "types.h"
26
27#ifndef DATA_TYPE_MIN
28#define DATA_TYPE_MIN 0x0
Anthony Barbierac69aa12017-07-03 17:39:37 +010029#endif /* DATA_TYPE_MIN */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010030
31#ifndef DATA_TYPE_MAX
32#define DATA_TYPE_MAX 0xFF
Anthony Barbierac69aa12017-07-03 17:39:37 +010033#endif /* DATA_TYPE_MAX */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010034
35__constant VEC_DATA_TYPE(DATA_TYPE, 16) type_min = (VEC_DATA_TYPE(DATA_TYPE, 16))(DATA_TYPE_MIN);
36__constant VEC_DATA_TYPE(DATA_TYPE, 16) type_max = (VEC_DATA_TYPE(DATA_TYPE, 16))(DATA_TYPE_MAX);
37__constant uint16 idx16 = (uint16)(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
38
39/** This function identifies the min and maximum value of an input image.
40 *
41 * @note Input image data type must be passed as a preprocessor argument using -DDATA_TYPE.
42 * Moreover, the minimum and maximum value of the given data type must be provided using -DDATA_TYPE_MIN and -DDATA_TYPE_MAX respectively.
43 * @note In case image width is not a multiple of 16 then -DNON_MULTIPLE_OF_16 must be passed.
44 *
45 * @param[in] src_ptr Pointer to the source image. Supported data types: U8
46 * @param[in] src_stride_x Stride of the source image in X dimension (in bytes)
47 * @param[in] src_step_x src_stride_x * number of elements along X processed per workitem(in bytes)
48 * @param[in] src_stride_y Stride of the source image in Y dimension (in bytes)
49 * @param[in] src_step_y src_stride_y * number of elements along Y processed per workitem(in bytes)
50 * @param[in] src_offset_first_element_in_bytes The offset of the first element in the source image
51 * @param[out] min_max Pointer to buffer with minimum value in position 0 and maximum value in position 1
52 * @param[in] width Input image width
53 */
54__kernel void minmax(
55 IMAGE_DECLARATION(src),
56 __global int *min_max,
57 uint width)
58{
59 Image src = CONVERT_TO_IMAGE_STRUCT(src);
60
61 // Initialize local minimum and local maximum
62 VEC_DATA_TYPE(DATA_TYPE, 16)
63 local_min = type_max;
64 VEC_DATA_TYPE(DATA_TYPE, 16)
65 local_max = type_min;
66
67 // Calculate min/max of row
68 uint width4 = width >> 4;
69 for(uint i = 0; i < width4; i++)
70 {
71 VEC_DATA_TYPE(DATA_TYPE, 16)
72 data = vload16(0, (__global DATA_TYPE *)offset(&src, i << 4, 0));
73 local_min = min(data, local_min);
74 local_max = max(data, local_max);
75 }
76
77#ifdef NON_MULTIPLE_OF_16
78 // Handle non multiple of 16
79 VEC_DATA_TYPE(DATA_TYPE, 16)
80 data = vload16(0, (__global DATA_TYPE *)offset(&src, width4 << 4, 0));
81 VEC_DATA_TYPE(DATA_TYPE, 16)
82 widx = CONVERT(((uint16)(width4 << 4) + idx16) < width, VEC_DATA_TYPE(DATA_TYPE, 16));
83 local_max = max(local_max, select(type_min, data, widx));
84 local_min = min(local_min, select(type_max, data, widx));
Anthony Barbierac69aa12017-07-03 17:39:37 +010085#endif /* NON_MULTIPLE_OF_16 */
Anthony Barbier6ff3b192017-09-04 18:44:23 +010086
87 // Perform min/max reduction
88 local_min.s01234567 = min(local_min.s01234567, local_min.s89ABCDEF);
89 local_max.s01234567 = max(local_max.s01234567, local_max.s89ABCDEF);
90
91 local_min.s0123 = min(local_min.s0123, local_min.s4567);
92 local_max.s0123 = max(local_max.s0123, local_max.s4567);
93
94 local_min.s01 = min(local_min.s01, local_min.s23);
95 local_max.s01 = max(local_max.s01, local_max.s23);
96
97 local_min.s0 = min(local_min.s0, local_min.s1);
98 local_max.s0 = max(local_max.s0, local_max.s1);
99
100 // Update global min/max
101 atomic_min(&min_max[0], local_min.s0);
102 atomic_max(&min_max[1], local_max.s0);
103}
104
105/** This function counts the min and max occurrences in an image and tags their position.
106 *
107 * @note -DCOUNT_MIN_MAX should be specified if we want to count the occurrences of the minimum and maximum values.
108 * @note -DLOCATE_MIN and/or -DLOCATE_MAX should be specified if we want to store the position of each occurrence on the given array.
109 *
110 * @param[in] src_ptr Pointer to the source image. Supported data types: U8
111 * @param[in] src_stride_x Stride of the source image in X dimension (in bytes)
112 * @param[in] src_step_x src_stride_x * number of elements along X processed per workitem(in bytes)
113 * @param[in] src_stride_y Stride of the source image in Y dimension (in bytes)
114 * @param[in] src_step_y src_stride_y * number of elements along Y processed per workitem(in bytes)
115 * @param[in] src_offset_first_element_in_bytes The offset of the first element in the source image
116 * @param[in] min_max Pointer to buffer with minimum value in position 0 and maximum value in position 1
117 * @param[out] min_max_count Pointer to buffer with minimum value occurrences in position 0 and maximum value occurrences in position 1
118 * @param[out] min_loc Array that holds the location of the minimum value occurrences
119 * @param[in] max_min_loc_count The maximum number of min value occurrences coordinates the array can hold
120 * @param[out] max_loc Array that holds the location of the maximum value occurrences
121 * @param[in] max_max_loc_count The maximum number of max value occurrences coordinates the array can hold
122 */
123__kernel void minmaxloc(
124 IMAGE_DECLARATION(src),
125 __global int *min_max,
126 __global uint *min_max_count
Anthony Barbierac69aa12017-07-03 17:39:37 +0100127#ifdef LOCATE_MIN
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100128 ,
129 __global Coordinates2D *min_loc, uint max_min_loc_count
Anthony Barbierac69aa12017-07-03 17:39:37 +0100130#endif /* LOCATE_MIN */
131#ifdef LOCATE_MAX
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100132 ,
133 __global Coordinates2D *max_loc, uint max_max_loc_count
Anthony Barbierac69aa12017-07-03 17:39:37 +0100134#endif /* LOCATE_MAX */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100135)
136{
137 Image src = CONVERT_TO_IMAGE_STRUCT(src);
138
139 DATA_TYPE value = *((__global DATA_TYPE *)src.ptr);
Anthony Barbierac69aa12017-07-03 17:39:37 +0100140#ifdef COUNT_MIN_MAX
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100141 if(value == min_max[0])
142 {
143 uint idx = atomic_inc(&min_max_count[0]);
Anthony Barbierac69aa12017-07-03 17:39:37 +0100144#ifdef LOCATE_MIN
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100145 if(idx < max_min_loc_count)
146 {
147 min_loc[idx].x = get_global_id(0);
148 min_loc[idx].y = get_global_id(1);
149 }
Anthony Barbierac69aa12017-07-03 17:39:37 +0100150#endif /* LOCATE_MIN */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100151 }
152 if(value == min_max[1])
153 {
154 uint idx = atomic_inc(&min_max_count[1]);
Anthony Barbierac69aa12017-07-03 17:39:37 +0100155#ifdef LOCATE_MAX
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100156 if(idx < max_max_loc_count)
157 {
158 max_loc[idx].x = get_global_id(0);
159 max_loc[idx].y = get_global_id(1);
160 }
Anthony Barbierac69aa12017-07-03 17:39:37 +0100161#endif /* LOCATE_MAX */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100162 }
Anthony Barbierac69aa12017-07-03 17:39:37 +0100163#endif /* COUNT_MIN_MAX */
Anthony Barbier6ff3b192017-09-04 18:44:23 +0100164}