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