xref: /aosp_15_r20/external/OpenCL-CTS/test_conformance/basic/test_sizeof.cpp (revision 6467f958c7de8070b317fc65bcb0f6472e388d82)
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