1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //    http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #ifndef _imageHelpers_h
17 #define _imageHelpers_h
18 
19 #include "compat.h"
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <vector>
27 
28 #if !defined(_WIN32)
29 #include <unistd.h>
30 #endif
31 
32 #include <time.h>
33 
34 #include "errorHelpers.h"
35 
36 #include "conversions.h"
37 #include "typeWrappers.h"
38 #include "kernelHelpers.h"
39 #include "errorHelpers.h"
40 #include "mt19937.h"
41 #include "rounding_mode.h"
42 #include "clImageHelper.h"
43 
44 #include <CL/cl_half.h>
45 
46 extern cl_device_type gDeviceType;
47 extern bool gTestRounding;
48 
49 // Number of iterations per image format to test if not testing max images,
50 // rounding, or small images
51 #define NUM_IMAGE_ITERATIONS 3
52 
53 
54 // Definition for our own sampler type, to mirror the cl_sampler internals
55 #define MAX_sRGB_TO_lRGB_CONVERSION_ERROR 0.5
56 #define MAX_lRGB_TO_sRGB_CONVERSION_ERROR 0.6
57 
58 // Definition for our own sampler type, to mirror the cl_sampler internals
59 typedef struct
60 {
61     cl_addressing_mode addressing_mode;
62     cl_filter_mode filter_mode;
63     bool normalized_coords;
64 } image_sampler_data;
65 
66 int round_to_even(float v);
67 
68 #define NORMALIZE(v, max) (v < 0 ? 0 : (v > 1.f ? max : round_to_even(v * max)))
69 #define NORMALIZE_UNROUNDED(v, max) (v < 0 ? 0 : (v > 1.f ? max : v * max))
70 #define NORMALIZE_SIGNED(v, min, max)                                          \
71     (v < -1.0f ? min : (v > 1.f ? max : round_to_even(v * max)))
72 #define NORMALIZE_SIGNED_UNROUNDED(v, min, max)                                \
73     (v < -1.0f ? min : (v > 1.f ? max : v * max))
74 #define CONVERT_INT(v, min, max, max_val)                                      \
75     (v < min ? min : (v > max ? max_val : round_to_even(v)))
76 #define CONVERT_UINT(v, max, max_val)                                          \
77     (v < 0 ? 0 : (v > max ? max_val : round_to_even(v)))
78 
79 extern void print_read_header(const cl_image_format *format,
80                               image_sampler_data *sampler, bool err = false,
81                               int t = 0);
82 extern void print_write_header(const cl_image_format *format, bool err);
83 extern void print_header(const cl_image_format *format, bool err);
84 extern bool find_format(cl_image_format *formatList, unsigned int numFormats,
85                         cl_image_format *formatToFind);
86 extern bool is_image_format_required(cl_image_format format, cl_mem_flags flags,
87                                      cl_mem_object_type image_type,
88                                      cl_device_id device);
89 extern void
90 build_required_image_formats(cl_mem_flags flags, cl_mem_object_type image_type,
91                              cl_device_id device,
92                              std::vector<cl_image_format> &formatsToSupport);
93 
94 extern uint32_t get_format_type_size(const cl_image_format *format);
95 extern uint32_t get_channel_data_type_size(cl_channel_type channelType);
96 extern uint32_t get_format_channel_count(const cl_image_format *format);
97 extern uint32_t get_channel_order_channel_count(cl_channel_order order);
98 cl_channel_type get_channel_type_from_name(const char *name);
99 cl_channel_order get_channel_order_from_name(const char *name);
100 extern int is_format_signed(const cl_image_format *format);
101 extern uint32_t get_pixel_size(const cl_image_format *format);
102 
103 /* Helper to get any ol image format as long as it is 8-bits-per-channel */
104 extern int get_8_bit_image_format(cl_context context,
105                                   cl_mem_object_type objType,
106                                   cl_mem_flags flags, size_t channelCount,
107                                   cl_image_format *outFormat);
108 
109 /* Helper to get any ol image format as long as it is 32-bits-per-channel */
110 extern int get_32_bit_image_format(cl_context context,
111                                    cl_mem_object_type objType,
112                                    cl_mem_flags flags, size_t channelCount,
113                                    cl_image_format *outFormat);
114 
115 int random_in_range(int minV, int maxV, MTdata d);
116 int random_log_in_range(int minV, int maxV, MTdata d);
117 
118 typedef struct
119 {
120     size_t width;
121     size_t height;
122     size_t depth;
123     size_t rowPitch;
124     size_t slicePitch;
125     size_t arraySize;
126     const cl_image_format *format;
127     cl_mem buffer;
128     cl_mem_object_type type;
129     cl_uint num_mip_levels;
130 } image_descriptor;
131 
132 typedef struct
133 {
134     float p[4];
135 } FloatPixel;
136 
137 void print_first_pixel_difference_error(size_t where, const char *sourcePixel,
138                                         const char *destPixel,
139                                         image_descriptor *imageInfo, size_t y,
140                                         size_t thirdDim);
141 
142 void get_max_sizes(size_t *numberOfSizes, const int maxNumberOfSizes,
143                    size_t sizes[][3], size_t maxWidth, size_t maxHeight,
144                    size_t maxDepth, size_t maxArraySize,
145                    const cl_ulong maxIndividualAllocSize,
146                    const cl_ulong maxTotalAllocSize,
147                    cl_mem_object_type image_type, const cl_image_format *format,
148                    int usingMaxPixelSize = 0);
149 extern size_t get_format_max_int(const cl_image_format *format);
150 
151 extern cl_ulong get_image_size(image_descriptor const *imageInfo);
152 extern cl_ulong get_image_size_mb(image_descriptor const *imageInfo);
153 
154 extern char *generate_random_image_data(image_descriptor *imageInfo,
155                                         BufferOwningPtr<char> &Owner, MTdata d);
156 
157 extern int debug_find_vector_in_image(void *imagePtr,
158                                       image_descriptor *imageInfo,
159                                       void *vectorToFind, size_t vectorSize,
160                                       int *outX, int *outY, int *outZ,
161                                       size_t lod = 0);
162 
163 extern int debug_find_pixel_in_image(void *imagePtr,
164                                      image_descriptor *imageInfo,
165                                      unsigned int *valuesToFind, int *outX,
166                                      int *outY, int *outZ, int lod = 0);
167 extern int debug_find_pixel_in_image(void *imagePtr,
168                                      image_descriptor *imageInfo,
169                                      int *valuesToFind, int *outX, int *outY,
170                                      int *outZ, int lod = 0);
171 extern int debug_find_pixel_in_image(void *imagePtr,
172                                      image_descriptor *imageInfo,
173                                      float *valuesToFind, int *outX, int *outY,
174                                      int *outZ, int lod = 0);
175 
176 extern void copy_image_data(image_descriptor *srcImageInfo,
177                             image_descriptor *dstImageInfo, void *imageValues,
178                             void *destImageValues, const size_t sourcePos[],
179                             const size_t destPos[], const size_t regionSize[]);
180 
181 int has_alpha(const cl_image_format *format);
182 
183 extern bool is_sRGBA_order(cl_channel_order image_channel_order);
184 
185 inline float calculate_array_index(float coord, float extent);
186 
187 cl_uint compute_max_mip_levels(size_t width, size_t height, size_t depth);
188 cl_ulong compute_mipmapped_image_size(image_descriptor imageInfo);
189 size_t compute_mip_level_offset(image_descriptor *imageInfo, size_t lod);
190 
191 template <class T>
read_image_pixel(void * imageData,image_descriptor * imageInfo,int x,int y,int z,T * outData,int lod)192 void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
193                       int y, int z, T *outData, int lod)
194 {
195     size_t width_lod = imageInfo->width, height_lod = imageInfo->height,
196            depth_lod = imageInfo->depth,
197            slice_pitch_lod = 0 /*imageInfo->slicePitch*/,
198            row_pitch_lod = 0 /*imageInfo->rowPitch*/;
199     width_lod = (imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1;
200 
201     if (imageInfo->type != CL_MEM_OBJECT_IMAGE1D_ARRAY
202         && imageInfo->type != CL_MEM_OBJECT_IMAGE1D)
203         height_lod =
204             (imageInfo->height >> lod) ? (imageInfo->height >> lod) : 1;
205 
206     if (imageInfo->type == CL_MEM_OBJECT_IMAGE3D)
207         depth_lod = (imageInfo->depth >> lod) ? (imageInfo->depth >> lod) : 1;
208     row_pitch_lod = (imageInfo->num_mip_levels > 0)
209         ? (width_lod * get_pixel_size(imageInfo->format))
210         : imageInfo->rowPitch;
211     slice_pitch_lod = (imageInfo->num_mip_levels > 0)
212         ? (row_pitch_lod * height_lod)
213         : imageInfo->slicePitch;
214 
215     // correct depth_lod and height_lod for array image types in order to avoid
216     // return
217     if (imageInfo->type == CL_MEM_OBJECT_IMAGE1D_ARRAY && height_lod == 1
218         && depth_lod == 1)
219     {
220         depth_lod = 0;
221         height_lod = 0;
222     }
223 
224     if (imageInfo->type == CL_MEM_OBJECT_IMAGE2D_ARRAY && depth_lod == 1)
225     {
226         depth_lod = 0;
227     }
228 
229     if (x < 0 || x >= (int)width_lod
230         || (height_lod != 0 && (y < 0 || y >= (int)height_lod))
231         || (depth_lod != 0 && (z < 0 || z >= (int)depth_lod))
232         || (imageInfo->arraySize != 0
233             && (z < 0 || z >= (int)imageInfo->arraySize)))
234     {
235         // Border color
236         if (imageInfo->format->image_channel_order == CL_DEPTH)
237         {
238             outData[0] = 1;
239         }
240         else
241         {
242             outData[0] = outData[1] = outData[2] = outData[3] = 0;
243             if (!has_alpha(imageInfo->format)) outData[3] = 1;
244         }
245         return;
246     }
247 
248     const cl_image_format *format = imageInfo->format;
249 
250     unsigned int i;
251     T tempData[4];
252 
253     // Advance to the right spot
254     char *ptr = (char *)imageData;
255     size_t pixelSize = get_pixel_size(format);
256 
257     ptr += z * slice_pitch_lod + y * row_pitch_lod + x * pixelSize;
258 
259     // OpenCL only supports reading floats from certain formats
260     switch (format->image_channel_data_type)
261     {
262         case CL_SNORM_INT8: {
263             cl_char *dPtr = (cl_char *)ptr;
264             for (i = 0; i < get_format_channel_count(format); i++)
265                 tempData[i] = (T)dPtr[i];
266             break;
267         }
268 
269         case CL_UNORM_INT8: {
270             cl_uchar *dPtr = (cl_uchar *)ptr;
271             for (i = 0; i < get_format_channel_count(format); i++)
272                 tempData[i] = (T)dPtr[i];
273             break;
274         }
275 
276         case CL_SIGNED_INT8: {
277             cl_char *dPtr = (cl_char *)ptr;
278             for (i = 0; i < get_format_channel_count(format); i++)
279                 tempData[i] = (T)dPtr[i];
280             break;
281         }
282 
283         case CL_UNSIGNED_INT8: {
284             cl_uchar *dPtr = (cl_uchar *)ptr;
285             for (i = 0; i < get_format_channel_count(format); i++)
286                 tempData[i] = (T)dPtr[i];
287             break;
288         }
289 
290         case CL_SNORM_INT16: {
291             cl_short *dPtr = (cl_short *)ptr;
292             for (i = 0; i < get_format_channel_count(format); i++)
293                 tempData[i] = (T)dPtr[i];
294             break;
295         }
296 
297         case CL_UNORM_INT16: {
298             cl_ushort *dPtr = (cl_ushort *)ptr;
299             for (i = 0; i < get_format_channel_count(format); i++)
300                 tempData[i] = (T)dPtr[i];
301             break;
302         }
303 
304         case CL_SIGNED_INT16: {
305             cl_short *dPtr = (cl_short *)ptr;
306             for (i = 0; i < get_format_channel_count(format); i++)
307                 tempData[i] = (T)dPtr[i];
308             break;
309         }
310 
311         case CL_UNSIGNED_INT16: {
312             cl_ushort *dPtr = (cl_ushort *)ptr;
313             for (i = 0; i < get_format_channel_count(format); i++)
314                 tempData[i] = (T)dPtr[i];
315             break;
316         }
317 
318         case CL_HALF_FLOAT: {
319             cl_half *dPtr = (cl_half *)ptr;
320             for (i = 0; i < get_format_channel_count(format); i++)
321                 tempData[i] = (T)cl_half_to_float(dPtr[i]);
322             break;
323         }
324 
325         case CL_SIGNED_INT32: {
326             cl_int *dPtr = (cl_int *)ptr;
327             for (i = 0; i < get_format_channel_count(format); i++)
328                 tempData[i] = (T)dPtr[i];
329             break;
330         }
331 
332         case CL_UNSIGNED_INT32: {
333             cl_uint *dPtr = (cl_uint *)ptr;
334             for (i = 0; i < get_format_channel_count(format); i++)
335                 tempData[i] = (T)dPtr[i];
336             break;
337         }
338 
339         case CL_UNORM_SHORT_565: {
340             cl_ushort *dPtr = (cl_ushort *)ptr;
341             tempData[0] = (T)(dPtr[0] >> 11);
342             tempData[1] = (T)((dPtr[0] >> 5) & 63);
343             tempData[2] = (T)(dPtr[0] & 31);
344             break;
345         }
346 
347 #ifdef OBSOLETE_FORMAT
348         case CL_UNORM_SHORT_565_REV: {
349             unsigned short *dPtr = (unsigned short *)ptr;
350             tempData[2] = (T)(dPtr[0] >> 11);
351             tempData[1] = (T)((dPtr[0] >> 5) & 63);
352             tempData[0] = (T)(dPtr[0] & 31);
353             break;
354         }
355 
356         case CL_UNORM_SHORT_555_REV: {
357             unsigned short *dPtr = (unsigned short *)ptr;
358             tempData[2] = (T)((dPtr[0] >> 10) & 31);
359             tempData[1] = (T)((dPtr[0] >> 5) & 31);
360             tempData[0] = (T)(dPtr[0] & 31);
361             break;
362         }
363 
364         case CL_UNORM_INT_8888: {
365             unsigned int *dPtr = (unsigned int *)ptr;
366             tempData[3] = (T)(dPtr[0] >> 24);
367             tempData[2] = (T)((dPtr[0] >> 16) & 0xff);
368             tempData[1] = (T)((dPtr[0] >> 8) & 0xff);
369             tempData[0] = (T)(dPtr[0] & 0xff);
370             break;
371         }
372         case CL_UNORM_INT_8888_REV: {
373             unsigned int *dPtr = (unsigned int *)ptr;
374             tempData[0] = (T)(dPtr[0] >> 24);
375             tempData[1] = (T)((dPtr[0] >> 16) & 0xff);
376             tempData[2] = (T)((dPtr[0] >> 8) & 0xff);
377             tempData[3] = (T)(dPtr[0] & 0xff);
378             break;
379         }
380 
381         case CL_UNORM_INT_101010_REV: {
382             unsigned int *dPtr = (unsigned int *)ptr;
383             tempData[2] = (T)((dPtr[0] >> 20) & 0x3ff);
384             tempData[1] = (T)((dPtr[0] >> 10) & 0x3ff);
385             tempData[0] = (T)(dPtr[0] & 0x3ff);
386             break;
387         }
388 #endif
389         case CL_UNORM_SHORT_555: {
390             cl_ushort *dPtr = (cl_ushort *)ptr;
391             tempData[0] = (T)((dPtr[0] >> 10) & 31);
392             tempData[1] = (T)((dPtr[0] >> 5) & 31);
393             tempData[2] = (T)(dPtr[0] & 31);
394             break;
395         }
396 
397         case CL_UNORM_INT_101010: {
398             cl_uint *dPtr = (cl_uint *)ptr;
399             tempData[0] = (T)((dPtr[0] >> 20) & 0x3ff);
400             tempData[1] = (T)((dPtr[0] >> 10) & 0x3ff);
401             tempData[2] = (T)(dPtr[0] & 0x3ff);
402             break;
403         }
404 
405         case CL_FLOAT: {
406             cl_float *dPtr = (cl_float *)ptr;
407             for (i = 0; i < get_format_channel_count(format); i++)
408                 tempData[i] = (T)dPtr[i];
409             break;
410         }
411 #ifdef CL_SFIXED14_APPLE
412         case CL_SFIXED14_APPLE: {
413             cl_float *dPtr = (cl_float *)ptr;
414             for (i = 0; i < get_format_channel_count(format); i++)
415                 tempData[i] = (T)dPtr[i] + 0x4000;
416             break;
417         }
418 #endif
419     }
420 
421 
422     outData[0] = outData[1] = outData[2] = 0;
423     outData[3] = 1;
424 
425     if (format->image_channel_order == CL_A)
426     {
427         outData[3] = tempData[0];
428     }
429     else if (format->image_channel_order == CL_R)
430     {
431         outData[0] = tempData[0];
432     }
433     else if (format->image_channel_order == CL_Rx)
434     {
435         outData[0] = tempData[0];
436     }
437     else if (format->image_channel_order == CL_RA)
438     {
439         outData[0] = tempData[0];
440         outData[3] = tempData[1];
441     }
442     else if (format->image_channel_order == CL_RG)
443     {
444         outData[0] = tempData[0];
445         outData[1] = tempData[1];
446     }
447     else if (format->image_channel_order == CL_RGx)
448     {
449         outData[0] = tempData[0];
450         outData[1] = tempData[1];
451     }
452     else if ((format->image_channel_order == CL_RGB)
453              || (format->image_channel_order == CL_sRGB))
454     {
455         outData[0] = tempData[0];
456         outData[1] = tempData[1];
457         outData[2] = tempData[2];
458     }
459     else if ((format->image_channel_order == CL_RGBx)
460              || (format->image_channel_order == CL_sRGBx))
461     {
462         outData[0] = tempData[0];
463         outData[1] = tempData[1];
464         outData[2] = tempData[2];
465         outData[3] = 0;
466     }
467     else if ((format->image_channel_order == CL_RGBA)
468              || (format->image_channel_order == CL_sRGBA))
469     {
470         outData[0] = tempData[0];
471         outData[1] = tempData[1];
472         outData[2] = tempData[2];
473         outData[3] = tempData[3];
474     }
475     else if (format->image_channel_order == CL_ARGB)
476     {
477         outData[0] = tempData[1];
478         outData[1] = tempData[2];
479         outData[2] = tempData[3];
480         outData[3] = tempData[0];
481     }
482     else if ((format->image_channel_order == CL_BGRA)
483              || (format->image_channel_order == CL_sBGRA))
484     {
485         outData[0] = tempData[2];
486         outData[1] = tempData[1];
487         outData[2] = tempData[0];
488         outData[3] = tempData[3];
489     }
490     else if (format->image_channel_order == CL_INTENSITY)
491     {
492         outData[0] = tempData[0];
493         outData[1] = tempData[0];
494         outData[2] = tempData[0];
495         outData[3] = tempData[0];
496     }
497     else if (format->image_channel_order == CL_LUMINANCE)
498     {
499         outData[0] = tempData[0];
500         outData[1] = tempData[0];
501         outData[2] = tempData[0];
502     }
503     else if (format->image_channel_order == CL_DEPTH)
504     {
505         outData[0] = tempData[0];
506     }
507 #ifdef CL_1RGB_APPLE
508     else if (format->image_channel_order == CL_1RGB_APPLE)
509     {
510         outData[0] = tempData[1];
511         outData[1] = tempData[2];
512         outData[2] = tempData[3];
513         outData[3] = 0xff;
514     }
515 #endif
516 #ifdef CL_BGR1_APPLE
517     else if (format->image_channel_order == CL_BGR1_APPLE)
518     {
519         outData[0] = tempData[2];
520         outData[1] = tempData[1];
521         outData[2] = tempData[0];
522         outData[3] = 0xff;
523     }
524 #endif
525     else
526     {
527         log_error("Invalid format:");
528         print_header(format, true);
529     }
530 }
531 
532 template <class T>
read_image_pixel(void * imageData,image_descriptor * imageInfo,int x,int y,int z,T * outData)533 void read_image_pixel(void *imageData, image_descriptor *imageInfo, int x,
534                       int y, int z, T *outData)
535 {
536     read_image_pixel<T>(imageData, imageInfo, x, y, z, outData, 0);
537 }
538 
539 // Stupid template rules
540 bool get_integer_coords(float x, float y, float z, size_t width, size_t height,
541                         size_t depth, image_sampler_data *imageSampler,
542                         image_descriptor *imageInfo, int &outX, int &outY,
543                         int &outZ);
544 bool get_integer_coords_offset(float x, float y, float z, float xAddressOffset,
545                                float yAddressOffset, float zAddressOffset,
546                                size_t width, size_t height, size_t depth,
547                                image_sampler_data *imageSampler,
548                                image_descriptor *imageInfo, int &outX,
549                                int &outY, int &outZ);
550 
551 
552 template <class T>
sample_image_pixel_offset(void * imageData,image_descriptor * imageInfo,float x,float y,float z,float xAddressOffset,float yAddressOffset,float zAddressOffset,image_sampler_data * imageSampler,T * outData,int lod)553 void sample_image_pixel_offset(void *imageData, image_descriptor *imageInfo,
554                                float x, float y, float z, float xAddressOffset,
555                                float yAddressOffset, float zAddressOffset,
556                                image_sampler_data *imageSampler, T *outData,
557                                int lod)
558 {
559     int iX = 0, iY = 0, iZ = 0;
560 
561     float max_w = imageInfo->width;
562     float max_h;
563     float max_d;
564 
565     switch (imageInfo->type)
566     {
567         case CL_MEM_OBJECT_IMAGE1D_ARRAY:
568             max_h = imageInfo->arraySize;
569             max_d = 0;
570             break;
571         case CL_MEM_OBJECT_IMAGE2D_ARRAY:
572             max_h = imageInfo->height;
573             max_d = imageInfo->arraySize;
574             break;
575         default:
576             max_h = imageInfo->height;
577             max_d = imageInfo->depth;
578             break;
579     }
580 
581     if (/*gTestMipmaps*/ imageInfo->num_mip_levels > 1)
582     {
583         switch (imageInfo->type)
584         {
585             case CL_MEM_OBJECT_IMAGE3D:
586                 max_d = (float)((imageInfo->depth >> lod)
587                                     ? (imageInfo->depth >> lod)
588                                     : 1);
589             case CL_MEM_OBJECT_IMAGE2D:
590             case CL_MEM_OBJECT_IMAGE2D_ARRAY:
591                 max_h = (float)((imageInfo->height >> lod)
592                                     ? (imageInfo->height >> lod)
593                                     : 1);
594                 break;
595             default:;
596         }
597         max_w =
598             (float)((imageInfo->width >> lod) ? (imageInfo->width >> lod) : 1);
599     }
600     get_integer_coords_offset(x, y, z, xAddressOffset, yAddressOffset,
601                               zAddressOffset, max_w, max_h, max_d, imageSampler,
602                               imageInfo, iX, iY, iZ);
603 
604     read_image_pixel<T>(imageData, imageInfo, iX, iY, iZ, outData, lod);
605 }
606 
607 template <class T>
sample_image_pixel_offset(void * imageData,image_descriptor * imageInfo,float x,float y,float z,float xAddressOffset,float yAddressOffset,float zAddressOffset,image_sampler_data * imageSampler,T * outData)608 void sample_image_pixel_offset(void *imageData, image_descriptor *imageInfo,
609                                float x, float y, float z, float xAddressOffset,
610                                float yAddressOffset, float zAddressOffset,
611                                image_sampler_data *imageSampler, T *outData)
612 {
613     sample_image_pixel_offset<T>(imageData, imageInfo, x, y, z, xAddressOffset,
614                                  yAddressOffset, zAddressOffset, imageSampler,
615                                  outData, 0);
616 }
617 
618 template <class T>
sample_image_pixel(void * imageData,image_descriptor * imageInfo,float x,float y,float z,image_sampler_data * imageSampler,T * outData)619 void sample_image_pixel(void *imageData, image_descriptor *imageInfo, float x,
620                         float y, float z, image_sampler_data *imageSampler,
621                         T *outData)
622 {
623     return sample_image_pixel_offset<T>(imageData, imageInfo, x, y, z, 0.0f,
624                                         0.0f, 0.0f, imageSampler, outData);
625 }
626 
627 FloatPixel
628 sample_image_pixel_float(void *imageData, image_descriptor *imageInfo, float x,
629                          float y, float z, image_sampler_data *imageSampler,
630                          float *outData, int verbose, int *containsDenorms);
631 
632 FloatPixel sample_image_pixel_float(void *imageData,
633                                     image_descriptor *imageInfo, float x,
634                                     float y, float z,
635                                     image_sampler_data *imageSampler,
636                                     float *outData, int verbose,
637                                     int *containsDenorms, int lod);
638 
639 FloatPixel sample_image_pixel_float_offset(
640     void *imageData, image_descriptor *imageInfo, float x, float y, float z,
641     float xAddressOffset, float yAddressOffset, float zAddressOffset,
642     image_sampler_data *imageSampler, float *outData, int verbose,
643     int *containsDenorms);
644 FloatPixel sample_image_pixel_float_offset(
645     void *imageData, image_descriptor *imageInfo, float x, float y, float z,
646     float xAddressOffset, float yAddressOffset, float zAddressOffset,
647     image_sampler_data *imageSampler, float *outData, int verbose,
648     int *containsDenorms, int lod);
649 
650 
651 extern void pack_image_pixel(unsigned int *srcVector,
652                              const cl_image_format *imageFormat, void *outData);
653 extern void pack_image_pixel(int *srcVector, const cl_image_format *imageFormat,
654                              void *outData);
655 extern void pack_image_pixel(float *srcVector,
656                              const cl_image_format *imageFormat, void *outData);
657 extern void pack_image_pixel_error(const float *srcVector,
658                                    const cl_image_format *imageFormat,
659                                    const void *results, float *errors);
660 
661 extern char *create_random_image_data(ExplicitType dataType,
662                                       image_descriptor *imageInfo,
663                                       BufferOwningPtr<char> &P, MTdata d,
664                                       bool image2DFromBuffer = false);
665 
666 // deprecated
667 // extern bool clamp_image_coord( image_sampler_data *imageSampler, float value,
668 // size_t max, int &outValue );
669 
670 extern void get_sampler_kernel_code(image_sampler_data *imageSampler,
671                                     char *outLine);
672 extern float get_max_absolute_error(const cl_image_format *format,
673                                     image_sampler_data *sampler);
674 extern float get_max_relative_error(const cl_image_format *format,
675                                     image_sampler_data *sampler, int is3D,
676                                     int isLinearFilter);
677 
678 
679 #define errMax(_x, _y) ((_x) != (_x) ? (_x) : (_x) > (_y) ? (_x) : (_y))
680 
abs_diff_uint(cl_uint x,cl_uint y)681 static inline cl_uint abs_diff_uint(cl_uint x, cl_uint y)
682 {
683     return y > x ? y - x : x - y;
684 }
685 
abs_diff_int(cl_int x,cl_int y)686 static inline cl_uint abs_diff_int(cl_int x, cl_int y)
687 {
688     return (cl_uint)(y > x ? y - x : x - y);
689 }
690 
relative_error(float test,float expected)691 static inline cl_float relative_error(float test, float expected)
692 {
693     // 0-0/0 is 0 in this case, not NaN
694     if (test == 0.0f && expected == 0.0f) return 0.0f;
695 
696     return (test - expected) / expected;
697 }
698 
699 extern float random_float(float low, float high);
700 
701 class CoordWalker {
702 public:
703     CoordWalker(void *coords, bool useFloats, size_t vecSize);
704     ~CoordWalker();
705 
706     cl_float Get(size_t idx, size_t el);
707 
708 protected:
709     cl_float *mFloatCoords;
710     cl_int *mIntCoords;
711     size_t mVecSize;
712 };
713 
714 extern cl_half convert_float_to_half(float f);
715 extern int DetectFloatToHalfRoundingMode(
716     cl_command_queue); // Returns CL_SUCCESS on success
717 
718 // sign bit: don't care, exponent: maximum value, significand: non-zero
is_half_nan(cl_half half)719 static int inline is_half_nan(cl_half half) { return (half & 0x7fff) > 0x7c00; }
720 
721 // sign bit: don't care, exponent: zero, significand: non-zero
is_half_denorm(cl_half half)722 static int inline is_half_denorm(cl_half half) { return IsHalfSubnormal(half); }
723 
724 // sign bit: don't care, exponent: zero, significand: zero
is_half_zero(cl_half half)725 static int inline is_half_zero(cl_half half) { return (half & 0x7fff) == 0; }
726 
727 extern double sRGBmap(float fc);
728 
729 extern const char *convert_image_type_to_string(cl_mem_object_type imageType);
730 
731 
732 #endif // _imageHelpers_h
733