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