Mali OpenCL SDK v1.1.0
 All Classes Files Functions Variables Macros Pages
common.cpp
Go to the documentation of this file.
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2013 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10 
11 #include "common.h"
12 #include <iostream>
13 #include <sstream>
14 #include <fstream>
15 
16 using namespace std;
17 
18 bool printProfilingInfo(cl_event event)
19 {
20  cl_ulong queuedTime = 0;
21  if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_QUEUED, sizeof(cl_ulong), &queuedTime, NULL)))
22  {
23  cerr << "Retrieving CL_PROFILING_COMMAND_QUEUED OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
24  return false;
25  }
26 
27  cl_ulong submittedTime = 0;
28  if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_SUBMIT, sizeof(cl_ulong), &submittedTime, NULL)))
29  {
30  cerr << "Retrieving CL_PROFILING_COMMAND_SUBMIT OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
31  return false;
32  }
33 
34  cl_ulong startTime = 0;
35  if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &startTime, NULL)))
36  {
37  cerr << "Retrieving CL_PROFILING_COMMAND_START OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
38  return false;
39  }
40 
41  cl_ulong endTime = 0;
42  if (!checkSuccess(clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &endTime, NULL)))
43  {
44  cerr << "Retrieving CL_PROFILING_COMMAND_END OpenCL profiling information failed. " << __FILE__ << ":"<< __LINE__ << endl;
45  return false;
46  }
47 
48  cout << "Profiling information:\n";
49  /* OpenCL returns times in nano seconds. Print out the times in milliseconds (divide by a million). */
50  cout << "Queued time: \t" << (submittedTime - queuedTime) / 1000000.0 << "ms\n";
51  cout << "Wait time: \t" << (startTime - submittedTime) / 1000000.0 << "ms\n";
52  cout << "Run time: \t" << (endTime - startTime) / 1000000.0 << "ms" << endl;
53 
54  return true;
55 }
56 
57 bool printSupported2DImageFormats(cl_context context)
58 {
59  /* Get the number of supported image formats in order to allocate the correct amount of memory. */
60  cl_uint numberOfImageFormats;
61  if (!checkSuccess(clGetSupportedImageFormats(context, 0, CL_MEM_OBJECT_IMAGE2D, 0, NULL, &numberOfImageFormats)))
62  {
63  cerr << "Getting the number of supported 2D image formats failed. " << __FILE__ << ":"<< __LINE__ << endl;
64  return false;
65  }
66 
67  /* Get the list of supported image formats. */
68  cl_image_format* imageFormats = new cl_image_format[numberOfImageFormats];
69  if (!checkSuccess(clGetSupportedImageFormats(context, 0, CL_MEM_OBJECT_IMAGE3D, numberOfImageFormats, imageFormats, NULL)))
70  {
71  cerr << "Getting the list of supported 2D image formats failed. " << __FILE__ << ":"<< __LINE__ << endl;
72  return false;
73  }
74 
75  cout << numberOfImageFormats << " Image formats supported";
76 
77  if (numberOfImageFormats > 0)
78  {
79  cout << " (channel order, channel data type):" << endl;
80  }
81  else
82  {
83  cout << "." << endl;
84  }
85 
86  for (unsigned int i = 0; i < numberOfImageFormats; i++)
87  {
88  cout << imageChannelOrderToString(imageFormats[i].image_channel_order) << ", " << imageChannelDataTypeToString(imageFormats[i].image_channel_data_type) << endl;
89  }
90 
91  delete[] imageFormats;
92 
93  return true;
94 }
95 
96 string imageChannelOrderToString(cl_channel_order channelOrder)
97 {
98  switch (channelOrder)
99  {
100  case CL_R:
101  return "CL_R";
102  case CL_A:
103  return "CL_A";
104  case CL_RG:
105  return "CL_RG";
106  case CL_RA:
107  return "CL_RA";
108  case CL_RGB:
109  return "CL_RGB";
110  case CL_RGBA:
111  return "CL_RGBA";
112  case CL_BGRA:
113  return "CL_BGRA";
114  case CL_ARGB:
115  return "CL_ARGB";
116  case CL_INTENSITY:
117  return "CL_INTENSITY";
118  case CL_LUMINANCE:
119  return "CL_LUMINANCE";
120  case CL_Rx:
121  return "CL_Rx";
122  case CL_RGx:
123  return "CL_RGx";
124  case CL_RGBx:
125  return "CL_RGBx";
126  default:
127  return "Unknown image channel order";
128  }
129 }
130 
131 string imageChannelDataTypeToString(cl_channel_type channelDataType)
132 {
133  switch (channelDataType)
134  {
135  case CL_SNORM_INT8:
136  return "CL_SNORM_INT8";
137  case CL_SNORM_INT16:
138  return "CL_SNORM_INT16";
139  case CL_UNORM_INT8:
140  return "CL_UNORM_INT8";
141  case CL_UNORM_INT16:
142  return "CL_UNORM_INT16";
143  case CL_UNORM_SHORT_565:
144  return "CL_UNORM_SHORT_565";
145  case CL_UNORM_SHORT_555:
146  return "CL_UNORM_SHORT_555";
147  case CL_UNORM_INT_101010:
148  return "CL_UNORM_INT_101010";
149  case CL_SIGNED_INT8:
150  return "CL_SIGNED_INT8";
151  case CL_SIGNED_INT16:
152  return "CL_SIGNED_INT16";
153  case CL_SIGNED_INT32:
154  return "CL_SIGNED_INT32";
155  case CL_UNSIGNED_INT8:
156  return "CL_UNSIGNED_INT8";
157  case CL_UNSIGNED_INT16:
158  return "CL_UNSIGNED_INT16";
159  case CL_UNSIGNED_INT32:
160  return "CL_UNSIGNED_INT32";
161  case CL_HALF_FLOAT:
162  return "CL_HALF_FLOAT";
163  case CL_FLOAT:
164  return "CL_FLOAT";
165  default:
166  return "Unknown image channel data type";
167  }
168 }
169 
170 bool cleanUpOpenCL(cl_context context, cl_command_queue commandQueue, cl_program program, cl_kernel kernel, cl_mem* memoryObjects, int numberOfMemoryObjects)
171 {
172  bool returnValue = true;
173  if (context != 0)
174  {
175  if (!checkSuccess(clReleaseContext(context)))
176  {
177  cerr << "Releasing the OpenCL context failed. " << __FILE__ << ":"<< __LINE__ << endl;
178  returnValue = false;
179  }
180  }
181 
182  if (commandQueue != 0)
183  {
184  if (!checkSuccess(clReleaseCommandQueue(commandQueue)))
185  {
186  cerr << "Releasing the OpenCL command queue failed. " << __FILE__ << ":"<< __LINE__ << endl;
187  returnValue = false;
188  }
189  }
190 
191  if (kernel != 0)
192  {
193  if (!checkSuccess(clReleaseKernel(kernel)))
194  {
195  cerr << "Releasing the OpenCL kernel failed. " << __FILE__ << ":"<< __LINE__ << endl;
196  returnValue = false;
197  }
198  }
199 
200  if (program != 0)
201  {
202  if (!checkSuccess(clReleaseProgram(program)))
203  {
204  cerr << "Releasing the OpenCL program failed. " << __FILE__ << ":"<< __LINE__ << endl;
205  returnValue = false;
206  }
207  }
208 
209  for (int index = 0; index < numberOfMemoryObjects; index++)
210  {
211  if (memoryObjects[index] != 0)
212  {
213  if (!checkSuccess(clReleaseMemObject(memoryObjects[index])))
214  {
215  cerr << "Releasing the OpenCL memory object " << index << " failed. " << __FILE__ << ":"<< __LINE__ << endl;
216  returnValue = false;
217  }
218  }
219  }
220 
221  return returnValue;
222 }
223 
224 bool createContext(cl_context* context)
225 {
226  cl_int errorNumber = 0;
227  cl_uint numberOfPlatforms = 0;
228  cl_platform_id firstPlatformID = 0;
229 
230  /* Retrieve a single platform ID. */
231  if (!checkSuccess(clGetPlatformIDs(1, &firstPlatformID, &numberOfPlatforms)))
232  {
233  cerr << "Retrieving OpenCL platforms failed. " << __FILE__ << ":"<< __LINE__ << endl;
234  return false;
235  }
236 
237  if (numberOfPlatforms <= 0)
238  {
239  cerr << "No OpenCL platforms found. " << __FILE__ << ":"<< __LINE__ << endl;
240  return false;
241  }
242 
243  /* Get a context with a GPU device from the platform found above. */
244  cl_context_properties contextProperties [] = {CL_CONTEXT_PLATFORM, (cl_context_properties)firstPlatformID, 0};
245  *context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU, NULL, NULL, &errorNumber);
246  if (!checkSuccess(errorNumber))
247  {
248  cerr << "Creating an OpenCL context failed. " << __FILE__ << ":"<< __LINE__ << endl;
249  return false;
250  }
251 
252  return true;
253 }
254 
255 bool createCommandQueue(cl_context context, cl_command_queue* commandQueue, cl_device_id* device)
256 {
257  cl_int errorNumber = 0;
258  cl_device_id* devices = NULL;
259  size_t deviceBufferSize = -1;
260 
261  /* Retrieve the size of the buffer needed to contain information about the devices in this OpenCL context. */
262  if (!checkSuccess(clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize)))
263  {
264  cerr << "Failed to get OpenCL context information. " << __FILE__ << ":"<< __LINE__ << endl;
265  return false;
266  }
267 
268  if(deviceBufferSize == 0)
269  {
270  cerr << "No OpenCL devices found. " << __FILE__ << ":"<< __LINE__ << endl;
271  return false;
272  }
273 
274  /* Retrieve the list of devices available in this context. */
275  devices = new cl_device_id[deviceBufferSize / sizeof(cl_device_id)];
276  if (!checkSuccess(clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices, NULL)))
277  {
278  cerr << "Failed to get the OpenCL context information. " << __FILE__ << ":"<< __LINE__ << endl;
279  delete [] devices;
280  return false;
281  }
282 
283  /* Use the first available device in this context. */
284  *device = devices[0];
285  delete [] devices;
286 
287  /* Set up the command queue with the selected device. */
288  *commandQueue = clCreateCommandQueue(context, *device, CL_QUEUE_PROFILING_ENABLE, &errorNumber);
289  if (!checkSuccess(errorNumber))
290  {
291  cerr << "Failed to create the OpenCL command queue. " << __FILE__ << ":"<< __LINE__ << endl;
292  return false;
293  }
294 
295  return true;
296 }
297 
298 bool createProgram(cl_context context, cl_device_id device, string filename, cl_program* program)
299 {
300  cl_int errorNumber = 0;
301  ifstream kernelFile(filename.c_str(), ios::in);
302 
303  if(!kernelFile.is_open())
304  {
305  cerr << "Unable to open " << filename << ". " << __FILE__ << ":"<< __LINE__ << endl;
306  return false;
307  }
308 
309  /*
310  * Read the kernel file into an output stream.
311  * Convert this into a char array for passing to OpenCL.
312  */
313  ostringstream outputStringStream;
314  outputStringStream << kernelFile.rdbuf();
315  string srcStdStr = outputStringStream.str();
316  const char* charSource = srcStdStr.c_str();
317 
318  *program = clCreateProgramWithSource(context, 1, &charSource, NULL, &errorNumber);
319  if (!checkSuccess(errorNumber) || program == NULL)
320  {
321  cerr << "Failed to create OpenCL program. " << __FILE__ << ":"<< __LINE__ << endl;
322  return false;
323  }
324 
325  /* Try to build the OpenCL program. */
326  bool buildSuccess = checkSuccess(clBuildProgram(*program, 0, NULL, NULL, NULL, NULL));
327 
328  /* Get the size of the build log. */
329  size_t logSize = 0;
330  clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &logSize);
331 
332  /*
333  * If the build succeeds with no log, an empty string is returned (logSize = 1),
334  * we only want to print the message if it has some content (logSize > 1).
335  */
336  if (logSize > 1)
337  {
338  char* log = new char[logSize];
339  clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, logSize, log, NULL);
340 
341  string* stringChars = new string(log, logSize);
342  cerr << "Build log:\n " << *stringChars << endl;
343 
344  delete[] log;
345  delete stringChars;
346  }
347 
348  if (!buildSuccess)
349  {
350  clReleaseProgram(*program);
351  cerr << "Failed to build OpenCL program. " << __FILE__ << ":"<< __LINE__ << endl;
352  return false;
353  }
354 
355  return true;
356 }
357 
358 inline bool checkSuccess(cl_int errorNumber)
359 {
360  if (errorNumber != CL_SUCCESS)
361  {
362  cerr << "OpenCL error: " << errorNumberToString(errorNumber) << endl;
363  return false;
364  }
365  return true;
366 }
367 
368 string errorNumberToString(cl_int errorNumber)
369 {
370  switch (errorNumber)
371  {
372  case CL_SUCCESS:
373  return "CL_SUCCESS";
374  case CL_DEVICE_NOT_FOUND:
375  return "CL_DEVICE_NOT_FOUND";
376  case CL_DEVICE_NOT_AVAILABLE:
377  return "CL_DEVICE_NOT_AVAILABLE";
378  case CL_COMPILER_NOT_AVAILABLE:
379  return "CL_COMPILER_NOT_AVAILABLE";
380  case CL_MEM_OBJECT_ALLOCATION_FAILURE:
381  return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
382  case CL_OUT_OF_RESOURCES:
383  return "CL_OUT_OF_RESOURCES";
384  case CL_OUT_OF_HOST_MEMORY:
385  return "CL_OUT_OF_HOST_MEMORY";
386  case CL_PROFILING_INFO_NOT_AVAILABLE:
387  return "CL_PROFILING_INFO_NOT_AVAILABLE";
388  case CL_MEM_COPY_OVERLAP:
389  return "CL_MEM_COPY_OVERLAP";
390  case CL_IMAGE_FORMAT_MISMATCH:
391  return "CL_IMAGE_FORMAT_MISMATCH";
392  case CL_IMAGE_FORMAT_NOT_SUPPORTED:
393  return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
394  case CL_BUILD_PROGRAM_FAILURE:
395  return "CL_BUILD_PROGRAM_FAILURE";
396  case CL_MAP_FAILURE:
397  return "CL_MAP_FAILURE";
398  case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
399  return "CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
400  case CL_INVALID_VALUE:
401  return "CL_INVALID_VALUE";
402  case CL_INVALID_DEVICE_TYPE:
403  return "CL_INVALID_DEVICE_TYPE";
404  case CL_INVALID_PLATFORM:
405  return "CL_INVALID_PLATFORM";
406  case CL_INVALID_DEVICE:
407  return "CL_INVALID_DEVICE";
408  case CL_INVALID_CONTEXT:
409  return "CL_INVALID_CONTEXT";
410  case CL_INVALID_QUEUE_PROPERTIES:
411  return "CL_INVALID_QUEUE_PROPERTIES";
412  case CL_INVALID_COMMAND_QUEUE:
413  return "CL_INVALID_COMMAND_QUEUE";
414  case CL_INVALID_HOST_PTR:
415  return "CL_INVALID_HOST_PTR";
416  case CL_INVALID_MEM_OBJECT:
417  return "CL_INVALID_MEM_OBJECT";
418  case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
419  return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
420  case CL_INVALID_IMAGE_SIZE:
421  return "CL_INVALID_IMAGE_SIZE";
422  case CL_INVALID_SAMPLER:
423  return "CL_INVALID_SAMPLER";
424  case CL_INVALID_BINARY:
425  return "CL_INVALID_BINARY";
426  case CL_INVALID_BUILD_OPTIONS:
427  return "CL_INVALID_BUILD_OPTIONS";
428  case CL_INVALID_PROGRAM:
429  return "CL_INVALID_PROGRAM";
430  case CL_INVALID_PROGRAM_EXECUTABLE:
431  return "CL_INVALID_PROGRAM_EXECUTABLE";
432  case CL_INVALID_KERNEL_NAME:
433  return "CL_INVALID_KERNEL_NAME";
434  case CL_INVALID_KERNEL_DEFINITION:
435  return "CL_INVALID_KERNEL_DEFINITION";
436  case CL_INVALID_KERNEL:
437  return "CL_INVALID_KERNEL";
438  case CL_INVALID_ARG_INDEX:
439  return "CL_INVALID_ARG_INDEX";
440  case CL_INVALID_ARG_VALUE:
441  return "CL_INVALID_ARG_VALUE";
442  case CL_INVALID_ARG_SIZE:
443  return "CL_INVALID_ARG_SIZE";
444  case CL_INVALID_KERNEL_ARGS:
445  return "CL_INVALID_KERNEL_ARGS";
446  case CL_INVALID_WORK_DIMENSION:
447  return "CL_INVALID_WORK_DIMENSION";
448  case CL_INVALID_WORK_GROUP_SIZE:
449  return "CL_INVALID_WORK_GROUP_SIZE";
450  case CL_INVALID_WORK_ITEM_SIZE:
451  return "CL_INVALID_WORK_ITEM_SIZE";
452  case CL_INVALID_GLOBAL_OFFSET:
453  return "CL_INVALID_GLOBAL_OFFSET";
454  case CL_INVALID_EVENT_WAIT_LIST:
455  return "CL_INVALID_EVENT_WAIT_LIST";
456  case CL_INVALID_EVENT:
457  return "CL_INVALID_EVENT";
458  case CL_INVALID_OPERATION:
459  return "CL_INVALID_OPERATION";
460  case CL_INVALID_GL_OBJECT:
461  return "CL_INVALID_GL_OBJECT";
462  case CL_INVALID_BUFFER_SIZE:
463  return "CL_INVALID_BUFFER_SIZE";
464  case CL_INVALID_MIP_LEVEL:
465  return "CL_INVALID_MIP_LEVEL";
466  default:
467  return "Unknown error";
468  }
469 }
470 
471 bool isExtensionSupported(cl_device_id device, string extension)
472 {
473  if (extension.empty())
474  {
475  return false;
476  }
477 
478  /* First find out how large the ouput of the OpenCL device query will be. */
479  size_t extensionsReturnSize = 0;
480  if (!checkSuccess(clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, 0, NULL, &extensionsReturnSize)))
481  {
482  cerr << "Failed to get return size from clGetDeviceInfo for parameter CL_DEVICE_EXTENSIONS. " << __FILE__ << ":"<< __LINE__ << endl;
483  return false;
484  }
485 
486  /* Allocate enough memory for the output. */
487  char* extensions = new char[extensionsReturnSize];
488 
489  /* Get the list of all extensions supported. */
490  if (!checkSuccess(clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, extensionsReturnSize, extensions, NULL)))
491  {
492  cerr << "Failed to get data from clGetDeviceInfo for parameter CL_DEVICE_EXTENSIONS. " << __FILE__ << ":"<< __LINE__ << endl;
493  delete [] extensions;
494  return false;
495  }
496 
497  /* See if the requested extension is in the list. */
498  string* extensionsString = new string(extensions);
499  bool returnResult = false;
500  if (extensionsString->find(extension) != string::npos)
501  {
502  returnResult = true;
503  }
504 
505  delete [] extensions;
506  delete extensionsString;
507 
508  return returnResult;
509 }