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