34int32_t
main(
int argc,
char** argv)
38 std::vector<char*> files;
40 printf(
"Passing command line options:\n");
41 bool add_option =
false;
42 for (int32_t
i = 1;
i < argc;
i++) {
44 compiler_options +=
" ";
45 compiler_options += argv[
i];
46 }
else if (strcmp(argv[
i],
"--") == 0) {
48 }
else if (strcmp(argv[
i],
"-output-file") == 0) {
50 quit(
"Output file name missing");
52 output_file = argv[
i];
54 fprintf(stderr,
"%s\n", argv[
i]);
55 files.push_back(argv[
i]);
60 cl_uint num_platforms;
61 if (clGetPlatformIDs(0,
nullptr, &num_platforms) != CL_SUCCESS) {
62 quit(
"Error getting OpenCL Platform Count");
64 if (num_platforms == 0) {
65 quit(
"No OpenCL Platform found");
67 printf(
"%d OpenCL Platforms found\n", num_platforms);
70 cl_platform_id* platforms =
new cl_platform_id[num_platforms];
71 if (platforms ==
nullptr) {
72 quit(
"Memory allocation error");
74 if (clGetPlatformIDs(num_platforms, platforms,
nullptr) != CL_SUCCESS) {
75 quit(
"Error getting OpenCL Platforms");
78 cl_platform_id platform;
82 for (uint32_t i_platform = 0; i_platform < num_platforms; i_platform++) {
83 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_PROFILE, 64, pinfo.
platform_profile,
nullptr);
84 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_VERSION, 64, pinfo.
platform_version,
nullptr);
85 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_NAME, 64, pinfo.
platform_name,
nullptr);
86 clGetPlatformInfo(platforms[i_platform], CL_PLATFORM_VENDOR, 64, pinfo.
platform_vendor,
nullptr);
90 printf(
"AMD OpenCL Platform found (%u)\n", i_platform);
91 platform = platforms[i_platform];
96 quit(
"Did not find AMD OpenCL Platform");
99 if (clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0,
nullptr, &pinfo.
count) != CL_SUCCESS) {
100 quit(
"Error getting OPENCL Device Count");
104 cl_device_id* devices =
new cl_device_id[pinfo.
count];
105 if (devices ==
nullptr) {
106 quit(
"Memory allocation error");
108 if (clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, pinfo.
count, devices,
nullptr) != CL_SUCCESS) {
109 quit(
"Error getting OpenCL devices");
113 cl_device_type device_type;
116 printf(
"Available OPENCL devices:\n");
117 for (uint32_t
i = 0;
i < pinfo.
count;
i++) {
118 printf(
"Examining device %u\n",
i);
120 clGetDeviceInfo(devices[
i], CL_DEVICE_NAME, 64, dinfo.
device_name,
nullptr);
121 clGetDeviceInfo(devices[
i], CL_DEVICE_VENDOR, 64, dinfo.
device_vendor,
nullptr);
122 clGetDeviceInfo(devices[
i], CL_DEVICE_TYPE,
sizeof(cl_device_type), &device_type,
nullptr);
123 clGetDeviceInfo(devices[
i], CL_DEVICE_MAX_CLOCK_FREQUENCY,
sizeof(freq), &freq,
nullptr);
124 clGetDeviceInfo(devices[
i], CL_DEVICE_MAX_COMPUTE_UNITS,
sizeof(
shaders), &
shaders,
nullptr);
125 clGetDeviceInfo(devices[
i], CL_DEVICE_ADDRESS_BITS,
sizeof(dinfo.
nbits), &dinfo.
nbits,
nullptr);
129 if (files.size() == 0) {
130 quit(
"Syntax: opencl [-output-file OUTPUT_FILE] FILE1 [FILE2] ... [FILEn] [-- COMPILER_OPTION_1] [COMPILER_OPTION_2] ... [COMPILER_OPTION_N]");
133 char**
buffers = (
char**)malloc(files.size() *
sizeof(
char*));
135 quit(
"Memory allocation error\n");
137 for (uint32_t
i = 0;
i < files.size();
i++) {
138 printf(
"Reading source file %s\n", files[
i]);
139 FILE* fp = fopen(files[
i],
"rb");
141 printf(
"Cannot open %s\n", files[
i]);
145 fseek(fp, 0, SEEK_END);
146 size_t file_size = ftell(fp);
147 fseek(fp, 0, SEEK_SET);
149 buffers[
i] = (
char*)malloc(file_size + 1);
151 quit(
"Memory allocation error");
153 if (fread(
buffers[
i], 1, file_size, fp) != file_size) {
154 quit(
"Error reading file");
160 printf(
"Creating OpenCL Context\n");
162 cl_context context = clCreateContext(
nullptr, pinfo.
count, devices,
nullptr,
nullptr, &ocl_error);
163 if (ocl_error != CL_SUCCESS) {
164 quit(
"Error creating OpenCL context");
167 printf(
"Creating OpenCL Program Object\n");
169 cl_program
program = clCreateProgramWithSource(context, (cl_uint)files.size(), (
const char**)
buffers,
nullptr, &ocl_error);
170 if (ocl_error != CL_SUCCESS) {
171 quit(
"Error creating program object");
174 printf(
"Compiling OpenCL Program\n");
176 ocl_error = clBuildProgram(
program, pinfo.
count, devices, compiler_options.c_str(),
nullptr,
nullptr);
177 if (ocl_error != CL_SUCCESS) {
178 fprintf(stderr,
"OpenCL Error while building program: %d (Compiler options: %s)\n", ocl_error, compiler_options.c_str());
179 fprintf(stderr,
"OpenCL Kernel:\n\n");
180 for (uint32_t
i = 0;
i < files.size();
i++) {
184 for (uint32_t
i = 0;
i < pinfo.
count;
i++) {
185 cl_build_status status;
186 clGetProgramBuildInfo(
program, devices[
i], CL_PROGRAM_BUILD_STATUS,
sizeof(status), &status,
nullptr);
187 if (status == CL_BUILD_ERROR) {
189 clGetProgramBuildInfo(
program, devices[
i], CL_PROGRAM_BUILD_LOG, 0,
nullptr, &log_size);
190 char* build_log = (
char*)malloc(log_size + 1);
191 if (build_log ==
nullptr) {
192 quit(
"Memory allocation error");
194 clGetProgramBuildInfo(
program, devices[
i], CL_PROGRAM_BUILD_LOG, log_size, build_log,
nullptr);
195 fprintf(stderr,
"Build Log (device %d):\n\n%s\n\n",
i, build_log);
200 for (uint32_t
i = 0;
i < files.size();
i++) {
204 if (ocl_error != CL_SUCCESS) {
208 printf(
"Obtaining program binaries\n");
209 size_t* binary_sizes = (
size_t*)malloc(pinfo.
count *
sizeof(
size_t));
210 if (binary_sizes ==
nullptr) {
211 quit(
"Memory allocation error");
213 clGetProgramInfo(
program, CL_PROGRAM_BINARY_SIZES, pinfo.
count *
sizeof(
size_t), binary_sizes,
nullptr);
214 char** binary_buffers = (
char**)malloc(pinfo.
count *
sizeof(
char*));
215 if (binary_buffers ==
nullptr) {
216 quit(
"Memory allocation error");
218 for (uint32_t
i = 0;
i < pinfo.
count;
i++) {
219 printf(
"Binary size for device %d: %d\n",
i, (int32_t)binary_sizes[
i]);
220 binary_buffers[
i] = (
char*)malloc(binary_sizes[
i]);
221 memset(binary_buffers[
i], 0, binary_sizes[
i]);
222 if (binary_buffers[
i] ==
nullptr) {
223 quit(
"Memory allocation error");
226 clGetProgramInfo(
program, CL_PROGRAM_BINARIES, pinfo.
count *
sizeof(
char*), binary_buffers,
nullptr);
228 printf(
"Programs obtained successfully, cleaning up opencl\n");
230 clReleaseContext(context);
232 printf(
"Writing binaries to file (%s)\n", output_file);
234 fp = fopen(output_file,
"w+b");
236 quit(
"Error opening output file\n");
238 const char* magic_bytes =
"QOCLPB";
239 fwrite(magic_bytes, 1, strlen(magic_bytes) + 1, fp);
240 fwrite(&pinfo, 1,
sizeof(pinfo), fp);
241 for (uint32_t
i = 0;
i < pinfo.
count;
i++) {
242 clGetDeviceInfo(devices[
i], CL_DEVICE_NAME, 64, dinfo.
device_name,
nullptr);
243 clGetDeviceInfo(devices[
i], CL_DEVICE_VENDOR, 64, dinfo.
device_vendor,
nullptr);
245 fwrite(&dinfo, 1,
sizeof(dinfo), fp);
246 fwrite(binary_buffers[
i], 1, binary_sizes[
i], fp);
250 printf(
"All done, cleaning up remaining buffers\n");
251 for (uint32_t
i = 0;
i < pinfo.
count;
i++) {
252 free(binary_buffers[
i]);
255 free(binary_buffers);