• 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 "harness/compat.h"
17 
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include "procs.h"
24 
25 
26 
get_type_size(cl_context context,cl_command_queue queue,const char * type,cl_ulong * size,cl_device_id device)27 cl_int get_type_size( cl_context context, cl_command_queue queue, const char *type, cl_ulong *size, cl_device_id device  )
28 {
29     const char *sizeof_kernel_code[4] =
30     {
31         "", /* optional pragma string */
32         "__kernel __attribute__((reqd_work_group_size(1,1,1))) void test_sizeof(__global uint *dst) \n"
33         "{\n"
34         "   dst[0] = (uint) sizeof( ", type, " );\n"
35         "}\n"
36     };
37 
38     cl_program  p;
39     cl_kernel   k;
40     cl_mem      m;
41     cl_uint        temp;
42 
43 
44     if (!strncmp(type, "double", 6))
45     {
46         sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";
47     }
48     else if (!strncmp(type, "half", 4))
49     {
50         sizeof_kernel_code[0] = "#pragma OPENCL EXTENSION cl_khr_fp16 : enable\n";
51     }
52     bool deviceLt20 = false;
53     Version version = get_device_cl_version(device);
54     if (version < Version(2,0)) {
55         deviceLt20 = true;
56     }
57 
58     cl_int err = create_single_kernel_helper_with_build_options(context, &p, &k, 4, sizeof_kernel_code, "test_sizeof", deviceLt20 ? "" : "-cl-std=CL2.0");
59     if( err )
60         return err;
61 
62     m = clCreateBuffer( context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof( cl_ulong ), size, &err );
63     if( NULL == m )
64     {
65         clReleaseProgram( p );
66         clReleaseKernel( k );
67         log_error("\nclCreateBuffer FAILED\n");
68         return err;
69     }
70 
71     err = clSetKernelArg( k, 0, sizeof( cl_mem ), &m );
72     if( err )
73     {
74         clReleaseProgram( p );
75         clReleaseKernel( k );
76         clReleaseMemObject( m );
77         log_error("\nclSetKernelArg FAILED\n");
78         return err;
79     }
80 
81     err = clEnqueueTask( queue, k, 0, NULL, NULL );
82     clReleaseProgram( p );
83     clReleaseKernel( k );
84     if( err )
85     {
86         clReleaseMemObject( m );
87         log_error( "\nclEnqueueTask FAILED\n" );
88         return err;
89     }
90 
91     err = clEnqueueReadBuffer( queue, m, CL_TRUE, 0, sizeof( cl_uint ), &temp, 0, NULL, NULL );
92     clReleaseMemObject( m );
93     if( err )
94         log_error( "\nclEnqueueReadBuffer FAILED\n" );
95 
96     *size = (cl_ulong) temp;
97 
98     return err;
99 }
100 
101 typedef struct size_table
102 {
103     const char *name;
104     cl_ulong   size;
105     cl_ulong   cl_size;
106 }size_table;
107 
108 const size_table  scalar_table[] =
109 {
110     // Fixed size entries from table 6.1
111     {  "char",              1,  sizeof( cl_char )   },
112     {  "uchar",             1,  sizeof( cl_uchar)   },
113     {  "unsigned char",     1,  sizeof( cl_uchar)   },
114     {  "short",             2,  sizeof( cl_short)   },
115     {  "ushort",            2,  sizeof( cl_ushort)  },
116     {  "unsigned short",    2,  sizeof( cl_ushort)  },
117     {  "int",               4,  sizeof( cl_int )    },
118     {  "uint",              4,  sizeof( cl_uint)    },
119     {  "unsigned int",      4,  sizeof( cl_uint)    },
120     {  "float",             4,  sizeof( cl_float)   },
121     {  "long",              8,  sizeof( cl_long )   },
122     {  "ulong",             8,  sizeof( cl_ulong)   },
123     {  "unsigned long",     8,  sizeof( cl_ulong)   }
124 };
125 
126 const size_table  vector_table[] =
127 {
128     // Fixed size entries from table 6.1
129     {  "char",      1,  sizeof( cl_char )   },
130     {  "uchar",     1,  sizeof( cl_uchar)   },
131     {  "short",     2,  sizeof( cl_short)   },
132     {  "ushort",    2,  sizeof( cl_ushort)  },
133     {  "int",       4,  sizeof( cl_int )    },
134     {  "uint",      4,  sizeof( cl_uint)    },
135     {  "float",     4,  sizeof( cl_float)   },
136     {  "long",      8,  sizeof( cl_long )   },
137     {  "ulong",     8,  sizeof( cl_ulong)   }
138 };
139 
140 const char  *ptr_table[] =
141 {
142     "global void*",
143     "size_t",
144     "sizeof(int)",      // check return type of sizeof
145     "ptrdiff_t"
146 };
147 
148 const char *other_types[] =
149 {
150     "event_t",
151     "image2d_t",
152     "image3d_t",
153     "sampler_t"
154 };
155 
IsPowerOfTwo(cl_ulong x)156 static int IsPowerOfTwo( cl_ulong x ){ return 0 == (x & (x-1)); }
157 
test_sizeof(cl_device_id device,cl_context context,cl_command_queue queue,int num_elements)158 int test_sizeof(cl_device_id device, cl_context context, cl_command_queue queue, int num_elements)
159 {
160     size_t i, j;
161     cl_ulong test;
162     cl_uint ptr_size = CL_UINT_MAX;
163     cl_int err = CL_SUCCESS;
164 
165     // Check address space size
166     err = clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(ptr_size), &ptr_size, NULL);
167     if( err || ptr_size > 64)
168     {
169         log_error( "FAILED:  Unable to get CL_DEVICE_ADDRESS_BITS for device %p\n", device );
170         return -1;
171     }
172     log_info( "\tCL_DEVICE_ADDRESS_BITS = %u\n", ptr_size );
173     ptr_size /= 8;
174 
175     // Test standard scalar sizes
176     for( i = 0; i < sizeof( scalar_table ) / sizeof( scalar_table[0] ); i++ )
177     {
178         if( ! gHasLong &&
179            (0 == strcmp(scalar_table[i].name, "long") ||
180             0 == strcmp(scalar_table[i].name, "ulong") ||
181             0 == strcmp(scalar_table[i].name, "unsigned long")))
182         {
183             log_info("\nLongs are not supported by this device. Skipping test.\t");
184             continue;
185         }
186 
187         test = CL_ULONG_MAX;
188         err = get_type_size( context, queue, scalar_table[i].name, &test, device);
189         if( err )
190             return err;
191         if( test != scalar_table[i].size )
192         {
193             log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", scalar_table[i].name, test, scalar_table[i].size );
194             return -1;
195         }
196         if( test != scalar_table[i].cl_size )
197         {
198             log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", scalar_table[i].name, test, scalar_table[i].cl_size );
199             return -2;
200         }
201         log_info( "%16s", scalar_table[i].name );
202     }
203     log_info( "\n" );
204 
205     // Test standard vector sizes
206     for( j = 2; j <= 16; j *= 2 )
207     {
208         // For each vector size, iterate through types
209         for( i = 0; i < sizeof( vector_table ) / sizeof( vector_table[0] ); i++ )
210         {
211             if( !gHasLong &&
212                (0 == strcmp(vector_table[i].name, "long") ||
213                 0 == strcmp(vector_table[i].name, "ulong")))
214             {
215                 log_info("\nLongs are not supported by this device. Skipping test.\t");
216                 continue;
217             }
218 
219             char name[32];
220             sprintf( name, "%s%ld", vector_table[i].name, j );
221 
222             test = CL_ULONG_MAX;
223             err = get_type_size( context, queue, name, &test, device  );
224             if( err )
225                 return err;
226             if( test != j * vector_table[i].size )
227             {
228                 log_error( "\nFAILED: Type %s has size %lld, but expected size %lld!\n", name, test, j * vector_table[i].size );
229                 return -1;
230             }
231             if( test != j * vector_table[i].cl_size )
232             {
233                 log_error( "\nFAILED: Type %s has size %lld, but cl_ size is %lld!\n", name, test, j * vector_table[i].cl_size );
234                 return -2;
235             }
236             log_info( "%16s", name );
237         }
238         log_info( "\n" );
239     }
240 
241     //Check that pointer sizes are correct
242     for( i = 0; i < sizeof( ptr_table ) / sizeof( ptr_table[0] ); i++ )
243     {
244         test = CL_ULONG_MAX;
245         err = get_type_size( context, queue, ptr_table[i], &test, device );
246         if( err )
247             return err;
248         if( test != ptr_size )
249         {
250             log_error( "\nFAILED: Type %s has size %lld, but expected size %u!\n", ptr_table[i], test, ptr_size );
251             return -1;
252         }
253         log_info( "%16s", ptr_table[i] );
254     }
255 
256     // Check that intptr_t is large enough
257     test = CL_ULONG_MAX;
258     err = get_type_size( context, queue, "intptr_t", &test, device );
259     if( err )
260         return err;
261     if( test < ptr_size )
262     {
263         log_error( "\nFAILED: intptr_t has size %lld, but must be at least %u!\n", test, ptr_size );
264         return -1;
265     }
266     if( ! IsPowerOfTwo( test ) )
267     {
268         log_error( "\nFAILED: sizeof(intptr_t) is %lld, but must be a power of two!\n", test );
269         return -2;
270     }
271     log_info( "%16s", "intptr_t" );
272 
273     // Check that uintptr_t is large enough
274     test = CL_ULONG_MAX;
275     err = get_type_size( context, queue, "uintptr_t", &test, device );
276     if( err )
277         return err;
278     if( test < ptr_size )
279     {
280         log_error( "\nFAILED: uintptr_t has size %lld, but must be at least %u!\n", test, ptr_size );
281         return -1;
282     }
283     if( ! IsPowerOfTwo( test ) )
284     {
285         log_error( "\nFAILED: sizeof(uintptr_t) is %lld, but must be a power of two!\n", test );
286         return -2;
287     }
288     log_info( "%16s\n", "uintptr_t" );
289 
290     //Check that other types are powers of two
291     for( i = 0; i < sizeof( other_types ) / sizeof( other_types[0] ); i++ )
292     {
293         if( 0 == strcmp(other_types[i], "image2d_t") &&
294            checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
295         {
296             log_info("\nimages are not supported by this device. Skipping test.\t");
297             continue;
298         }
299 
300         if( gIsEmbedded &&
301            0 == strcmp(other_types[i], "image3d_t") &&
302            checkFor3DImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
303         {
304             log_info("\n3D images are not supported by this device. Skipping test.\t");
305             continue;
306         }
307 
308         if( 0 == strcmp(other_types[i], "sampler_t") &&
309            checkForImageSupport( device ) == CL_IMAGE_FORMAT_NOT_SUPPORTED)
310         {
311           log_info("\nimages are not supported by this device. Skipping test.\t");
312           continue;
313         }
314 
315         test = CL_ULONG_MAX;
316         err = get_type_size( context, queue, other_types[i], &test, device );
317         if( err )
318             return err;
319         if( ! IsPowerOfTwo( test ) )
320         {
321             log_error( "\nFAILED: Type %s has size %lld, which is not a power of two (section 6.1.5)!\n", other_types[i], test );
322             return -1;
323         }
324         log_info( "%16s", other_types[i] );
325     }
326     log_info( "\n" );
327 
328 
329     //Check double
330     if( is_extension_available( device, "cl_khr_fp64" ) )
331     {
332         log_info( "\tcl_khr_fp64:" );
333         test = CL_ULONG_MAX;
334         err = get_type_size( context, queue, "double", &test, device );
335         if( err )
336             return err;
337         if( test != 8 )
338         {
339             log_error( "\nFAILED: double has size %lld, but must be 8!\n", test );
340             return -1;
341         }
342         log_info( "%16s", "double" );
343 
344         // Test standard vector sizes
345         for( j = 2; j <= 16; j *= 2 )
346         {
347             char name[32];
348             sprintf( name, "double%ld", j );
349 
350             test = CL_ULONG_MAX;
351             err = get_type_size( context, queue, name, &test, device );
352             if( err )
353                 return err;
354             if( test != 8*j )
355             {
356                 log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 8 * j);
357                 return -1;
358             }
359             log_info( "%16s", name );
360         }
361         log_info( "\n" );
362     }
363 
364     //Check half
365     if( is_extension_available( device, "cl_khr_fp16" ) )
366     {
367         log_info( "\tcl_khr_fp16:" );
368         test = CL_ULONG_MAX;
369         err = get_type_size( context, queue, "half", &test, device );
370         if( err )
371             return err;
372         if( test != 2 )
373         {
374             log_error( "\nFAILED: half has size %lld, but must be 2!\n", test );
375             return -1;
376         }
377         log_info( "%16s", "half" );
378 
379         // Test standard vector sizes
380         for( j = 2; j <= 16; j *= 2 )
381         {
382             char name[32];
383             sprintf( name, "half%ld", j );
384 
385             test = CL_ULONG_MAX;
386             err = get_type_size( context, queue, name, &test, device );
387             if( err )
388                 return err;
389             if( test != 2*j )
390             {
391                 log_error( "\nFAILED: %s has size %lld, but must be %ld!\n", name, test, 2 * j);
392                 return -1;
393             }
394             log_info( "%16s", name );
395         }
396         log_info( "\n" );
397     }
398 
399     return err;
400 }
401 
402 
403