1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "ocl_utilities.h"
4 
5 /* Return the OpenCL error string for a given error number.
6  */
opencl_error_string(cl_int error)7 const char *opencl_error_string(cl_int error)
8 {
9 	int errorCount;
10 	int index;
11 
12 	static const char *errorString[] = {
13 		[CL_SUCCESS] = "CL_SUCCESS",
14 		[-CL_DEVICE_NOT_FOUND] = "CL_DEVICE_NOT_FOUND",
15 		[-CL_DEVICE_NOT_AVAILABLE] = "CL_DEVICE_NOT_AVAILABLE",
16 		[-CL_COMPILER_NOT_AVAILABLE] = "CL_COMPILER_NOT_AVAILABLE",
17 		[-CL_MEM_OBJECT_ALLOCATION_FAILURE] =
18 			"CL_MEM_OBJECT_ALLOCATION_FAILURE",
19 		[-CL_OUT_OF_RESOURCES] = "CL_OUT_OF_RESOURCES",
20 		[-CL_OUT_OF_HOST_MEMORY] = "CL_OUT_OF_HOST_MEMORY",
21 		[-CL_PROFILING_INFO_NOT_AVAILABLE] =
22 			"CL_PROFILING_INFO_NOT_AVAILABLE",
23 		[-CL_MEM_COPY_OVERLAP] = "CL_MEM_COPY_OVERLAP",
24 		[-CL_IMAGE_FORMAT_MISMATCH] = "CL_IMAGE_FORMAT_MISMATCH",
25 		[-CL_IMAGE_FORMAT_NOT_SUPPORTED] =
26 			"CL_IMAGE_FORMAT_NOT_SUPPORTED",
27 		[-CL_BUILD_PROGRAM_FAILURE] = "CL_BUILD_PROGRAM_FAILURE",
28 		[-CL_MAP_FAILURE] = "CL_MAP_FAILURE",
29 		[-CL_INVALID_VALUE] = "CL_INVALID_VALUE",
30 		[-CL_INVALID_DEVICE_TYPE] = "CL_INVALID_DEVICE_TYPE",
31 		[-CL_INVALID_PLATFORM] = "CL_INVALID_PLATFORM",
32 		[-CL_INVALID_DEVICE] = "CL_INVALID_DEVICE",
33 		[-CL_INVALID_CONTEXT] = "CL_INVALID_CONTEXT",
34 		[-CL_INVALID_QUEUE_PROPERTIES] = "CL_INVALID_QUEUE_PROPERTIES",
35 		[-CL_INVALID_COMMAND_QUEUE] = "CL_INVALID_COMMAND_QUEUE",
36 		[-CL_INVALID_HOST_PTR] = "CL_INVALID_HOST_PTR",
37 		[-CL_INVALID_MEM_OBJECT] = "CL_INVALID_MEM_OBJECT",
38 		[-CL_INVALID_IMAGE_FORMAT_DESCRIPTOR] =
39 			"CL_INVALID_IMAGE_FORMAT_DESCRIPTOR",
40 		[-CL_INVALID_IMAGE_SIZE] = "CL_INVALID_IMAGE_SIZE",
41 		[-CL_INVALID_SAMPLER] = "CL_INVALID_SAMPLER",
42 		[-CL_INVALID_BINARY] = "CL_INVALID_BINARY",
43 		[-CL_INVALID_BUILD_OPTIONS] = "CL_INVALID_BUILD_OPTIONS",
44 		[-CL_INVALID_PROGRAM] = "CL_INVALID_PROGRAM",
45 		[-CL_INVALID_PROGRAM_EXECUTABLE] =
46 			"CL_INVALID_PROGRAM_EXECUTABLE",
47 		[-CL_INVALID_KERNEL_NAME] = "CL_INVALID_KERNEL_NAME",
48 		[-CL_INVALID_KERNEL_DEFINITION] =
49 			"CL_INVALID_KERNEL_DEFINITION",
50 		[-CL_INVALID_KERNEL] = "CL_INVALID_KERNEL",
51 		[-CL_INVALID_ARG_INDEX] = "CL_INVALID_ARG_INDEX",
52 		[-CL_INVALID_ARG_VALUE] = "CL_INVALID_ARG_VALUE",
53 		[-CL_INVALID_ARG_SIZE] = "CL_INVALID_ARG_SIZE",
54 		[-CL_INVALID_KERNEL_ARGS] = "CL_INVALID_KERNEL_ARGS",
55 		[-CL_INVALID_WORK_DIMENSION] = "CL_INVALID_WORK_DIMENSION",
56 		[-CL_INVALID_WORK_GROUP_SIZE] = "CL_INVALID_WORK_GROUP_SIZE",
57 		[-CL_INVALID_WORK_ITEM_SIZE] = "CL_INVALID_WORK_ITEM_SIZE",
58 		[-CL_INVALID_GLOBAL_OFFSET] = "CL_INVALID_GLOBAL_OFFSET",
59 		[-CL_INVALID_EVENT_WAIT_LIST] = "CL_INVALID_EVENT_WAIT_LIST",
60 		[-CL_INVALID_EVENT] = "CL_INVALID_EVENT",
61 		[-CL_INVALID_OPERATION] = "CL_INVALID_OPERATION",
62 		[-CL_INVALID_GL_OBJECT] = "CL_INVALID_GL_OBJECT",
63 		[-CL_INVALID_BUFFER_SIZE] = "CL_INVALID_BUFFER_SIZE",
64 		[-CL_INVALID_MIP_LEVEL] = "CL_INVALID_MIP_LEVEL",
65 		[-CL_INVALID_GLOBAL_WORK_SIZE] = "CL_INVALID_GLOBAL_WORK_SIZE",
66 		[-CL_INVALID_PROPERTY] = "CL_INVALID_PROPERTY"
67 	};
68 
69 	errorCount = sizeof(errorString) / sizeof(errorString[0]);
70 	index = -error;
71 
72 	return (index >= 0 && index < errorCount) ?
73 		errorString[index] : "Unspecified Error";
74 }
75 
76 /* Find a GPU or a CPU associated with the first available platform.
77  * If use_gpu is set, then this function first tries to look for a GPU
78  * in the first available platform.
79  * If this fails or if use_gpu is not set, then it tries to use the CPU.
80  */
opencl_create_device(int use_gpu)81 cl_device_id opencl_create_device(int use_gpu)
82 {
83 	cl_platform_id platform;
84 	cl_device_id dev;
85 	int err;
86 
87 	err = clGetPlatformIDs(1, &platform, NULL);
88 	if (err < 0) {
89 		fprintf(stderr, "Error %s while looking for a platform.\n",
90 				opencl_error_string(err));
91 		exit(1);
92 	}
93 
94 	err = CL_DEVICE_NOT_FOUND;
95 	if (use_gpu)
96 		err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &dev,
97 				NULL);
98 	if (err == CL_DEVICE_NOT_FOUND)
99 		err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, &dev,
100 				NULL);
101 	if (err < 0) {
102 		fprintf(stderr, "Error %s while looking for a device.\n",
103 				opencl_error_string(err));
104 		exit(1);
105 	}
106 	return dev;
107 }
108 
109 /* Create an OpenCL program from a string and compile it.
110  */
opencl_build_program_from_string(cl_context ctx,cl_device_id dev,const char * program_source,size_t program_size,const char * opencl_options)111 cl_program opencl_build_program_from_string(cl_context ctx, cl_device_id dev,
112 	const char *program_source, size_t program_size,
113 	const char *opencl_options)
114 {
115 	int err;
116 	cl_program program;
117 	char *program_log;
118 	size_t log_size;
119 
120 	program = clCreateProgramWithSource(ctx, 1,
121 			&program_source, &program_size, &err);
122 	if (err < 0) {
123 		fprintf(stderr, "Could not create the program\n");
124 		exit(1);
125 	}
126 	err = clBuildProgram(program, 0, NULL, opencl_options, NULL, NULL);
127 	if (err < 0) {
128 		fprintf(stderr, "Could not build the program.\n");
129 		clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG, 0,
130 				NULL, &log_size);
131 		program_log = (char *) malloc(log_size + 1);
132 		program_log[log_size] = '\0';
133 		clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG,
134 				log_size + 1, program_log, NULL);
135 		fprintf(stderr, "%s\n", program_log);
136 		free(program_log);
137 		exit(1);
138 	}
139 	return program;
140 }
141 
142 /* Create an OpenCL program from a source file and compile it.
143  */
opencl_build_program_from_file(cl_context ctx,cl_device_id dev,const char * filename,const char * opencl_options)144 cl_program opencl_build_program_from_file(cl_context ctx, cl_device_id dev,
145 	const char* filename, const char* opencl_options)
146 {
147 	cl_program program;
148 	FILE *program_file;
149 	char *program_source;
150 	size_t program_size, read;
151 
152 	program_file = fopen(filename, "r");
153 	if (program_file == NULL) {
154 		fprintf(stderr, "Could not find the source file.\n");
155 		exit(1);
156 	}
157 	fseek(program_file, 0, SEEK_END);
158 	program_size = ftell(program_file);
159 	rewind(program_file);
160 	program_source = (char *) malloc(program_size + 1);
161 	program_source[program_size] = '\0';
162 	read = fread(program_source, sizeof(char), program_size, program_file);
163 	if (read != program_size) {
164 		fprintf(stderr, "Error while reading the kernel.\n");
165 		exit(1);
166 	}
167 	fclose(program_file);
168 
169 	program = opencl_build_program_from_string(ctx, dev, program_source,
170 						program_size, opencl_options);
171 	free(program_source);
172 
173 	return program;
174 }
175