1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <CL/cl.h>
5 #include "poclu.h"
6 
7 #define MAX_PLATFORMS 32
8 #define MAX_DEVICES   32
9 #define MAX_BINARIES  32
10 char kernel[] = "__kernel void k() {\n    return;\n}";
11 
12 int
main(void)13 main(void){
14   cl_int err;
15   cl_platform_id platforms[MAX_PLATFORMS];
16   cl_uint nplatforms;
17   cl_device_id devices[MAX_DEVICES + 1]; // + 1 for duplicate test
18   cl_device_id device_id0;
19   cl_uint num_devices;
20   size_t i;
21   size_t num_binaries;
22   const unsigned char **binaries = NULL;
23   size_t *binary_sizes = NULL;
24   size_t num_bytes_copied;
25   cl_int binary_statuses[MAX_BINARIES];
26   cl_int binary_statuses2[MAX_BINARIES];
27   cl_program program = NULL;
28   cl_program program_with_binary = NULL;
29 
30   err = clGetPlatformIDs(MAX_PLATFORMS, platforms, &nplatforms);
31   CHECK_OPENCL_ERROR_IN("clGetPlatformIDs");
32   if (!nplatforms)
33     return EXIT_FAILURE;
34 
35   err = clGetDeviceIDs(platforms[0], CL_DEVICE_TYPE_ALL, MAX_DEVICES,
36                       devices, &num_devices);
37   CHECK_OPENCL_ERROR_IN("clGetDeviceIDs");
38 
39   cl_context context = clCreateContext(NULL, num_devices, devices, NULL, NULL, &err);
40   CHECK_OPENCL_ERROR_IN("clCreateContext");
41 
42   size_t kernel_size = strlen(kernel);
43   char* kernel_buffer = kernel;
44 
45   program = clCreateProgramWithSource(context, 1, (const char**)&kernel_buffer,
46 				      &kernel_size, &err);
47   CHECK_OPENCL_ERROR_IN("clCreateProgramWithSource");
48 
49   err = clBuildProgram(program, num_devices, devices, NULL, NULL, NULL);
50   CHECK_OPENCL_ERROR_IN("clBuildProgram");
51 
52   err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, 0, 0, &num_binaries);
53   CHECK_OPENCL_ERROR_IN("clGetProgramInfo");
54 
55   num_binaries = num_binaries/sizeof(size_t);
56   binary_sizes = (size_t*)malloc(num_binaries * sizeof(size_t));
57   binaries = (const unsigned char**)calloc(num_binaries, sizeof(unsigned char*));
58 
59   err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES,
60 			 num_binaries*sizeof(size_t), binary_sizes ,
61 			 &num_bytes_copied);
62   CHECK_OPENCL_ERROR_IN("clGetProgramInfo");
63 
64   for (i = 0; i < num_binaries; ++i)
65     binaries[i] = (const unsigned char*) malloc(binary_sizes[i] *
66 						sizeof(const unsigned char));
67 
68   err = clGetProgramInfo(program, CL_PROGRAM_BINARIES,
69 			 num_binaries*sizeof(char*), binaries, &num_bytes_copied);
70   CHECK_OPENCL_ERROR_IN("clGetProgramInfo");
71 
72   cl_uint num = num_binaries < num_devices ? num_binaries : num_devices;
73   if (num == 0)
74     {
75       err = !CL_SUCCESS;
76       goto FREE_AND_EXIT;
77     }
78 
79   program_with_binary = clCreateProgramWithBinary(context, num, devices, binary_sizes,
80 						  binaries, binary_statuses, &err);
81   CHECK_OPENCL_ERROR_IN("clCreateProgramWithBinary");
82 
83   for (i = 0; i < num; ++i) {
84       cl_program_binary_type bin_type = 0;
85       err = clGetProgramBuildInfo(program_with_binary, devices[i],
86                                   CL_PROGRAM_BINARY_TYPE,
87                                   sizeof(bin_type), (void *)&bin_type,
88                                   NULL);
89       CHECK_OPENCL_ERROR_IN("get program binary type");
90 
91       /* cl_program_binary_type */
92       switch(bin_type) {
93         case CL_PROGRAM_BINARY_TYPE_NONE: /*0x0*/
94           fprintf(stderr, "program binary type: CL_PROGRAM_BINARY_TYPE_NONE\n");
95         break;
96         case CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT: /*0x1*/
97           fprintf(stderr, "program binary type: CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT\n");
98         break;
99         case CL_PROGRAM_BINARY_TYPE_LIBRARY: /*0x2*/
100           fprintf(stderr, "program binary type: CL_PROGRAM_BINARY_TYPE_LIBRARY\n");
101         break;
102         case CL_PROGRAM_BINARY_TYPE_EXECUTABLE: /*0x4*/
103           fprintf(stderr, "program binary type: CL_PROGRAM_BINARY_TYPE_EXECUTABLE\n");
104          break;
105       }
106   }
107   err = clReleaseProgram(program_with_binary);
108   CHECK_OPENCL_ERROR_IN("clReleaseProgram");
109 
110   for (i = 0; i < num; i++)
111     {
112       if (binary_statuses[i] != CL_SUCCESS)
113         {
114           err = !CL_SUCCESS;
115           goto FREE_AND_EXIT;
116         }
117     }
118 
119   // negative test1: invalid device
120   device_id0 = devices[0];
121   devices[0] = NULL; // invalid device
122   program_with_binary = clCreateProgramWithBinary(context, num, devices, binary_sizes,
123 						  binaries, binary_statuses, &err);
124 
125   if (err != CL_INVALID_DEVICE || program_with_binary != NULL)
126     {
127       err = !CL_SUCCESS;
128       goto FREE_AND_EXIT;
129     }
130   err = CL_SUCCESS;
131 
132   devices[0] = device_id0;
133   for (i = 0; i < num_binaries; ++i) free((void*)binaries[i]);
134   free(binary_sizes);
135   free(binaries);
136 
137   // negative test2: duplicate device
138   num_binaries = 2;
139   devices[1] = devices[0]; // duplicate
140 
141   binary_sizes = (size_t*)malloc(num_binaries * sizeof(size_t));
142   binaries = (const unsigned char**)calloc(num_binaries, sizeof(unsigned char*));
143 
144   err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, 1*sizeof(size_t),
145 			 binary_sizes , &num_bytes_copied);
146   CHECK_OPENCL_ERROR_IN("clGetProgramInfo");
147 
148   binary_sizes[1] = binary_sizes[0];
149 
150   binaries[0] = (const unsigned char*) malloc(binary_sizes[0] *
151 					      sizeof(const unsigned char));
152   binaries[1] = (const unsigned char*) malloc(binary_sizes[1] *
153 					      sizeof(const unsigned char));
154 
155   err = clGetProgramInfo(program, CL_PROGRAM_BINARIES, 1 * sizeof(char*),
156 			 binaries, &num_bytes_copied);
157   CHECK_OPENCL_ERROR_IN("clGetProgramInfo");
158 
159   memcpy((void*)binaries[1], (void*)binaries[0], binary_sizes[0]);
160   program_with_binary = clCreateProgramWithBinary(context, 2, devices, binary_sizes,
161 						  binaries, binary_statuses2, &err);
162   if (err != CL_INVALID_DEVICE || program_with_binary != NULL)
163     {
164       err = !CL_SUCCESS;
165       goto FREE_AND_EXIT;
166     }
167   err = CL_SUCCESS;
168 
169  FREE_AND_EXIT:
170   // Free resources
171   for (i = 0; i < num_binaries; ++i)
172     if (binaries)
173       if(binaries[i])
174 	free((void*)binaries[i]);
175 
176   if (binary_sizes)
177     free(binary_sizes);
178   if (binaries)
179     free(binaries);
180   if (program)
181     CHECK_CL_ERROR (clReleaseProgram (program));
182   if (program_with_binary)
183     CHECK_CL_ERROR (clReleaseProgram (program_with_binary));
184   if (context)
185     CHECK_CL_ERROR (clReleaseContext (context));
186 
187   CHECK_CL_ERROR (clUnloadCompiler ());
188 
189   return err == CL_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
190 }
191