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 #include "compat.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 #include "errorHelpers.h"
22 
23 #include "parseParameters.h"
24 
25 #include <CL/cl_half.h>
26 
IGetErrorString(int clErrorCode)27 const char *IGetErrorString(int clErrorCode)
28 {
29     switch (clErrorCode)
30     {
31         case CL_SUCCESS: return "CL_SUCCESS";
32         case CL_DEVICE_NOT_FOUND: return "CL_DEVICE_NOT_FOUND";
33         case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE";
34         case CL_COMPILER_NOT_AVAILABLE: return "CL_COMPILER_NOT_AVAILABLE";
35         case CL_MEM_OBJECT_ALLOCATION_FAILURE:
36             return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
37         case CL_OUT_OF_RESOURCES: return "CL_OUT_OF_RESOURCES";
38         case CL_OUT_OF_HOST_MEMORY: return "CL_OUT_OF_HOST_MEMORY";
39         case CL_PROFILING_INFO_NOT_AVAILABLE:
40             return "CL_PROFILING_INFO_NOT_AVAILABLE";
41         case CL_MEM_COPY_OVERLAP: return "CL_MEM_COPY_OVERLAP";
42         case CL_IMAGE_FORMAT_MISMATCH: return "CL_IMAGE_FORMAT_MISMATCH";
43         case CL_IMAGE_FORMAT_NOT_SUPPORTED:
44             return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
45         case CL_BUILD_PROGRAM_FAILURE: return "CL_BUILD_PROGRAM_FAILURE";
46         case CL_MAP_FAILURE: return "CL_MAP_FAILURE";
47         case CL_MISALIGNED_SUB_BUFFER_OFFSET:
48             return "CL_MISALIGNED_SUB_BUFFER_OFFSET";
49         case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
50             return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
51         case CL_COMPILE_PROGRAM_FAILURE: return "CL_COMPILE_PROGRAM_FAILURE";
52         case CL_LINKER_NOT_AVAILABLE: return "CL_LINKER_NOT_AVAILABLE";
53         case CL_LINK_PROGRAM_FAILURE: return "CL_LINK_PROGRAM_FAILURE";
54         case CL_DEVICE_PARTITION_FAILED: return "CL_DEVICE_PARTITION_FAILED";
55         case CL_KERNEL_ARG_INFO_NOT_AVAILABLE:
56             return "CL_KERNEL_ARG_INFO_NOT_AVAILABLE";
57         case CL_INVALID_VALUE: return "CL_INVALID_VALUE";
58         case CL_INVALID_DEVICE_TYPE: return "CL_INVALID_DEVICE_TYPE";
59         case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE";
60         case CL_INVALID_CONTEXT: return "CL_INVALID_CONTEXT";
61         case CL_INVALID_QUEUE_PROPERTIES: return "CL_INVALID_QUEUE_PROPERTIES";
62         case CL_INVALID_COMMAND_QUEUE: return "CL_INVALID_COMMAND_QUEUE";
63         case CL_INVALID_HOST_PTR: return "CL_INVALID_HOST_PTR";
64         case CL_INVALID_MEM_OBJECT: return "CL_INVALID_MEM_OBJECT";
65         case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
66             return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
67         case CL_INVALID_IMAGE_SIZE: return "CL_INVALID_IMAGE_SIZE";
68         case CL_INVALID_SAMPLER: return "CL_INVALID_SAMPLER";
69         case CL_INVALID_BINARY: return "CL_INVALID_BINARY";
70         case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS";
71         case CL_INVALID_PLATFORM: return "CL_INVALID_PLATFORM";
72         case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM";
73         case CL_INVALID_PROGRAM_EXECUTABLE:
74             return "CL_INVALID_PROGRAM_EXECUTABLE";
75         case CL_INVALID_KERNEL_NAME: return "CL_INVALID_KERNEL_NAME";
76         case CL_INVALID_KERNEL_DEFINITION:
77             return "CL_INVALID_KERNEL_DEFINITION";
78         case CL_INVALID_KERNEL: return "CL_INVALID_KERNEL";
79         case CL_INVALID_ARG_INDEX: return "CL_INVALID_ARG_INDEX";
80         case CL_INVALID_ARG_VALUE: return "CL_INVALID_ARG_VALUE";
81         case CL_INVALID_ARG_SIZE: return "CL_INVALID_ARG_SIZE";
82         case CL_INVALID_KERNEL_ARGS: return "CL_INVALID_KERNEL_ARGS";
83         case CL_INVALID_WORK_DIMENSION: return "CL_INVALID_WORK_DIMENSION";
84         case CL_INVALID_WORK_GROUP_SIZE: return "CL_INVALID_WORK_GROUP_SIZE";
85         case CL_INVALID_WORK_ITEM_SIZE: return "CL_INVALID_WORK_ITEM_SIZE";
86         case CL_INVALID_GLOBAL_OFFSET: return "CL_INVALID_GLOBAL_OFFSET";
87         case CL_INVALID_EVENT_WAIT_LIST: return "CL_INVALID_EVENT_WAIT_LIST";
88         case CL_INVALID_EVENT: return "CL_INVALID_EVENT";
89         case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION";
90         case CL_INVALID_GL_OBJECT: return "CL_INVALID_GL_OBJECT";
91         case CL_INVALID_BUFFER_SIZE: return "CL_INVALID_BUFFER_SIZE";
92         case CL_INVALID_MIP_LEVEL: return "CL_INVALID_MIP_LEVEL";
93         case CL_INVALID_GLOBAL_WORK_SIZE: return "CL_INVALID_GLOBAL_WORK_SIZE";
94         case CL_INVALID_PROPERTY: return "CL_INVALID_PROPERTY";
95         case CL_INVALID_IMAGE_DESCRIPTOR: return "CL_INVALID_IMAGE_DESCRIPTOR";
96         case CL_INVALID_COMPILER_OPTIONS: return "CL_INVALID_COMPILER_OPTIONS";
97         case CL_INVALID_LINKER_OPTIONS: return "CL_INVALID_LINKER_OPTIONS";
98         case CL_INVALID_DEVICE_PARTITION_COUNT:
99             return "CL_INVALID_DEVICE_PARTITION_COUNT";
100         case CL_INVALID_PIPE_SIZE: return "CL_INVALID_PIPE_SIZE";
101         case CL_INVALID_DEVICE_QUEUE: return "CL_INVALID_DEVICE_QUEUE";
102         case CL_INVALID_SPEC_ID: return "CL_INVALID_SPEC_ID";
103         case CL_MAX_SIZE_RESTRICTION_EXCEEDED:
104             return "CL_MAX_SIZE_RESTRICTION_EXCEEDED";
105         default: return "(unknown)";
106     }
107 }
108 
GetChannelOrderName(cl_channel_order order)109 const char *GetChannelOrderName(cl_channel_order order)
110 {
111     switch (order)
112     {
113         case CL_R: return "CL_R";
114         case CL_A: return "CL_A";
115         case CL_Rx: return "CL_Rx";
116         case CL_RG: return "CL_RG";
117         case CL_RA: return "CL_RA";
118         case CL_RGx: return "CL_RGx";
119         case CL_RGB: return "CL_RGB";
120         case CL_RGBx: return "CL_RGBx";
121         case CL_RGBA: return "CL_RGBA";
122         case CL_ARGB: return "CL_ARGB";
123         case CL_BGRA: return "CL_BGRA";
124         case CL_INTENSITY: return "CL_INTENSITY";
125         case CL_LUMINANCE: return "CL_LUMINANCE";
126 #if defined CL_1RGB_APPLE
127         case CL_1RGB_APPLE: return "CL_1RGB_APPLE";
128 #endif
129 #if defined CL_BGR1_APPLE
130         case CL_BGR1_APPLE: return "CL_BGR1_APPLE";
131 #endif
132 #if defined CL_ABGR_APPLE
133         case CL_ABGR_APPLE: return "CL_ABGR_APPLE";
134 #endif
135         case CL_DEPTH: return "CL_DEPTH";
136         case CL_DEPTH_STENCIL: return "CL_DEPTH_STENCIL";
137         case CL_sRGB: return "CL_sRGB";
138         case CL_sRGBA: return "CL_sRGBA";
139         case CL_sRGBx: return "CL_sRGBx";
140         case CL_sBGRA: return "CL_sBGRA";
141         case CL_ABGR: return "CL_ABGR";
142         default: return NULL;
143     }
144 }
145 
IsChannelOrderSupported(cl_channel_order order)146 int IsChannelOrderSupported(cl_channel_order order)
147 {
148     switch (order)
149     {
150         case CL_R:
151         case CL_A:
152         case CL_Rx:
153         case CL_RG:
154         case CL_RA:
155         case CL_RGx:
156         case CL_RGB:
157         case CL_RGBx:
158         case CL_RGBA:
159         case CL_ARGB:
160         case CL_BGRA:
161         case CL_INTENSITY:
162         case CL_LUMINANCE:
163         case CL_ABGR:
164         case CL_sRGB:
165         case CL_sRGBx:
166         case CL_sBGRA:
167         case CL_sRGBA:
168         case CL_DEPTH: return 1;
169 #if defined CL_1RGB_APPLE
170         case CL_1RGB_APPLE: return 1;
171 #endif
172 #if defined CL_BGR1_APPLE
173         case CL_BGR1_APPLE: return 1;
174 #endif
175         default: return 0;
176     }
177 }
178 
GetChannelTypeName(cl_channel_type type)179 const char *GetChannelTypeName(cl_channel_type type)
180 {
181     switch (type)
182     {
183         case CL_SNORM_INT8: return "CL_SNORM_INT8";
184         case CL_SNORM_INT16: return "CL_SNORM_INT16";
185         case CL_UNORM_INT8: return "CL_UNORM_INT8";
186         case CL_UNORM_INT16: return "CL_UNORM_INT16";
187         case CL_UNORM_SHORT_565: return "CL_UNORM_SHORT_565";
188         case CL_UNORM_SHORT_555: return "CL_UNORM_SHORT_555";
189         case CL_UNORM_INT_101010: return "CL_UNORM_INT_101010";
190         case CL_SIGNED_INT8: return "CL_SIGNED_INT8";
191         case CL_SIGNED_INT16: return "CL_SIGNED_INT16";
192         case CL_SIGNED_INT32: return "CL_SIGNED_INT32";
193         case CL_UNSIGNED_INT8: return "CL_UNSIGNED_INT8";
194         case CL_UNSIGNED_INT16: return "CL_UNSIGNED_INT16";
195         case CL_UNSIGNED_INT32: return "CL_UNSIGNED_INT32";
196         case CL_HALF_FLOAT: return "CL_HALF_FLOAT";
197         case CL_FLOAT: return "CL_FLOAT";
198 #ifdef CL_SFIXED14_APPLE
199         case CL_SFIXED14_APPLE: return "CL_SFIXED14_APPLE";
200 #endif
201         case CL_UNORM_INT24: return "CL_UNORM_INT24";
202         default: return NULL;
203     }
204 }
205 
IsChannelTypeSupported(cl_channel_type type)206 int IsChannelTypeSupported(cl_channel_type type)
207 {
208     switch (type)
209     {
210         case CL_SNORM_INT8:
211         case CL_SNORM_INT16:
212         case CL_UNORM_INT8:
213         case CL_UNORM_INT16:
214         case CL_UNORM_INT24:
215         case CL_UNORM_SHORT_565:
216         case CL_UNORM_SHORT_555:
217         case CL_UNORM_INT_101010:
218         case CL_SIGNED_INT8:
219         case CL_SIGNED_INT16:
220         case CL_SIGNED_INT32:
221         case CL_UNSIGNED_INT8:
222         case CL_UNSIGNED_INT16:
223         case CL_UNSIGNED_INT32:
224         case CL_HALF_FLOAT:
225         case CL_FLOAT: return 1;
226 #ifdef CL_SFIXED14_APPLE
227         case CL_SFIXED14_APPLE: return 1;
228 #endif
229         default: return 0;
230     }
231 }
232 
GetAddressModeName(cl_addressing_mode mode)233 const char *GetAddressModeName(cl_addressing_mode mode)
234 {
235     switch (mode)
236     {
237         case CL_ADDRESS_NONE: return "CL_ADDRESS_NONE";
238         case CL_ADDRESS_CLAMP_TO_EDGE: return "CL_ADDRESS_CLAMP_TO_EDGE";
239         case CL_ADDRESS_CLAMP: return "CL_ADDRESS_CLAMP";
240         case CL_ADDRESS_REPEAT: return "CL_ADDRESS_REPEAT";
241         case CL_ADDRESS_MIRRORED_REPEAT: return "CL_ADDRESS_MIRRORED_REPEAT";
242         default: return NULL;
243     }
244 }
245 
GetDeviceTypeName(cl_device_type type)246 const char *GetDeviceTypeName(cl_device_type type)
247 {
248     switch (type)
249     {
250         case CL_DEVICE_TYPE_GPU: return "CL_DEVICE_TYPE_GPU";
251         case CL_DEVICE_TYPE_CPU: return "CL_DEVICE_TYPE_CPU";
252         case CL_DEVICE_TYPE_ACCELERATOR: return "CL_DEVICE_TYPE_ACCELERATOR";
253         case CL_DEVICE_TYPE_ALL: return "CL_DEVICE_TYPE_ALL";
254         default: return NULL;
255     }
256 }
257 
GetDataVectorString(void * dataBuffer,size_t typeSize,size_t vecSize,char * buffer)258 const char *GetDataVectorString(void *dataBuffer, size_t typeSize,
259                                 size_t vecSize, char *buffer)
260 {
261     static char scratch[1024];
262     size_t i, j;
263 
264     if (buffer == NULL) buffer = scratch;
265 
266     unsigned char *p = (unsigned char *)dataBuffer;
267     char *bPtr;
268 
269     buffer[0] = 0;
270     bPtr = buffer;
271     for (i = 0; i < vecSize; i++)
272     {
273         if (i > 0)
274         {
275             bPtr[0] = ' ';
276             bPtr++;
277         }
278         for (j = 0; j < typeSize; j++)
279         {
280             sprintf(bPtr, "%02x", (unsigned int)p[typeSize - j - 1]);
281             bPtr += 2;
282         }
283         p += typeSize;
284     }
285     bPtr[0] = 0;
286 
287     return buffer;
288 }
289 
GetQueuePropertyName(cl_command_queue_properties property)290 const char *GetQueuePropertyName(cl_command_queue_properties property)
291 {
292     switch (property)
293     {
294         case CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE:
295             return "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE";
296         case CL_QUEUE_PROFILING_ENABLE: return "CL_QUEUE_PROFILING_ENABLE";
297         case CL_QUEUE_ON_DEVICE: return "CL_QUEUE_ON_DEVICE";
298         case CL_QUEUE_ON_DEVICE_DEFAULT: return "CL_QUEUE_ON_DEVICE_DEFAULT";
299         default: return "(unknown)";
300     }
301 }
302 
303 #ifndef MAX
304 #define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
305 #endif
306 
307 #if defined(_MSC_VER)
308 #define scalbnf(_a, _i) ldexpf(_a, _i)
309 #define scalbn(_a, _i) ldexp(_a, _i)
310 #define scalbnl(_a, _i) ldexpl(_a, _i)
311 #endif
312 
313 // taken from math tests
314 #define HALF_MIN_EXP -13
315 #define HALF_MANT_DIG 11
Ulp_Error_Half_Float(float test,double reference)316 static float Ulp_Error_Half_Float(float test, double reference)
317 {
318     union {
319         double d;
320         uint64_t u;
321     } u;
322     u.d = reference;
323 
324     // Note: This function presumes that someone has already tested whether the
325     // result is correctly, rounded before calling this function.  That test:
326     //
327     //    if( (float) reference == test )
328     //        return 0.0f;
329     //
330     // would ensure that cases like fabs(reference) > FLT_MAX are weeded out
331     // before we get here. Otherwise, we'll return inf ulp error here, for what
332     // are otherwise correctly rounded results.
333 
334     double testVal = test;
335 
336     if (isinf(reference))
337     {
338         if (testVal == reference) return 0.0f;
339 
340         return (float)(testVal - reference);
341     }
342 
343     if (isinf(testVal))
344     {
345         // Allow overflow within the limit of the allowed ulp error. Towards
346         // that end we pretend the test value is actually 2**16, the next value
347         // that would appear in the number line if half had sufficient range.
348         testVal = copysign(65536.0, testVal);
349     }
350 
351 
352     if (u.u & 0x000fffffffffffffULL)
353     { // Non-power of two and NaN
354         if (isnan(reference) && isnan(test))
355             return 0.0f; // if we are expecting a NaN, any NaN is fine
356 
357         // The unbiased exponent of the ulp unit place
358         int ulp_exp =
359             HALF_MANT_DIG - 1 - MAX(ilogb(reference), HALF_MIN_EXP - 1);
360 
361         // Scale the exponent of the error
362         return (float)scalbn(testVal - reference, ulp_exp);
363     }
364 
365     // reference is a normal power of two or a zero
366     int ulp_exp =
367         HALF_MANT_DIG - 1 - MAX(ilogb(reference) - 1, HALF_MIN_EXP - 1);
368 
369     // Scale the exponent of the error
370     return (float)scalbn(testVal - reference, ulp_exp);
371 }
372 
Ulp_Error_Half(cl_half test,float reference)373 float Ulp_Error_Half(cl_half test, float reference)
374 {
375     return Ulp_Error_Half_Float(cl_half_to_float(test), reference);
376 }
377 
378 
Ulp_Error(float test,double reference)379 float Ulp_Error(float test, double reference)
380 {
381     union {
382         double d;
383         uint64_t u;
384     } u;
385     u.d = reference;
386     double testVal = test;
387 
388     // Note: This function presumes that someone has already tested whether the
389     // result is correctly, rounded before calling this function.  That test:
390     //
391     //    if( (float) reference == test )
392     //        return 0.0f;
393     //
394     // would ensure that cases like fabs(reference) > FLT_MAX are weeded out
395     // before we get here. Otherwise, we'll return inf ulp error here, for what
396     // are otherwise correctly rounded results.
397 
398 
399     if (isinf(reference))
400     {
401         if (testVal == reference) return 0.0f;
402 
403         return (float)(testVal - reference);
404     }
405 
406     if (isinf(testVal))
407     { // infinite test value, but finite (but possibly overflowing in float)
408       // reference.
409       //
410       // The function probably overflowed prematurely here. Formally, the spec
411       // says this is an infinite ulp error and should not be tolerated.
412       // Unfortunately, this would mean that the internal precision of some
413       // half_pow implementations would have to be 29+ bits at half_powr(
414       // 0x1.fffffep+31, 4) to correctly determine that 4*log2( 0x1.fffffep+31 )
415       // is not exactly 128.0. You might represent this for example as 4*(32 -
416       // ~2**-24), which after rounding to single is 4*32 = 128, which will
417       // ultimately result in premature overflow, even though a good faith
418       // representation would be correct to within 2**-29 interally.
419 
420         // In the interest of not requiring the implementation go to
421         // extraordinary lengths to deliver a half precision function, we allow
422         // premature overflow within the limit of the allowed ulp error.
423         // Towards, that end, we "pretend" the test value is actually 2**128,
424         // the next value that would appear in the number line if float had
425         // sufficient range.
426         testVal = copysign(MAKE_HEX_DOUBLE(0x1.0p128, 0x1LL, 128), testVal);
427 
428         // Note that the same hack may not work in long double, which is not
429         // guaranteed to have more range than double.  It is not clear that
430         // premature overflow should be tolerated for double.
431     }
432 
433     if (u.u & 0x000fffffffffffffULL)
434     { // Non-power of two and NaN
435         if (isnan(reference) && isnan(test))
436             return 0.0f; // if we are expecting a NaN, any NaN is fine
437 
438         // The unbiased exponent of the ulp unit place
439         int ulp_exp = FLT_MANT_DIG - 1 - MAX(ilogb(reference), FLT_MIN_EXP - 1);
440 
441         // Scale the exponent of the error
442         return (float)scalbn(testVal - reference, ulp_exp);
443     }
444 
445     // reference is a normal power of two or a zero
446     // The unbiased exponent of the ulp unit place
447     int ulp_exp = FLT_MANT_DIG - 1 - MAX(ilogb(reference) - 1, FLT_MIN_EXP - 1);
448 
449     // Scale the exponent of the error
450     return (float)scalbn(testVal - reference, ulp_exp);
451 }
452 
Ulp_Error_Double(double test,long double reference)453 float Ulp_Error_Double(double test, long double reference)
454 {
455     // Deal with long double = double
456     // On most systems long double is a higher precision type than double. They
457     // provide either a 80-bit or greater floating point type, or they provide a
458     // head-tail double double format. That is sufficient to represent the
459     // accuracy of a floating point result to many more bits than double and we
460     // can calculate sub-ulp errors. This is the standard system for which this
461     // test suite is designed.
462     //
463     // On some systems double and long double are the same thing. Then we run
464     // into a problem, because our representation of the infinitely precise
465     // result (passed in as reference above) can be off by as much as a half
466     // double precision ulp itself.  In this case, we inflate the reported error
467     // by half an ulp to take this into account.  A more correct and permanent
468     // fix would be to undertake refactoring the reference code to return
469     // results in this format:
470     //
471     //    typedef struct DoubleReference
472     //    {
473     //        // true value = correctlyRoundedResult + ulps *
474     //        //    ulp(correctlyRoundedResult)  (infinitely precise)
475     //        // as best we can:
476     //        double correctlyRoundedResult;
477     //        // plus a fractional amount to account for the difference
478     //        // between infinitely precise result and correctlyRoundedResult,
479     //        // in units of ulps:
480     //        double ulps;
481     //    } DoubleReference;
482     //
483     // This would provide a useful higher-than-double precision format for
484     // everyone that we can use, and would solve a few problems with
485     // representing absolute errors below DBL_MIN and over DBL_MAX for systems
486     // that use a head to tail double double for long double.
487 
488     // Note: This function presumes that someone has already tested whether the
489     // result is correctly, rounded before calling this function.  That test:
490     //
491     //    if( (float) reference == test )
492     //        return 0.0f;
493     //
494     // would ensure that cases like fabs(reference) > FLT_MAX are weeded out
495     // before we get here. Otherwise, we'll return inf ulp error here, for what
496     // are otherwise correctly rounded results.
497 
498 
499     int x;
500     long double testVal = test;
501     if (0.5L != frexpl(reference, &x))
502     { // Non-power of two and NaN
503         if (isinf(reference))
504         {
505             if (testVal == reference) return 0.0f;
506 
507             return (float)(testVal - reference);
508         }
509 
510         if (isnan(reference) && isnan(test))
511             return 0.0f; // if we are expecting a NaN, any NaN is fine
512 
513         // The unbiased exponent of the ulp unit place
514         int ulp_exp =
515             DBL_MANT_DIG - 1 - MAX(ilogbl(reference), DBL_MIN_EXP - 1);
516 
517         // Scale the exponent of the error
518         float result = (float)scalbnl(testVal - reference, ulp_exp);
519 
520         // account for rounding error in reference result on systems that do not
521         // have a higher precision floating point type (see above)
522         if (sizeof(long double) == sizeof(double))
523             result += copysignf(0.5f, result);
524 
525         return result;
526     }
527 
528     // reference is a normal power of two or a zero
529     // The unbiased exponent of the ulp unit place
530     int ulp_exp =
531         DBL_MANT_DIG - 1 - MAX(ilogbl(reference) - 1, DBL_MIN_EXP - 1);
532 
533     // Scale the exponent of the error
534     float result = (float)scalbnl(testVal - reference, ulp_exp);
535 
536     // account for rounding error in reference result on systems that do not
537     // have a higher precision floating point type (see above)
538     if (sizeof(long double) == sizeof(double))
539         result += copysignf(0.5f, result);
540 
541     return result;
542 }
543 
OutputBuildLogs(cl_program program,cl_uint num_devices,cl_device_id * device_list)544 cl_int OutputBuildLogs(cl_program program, cl_uint num_devices,
545                        cl_device_id *device_list)
546 {
547     int error;
548     size_t size_ret;
549 
550     // Does the program object exist?
551     if (program != NULL)
552     {
553 
554         // Was the number of devices given
555         if (num_devices == 0)
556         {
557 
558             // If zero devices were specified then allocate and query the device
559             // list from the context
560             cl_context context;
561             error = clGetProgramInfo(program, CL_PROGRAM_CONTEXT,
562                                      sizeof(context), &context, NULL);
563             test_error(error, "Unable to query program's context");
564             error = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL,
565                                      &size_ret);
566             test_error(error, "Unable to query context's device size");
567             num_devices = size_ret / sizeof(cl_device_id);
568             device_list = (cl_device_id *)malloc(size_ret);
569             if (device_list == NULL)
570             {
571                 print_error(error, "malloc failed");
572                 return CL_OUT_OF_HOST_MEMORY;
573             }
574             error = clGetContextInfo(context, CL_CONTEXT_DEVICES, size_ret,
575                                      device_list, NULL);
576             test_error(error, "Unable to query context's devices");
577         }
578 
579         // For each device in the device_list
580         unsigned int i;
581         for (i = 0; i < num_devices; i++)
582         {
583 
584             // Get the build status
585             cl_build_status build_status;
586             error = clGetProgramBuildInfo(
587                 program, device_list[i], CL_PROGRAM_BUILD_STATUS,
588                 sizeof(build_status), &build_status, &size_ret);
589             test_error(error, "Unable to query build status");
590 
591             // If the build failed then log the status, and allocate the build
592             // log, log it and free it
593             if (build_status != CL_BUILD_SUCCESS)
594             {
595 
596                 log_error("ERROR: CL_PROGRAM_BUILD_STATUS=%d\n",
597                           (int)build_status);
598                 error = clGetProgramBuildInfo(program, device_list[i],
599                                               CL_PROGRAM_BUILD_LOG, 0, NULL,
600                                               &size_ret);
601                 test_error(error, "Unable to query build log size");
602                 char *build_log = (char *)malloc(size_ret);
603                 error = clGetProgramBuildInfo(program, device_list[i],
604                                               CL_PROGRAM_BUILD_LOG, size_ret,
605                                               build_log, &size_ret);
606                 test_error(error, "Unable to query build log");
607                 log_error("ERROR: CL_PROGRAM_BUILD_LOG:\n%s\n", build_log);
608                 free(build_log);
609             }
610         }
611 
612         // Was the number of devices given
613         if (num_devices == 0)
614         {
615 
616             // If zero devices were specified then free the device list
617             free(device_list);
618         }
619     }
620 
621     return CL_SUCCESS;
622 }
623 
624 const char *subtests_to_skip_with_offline_compiler[] = {
625     "get_kernel_arg_info",
626     "binary_create",
627     "load_program_source",
628     "load_multistring_source",
629     "load_two_kernel_source",
630     "load_null_terminated_source",
631     "load_null_terminated_multi_line_source",
632     "load_null_terminated_partial_multi_line_source",
633     "load_discreet_length_source",
634     "get_program_source",
635     "get_program_build_info",
636     "options_build_optimizations",
637     "options_build_macro",
638     "options_build_macro_existence",
639     "options_include_directory",
640     "options_denorm_cache",
641     "preprocessor_define_udef",
642     "preprocessor_include",
643     "preprocessor_line_error",
644     "preprocessor_pragma",
645     "compiler_defines_for_extensions",
646     "image_macro",
647     "simple_extern_compile_only",
648     "simple_embedded_header_compile",
649     "two_file_regular_variable_access",
650     "two_file_regular_struct_access",
651     "two_file_regular_function_access",
652     "simple_embedded_header_link",
653     "execute_after_simple_compile_and_link_with_defines",
654     "execute_after_simple_compile_and_link_with_callbacks",
655     "execute_after_embedded_header_link",
656     "execute_after_included_header_link",
657     "multi_file_libraries",
658     "multiple_files",
659     "multiple_libraries",
660     "multiple_files_multiple_libraries",
661     "multiple_embedded_headers",
662     "program_binary_type",
663     "compile_and_link_status_options_log",
664     "kernel_preprocessor_macros",
665     "execute_after_serialize_reload_library",
666     "execute_after_serialize_reload_object",
667     "execute_after_simple_compile_and_link",
668     "execute_after_simple_compile_and_link_no_device_info",
669     "execute_after_simple_library_with_link",
670     "execute_after_two_file_link",
671     "simple_compile_only",
672     "simple_compile_with_callback",
673     "simple_library_only",
674     "simple_library_with_callback",
675     "simple_library_with_link",
676     "simple_link_only",
677     "simple_link_with_callback",
678     "simple_static_compile_only",
679     "two_file_link",
680     "async_build",
681     "unload_repeated",
682     "unload_compile_unload_link",
683     "unload_build_unload_create_kernel",
684     "unload_link_different",
685     "unload_build_threaded",
686     "unload_build_info",
687     "unload_program_binaries",
688     "features_macro",
689     "progvar_prog_scope_misc",
690     "library_function"
691 };
692 
check_functions_for_offline_compiler(const char * subtestname,cl_device_id device)693 int check_functions_for_offline_compiler(const char *subtestname,
694                                          cl_device_id device)
695 {
696     if (gCompilationMode != kOnline)
697     {
698         int nNotRequiredWithOfflineCompiler =
699             sizeof(subtests_to_skip_with_offline_compiler) / sizeof(char *);
700         size_t i;
701         for (i = 0; i < nNotRequiredWithOfflineCompiler; ++i)
702         {
703             if (!strcmp(subtestname, subtests_to_skip_with_offline_compiler[i]))
704             {
705                 return 1;
706             }
707         }
708     }
709     return 0;
710 }
711