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