Cycles: svn merge -r41225:41232 ^/trunk/blender
[blender.git] / intern / cycles / util / util_opencl.c
1 //////////////////////////////////////////////////////////////////////////
2 //  Copyright (c) 2009 Organic Vectory B.V.
3 //  Written by George van Venrooij
4 //
5 //  Distributed under the Boost Software License, Version 1.0.
6 //  (See accompanying file doc/license/Boost.txt)
7 //  Extracted from the CLCC project - http://clcc.sourceforge.net/
8 //////////////////////////////////////////////////////////////////////////
9
10 #include "util_opencl.h"
11
12 #ifndef CLCC_GENERATE_DOCUMENTATION
13 #ifdef _WIN32
14     #define WIN32_LEAN_AND_MEAN
15     #define VC_EXTRALEAN
16     #include <windows.h>
17
18     typedef HMODULE             CLCC_DYNLIB_HANDLE;
19
20     #define CLCC_DYNLIB_OPEN    LoadLibrary
21     #define CLCC_DYNLIB_CLOSE   FreeLibrary
22     #define CLCC_DYNLIB_IMPORT  GetProcAddress
23 #else
24     #include <dlfcn.h>
25     
26     typedef void*                   CLCC_DYNLIB_HANDLE;
27
28     #define CLCC_DYNLIB_OPEN(path)  dlopen(path, RTLD_NOW | RTLD_GLOBAL)
29     #define CLCC_DYNLIB_CLOSE       dlclose
30     #define CLCC_DYNLIB_IMPORT      dlsym
31 #endif
32 #else
33     //typedef implementation_defined  CLCC_DYNLIB_HANDLE;
34     //#define CLCC_DYNLIB_OPEN(path)  implementation_defined
35     //#define CLCC_DYNLIB_CLOSE       implementation_defined
36     //#define CLCC_DYNLIB_IMPORT      implementation_defined
37 #endif
38
39 #include <stdlib.h>
40
41 //! \brief module handle
42 static CLCC_DYNLIB_HANDLE module = NULL;
43
44 //  Variables holding function entry points
45 #ifndef CLCC_GENERATE_DOCUMENTATION
46 PFNCLGETPLATFORMIDS                 __clewGetPlatformIDs                = NULL;
47 PFNCLGETPLATFORMINFO                __clewGetPlatformInfo               = NULL;
48 PFNCLGETDEVICEIDS                   __clewGetDeviceIDs                  = NULL;
49 PFNCLGETDEVICEINFO                  __clewGetDeviceInfo                 = NULL;
50 PFNCLCREATECONTEXT                  __clewCreateContext                 = NULL;
51 PFNCLCREATECONTEXTFROMTYPE          __clewCreateContextFromType         = NULL;
52 PFNCLRETAINCONTEXT                  __clewRetainContext                 = NULL;
53 PFNCLRELEASECONTEXT                 __clewReleaseContext                = NULL;
54 PFNCLGETCONTEXTINFO                 __clewGetContextInfo                = NULL;
55 PFNCLCREATECOMMANDQUEUE             __clewCreateCommandQueue            = NULL;
56 PFNCLRETAINCOMMANDQUEUE             __clewRetainCommandQueue            = NULL;
57 PFNCLRELEASECOMMANDQUEUE            __clewReleaseCommandQueue           = NULL;
58 PFNCLGETCOMMANDQUEUEINFO            __clewGetCommandQueueInfo           = NULL;
59 PFNCLSETCOMMANDQUEUEPROPERTY        __clewSetCommandQueueProperty       = NULL;
60 PFNCLCREATEBUFFER                   __clewCreateBuffer                  = NULL;
61 PFNCLCREATEIMAGE2D                  __clewCreateImage2D                 = NULL;
62 PFNCLCREATEIMAGE3D                  __clewCreateImage3D                 = NULL;
63 PFNCLRETAINMEMOBJECT                __clewRetainMemObject               = NULL;
64 PFNCLRELEASEMEMOBJECT               __clewReleaseMemObject              = NULL;
65 PFNCLGETSUPPORTEDIMAGEFORMATS       __clewGetSupportedImageFormats      = NULL;
66 PFNCLGETMEMOBJECTINFO               __clewGetMemObjectInfo              = NULL;
67 PFNCLGETIMAGEINFO                   __clewGetImageInfo                  = NULL;
68 PFNCLCREATESAMPLER                  __clewCreateSampler                 = NULL;
69 PFNCLRETAINSAMPLER                  __clewRetainSampler                 = NULL;
70 PFNCLRELEASESAMPLER                 __clewReleaseSampler                = NULL;
71 PFNCLGETSAMPLERINFO                 __clewGetSamplerInfo                = NULL;
72 PFNCLCREATEPROGRAMWITHSOURCE        __clewCreateProgramWithSource       = NULL;
73 PFNCLCREATEPROGRAMWITHBINARY        __clewCreateProgramWithBinary       = NULL;
74 PFNCLRETAINPROGRAM                  __clewRetainProgram                 = NULL;
75 PFNCLRELEASEPROGRAM                 __clewReleaseProgram                = NULL;
76 PFNCLBUILDPROGRAM                   __clewBuildProgram                  = NULL;
77 PFNCLUNLOADCOMPILER                 __clewUnloadCompiler                = NULL;
78 PFNCLGETPROGRAMINFO                 __clewGetProgramInfo                = NULL;
79 PFNCLGETPROGRAMBUILDINFO            __clewGetProgramBuildInfo           = NULL;
80 PFNCLCREATEKERNEL                   __clewCreateKernel                  = NULL;
81 PFNCLCREATEKERNELSINPROGRAM         __clewCreateKernelsInProgram        = NULL;
82 PFNCLRETAINKERNEL                   __clewRetainKernel                  = NULL;
83 PFNCLRELEASEKERNEL                  __clewReleaseKernel                 = NULL;
84 PFNCLSETKERNELARG                   __clewSetKernelArg                  = NULL;
85 PFNCLGETKERNELINFO                  __clewGetKernelInfo                 = NULL;
86 PFNCLGETKERNELWORKGROUPINFO         __clewGetKernelWorkGroupInfo        = NULL;
87 PFNCLWAITFOREVENTS                  __clewWaitForEvents                 = NULL;
88 PFNCLGETEVENTINFO                   __clewGetEventInfo                  = NULL;
89 PFNCLRETAINEVENT                    __clewRetainEvent                   = NULL;
90 PFNCLRELEASEEVENT                   __clewReleaseEvent                  = NULL;
91 PFNCLGETEVENTPROFILINGINFO          __clewGetEventProfilingInfo         = NULL;
92 PFNCLFLUSH                          __clewFlush                         = NULL;
93 PFNCLFINISH                         __clewFinish                        = NULL;
94 PFNCLENQUEUEREADBUFFER              __clewEnqueueReadBuffer             = NULL;
95 PFNCLENQUEUEWRITEBUFFER             __clewEnqueueWriteBuffer            = NULL;
96 PFNCLENQUEUECOPYBUFFER              __clewEnqueueCopyBuffer             = NULL;
97 PFNCLENQUEUEREADIMAGE               __clewEnqueueReadImage              = NULL;
98 PFNCLENQUEUEWRITEIMAGE              __clewEnqueueWriteImage             = NULL;
99 PFNCLENQUEUECOPYIMAGE               __clewEnqueueCopyImage              = NULL;
100 PFNCLENQUEUECOPYIMAGETOBUFFER       __clewEnqueueCopyImageToBuffer      = NULL;
101 PFNCLENQUEUECOPYBUFFERTOIMAGE       __clewEnqueueCopyBufferToImage      = NULL;
102 PFNCLENQUEUEMAPBUFFER               __clewEnqueueMapBuffer              = NULL;
103 PFNCLENQUEUEMAPIMAGE                __clewEnqueueMapImage               = NULL;
104 PFNCLENQUEUEUNMAPMEMOBJECT          __clewEnqueueUnmapMemObject         = NULL;
105 PFNCLENQUEUENDRANGEKERNEL           __clewEnqueueNDRangeKernel          = NULL;
106 PFNCLENQUEUETASK                    __clewEnqueueTask                   = NULL;
107 PFNCLENQUEUENATIVEKERNEL            __clewEnqueueNativeKernel           = NULL;
108 PFNCLENQUEUEMARKER                  __clewEnqueueMarker                 = NULL;
109 PFNCLENQUEUEWAITFOREVENTS           __clewEnqueueWaitForEvents          = NULL;
110 PFNCLENQUEUEBARRIER                 __clewEnqueueBarrier                = NULL;
111 PFNCLGETEXTENSIONFUNCTIONADDRESS    __clewGetExtensionFunctionAddress   = NULL;
112 #endif  //  CLCC_GENERATE_DOCUMENTATION
113
114
115 //! \brief Unloads OpenCL dynamic library, should not be called directly
116 static void clewExit(void)
117 {
118     if (module != NULL)
119     {
120         //  Ignore errors
121         CLCC_DYNLIB_CLOSE(module);
122         module = NULL;
123     }
124 }
125
126 //! \param path path to dynamic library to load
127 //! \return CLEW_ERROR_OPEN_FAILED if the library could not be opened
128 //! CLEW_ERROR_ATEXIT_FAILED if atexit(clewExit) failed
129 //! CLEW_SUCCESS when the library was succesfully loaded
130 int clLibraryInit()
131 {
132 #ifdef _WIN32
133         const char *path = "OpenCL.dll";
134 #elif defined(__APPLE__)
135         const char *path = "/Library/Frameworks/OpenCL.framework/OpenCL";
136 #else
137         const char *path = "libOpenCL.so";
138 #endif
139     int error = 0;
140
141     //  Check if already initialized
142     if (module != NULL)
143     {
144         return 1;
145     }
146
147     //  Load library
148     module = CLCC_DYNLIB_OPEN(path);
149
150     //  Check for errors
151     if (module == NULL)
152     {
153         return 0;
154     }
155
156     //  Set unloading
157     error = atexit(clewExit);
158
159     if (error)
160     {
161         //  Failure queing atexit, shutdown with error
162         CLCC_DYNLIB_CLOSE(module);
163         module = NULL;
164
165         return 0;
166     }
167
168     //  Determine function entry-points
169     __clewGetPlatformIDs                = (PFNCLGETPLATFORMIDS              )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs");
170     __clewGetPlatformInfo               = (PFNCLGETPLATFORMINFO             )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo");
171     __clewGetDeviceIDs                  = (PFNCLGETDEVICEIDS                )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs");
172     __clewGetDeviceInfo                 = (PFNCLGETDEVICEINFO               )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo");
173     __clewCreateContext                 = (PFNCLCREATECONTEXT               )CLCC_DYNLIB_IMPORT(module, "clCreateContext");
174     __clewCreateContextFromType         = (PFNCLCREATECONTEXTFROMTYPE       )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType");
175     __clewRetainContext                 = (PFNCLRETAINCONTEXT               )CLCC_DYNLIB_IMPORT(module, "clRetainContext");
176     __clewReleaseContext                = (PFNCLRELEASECONTEXT              )CLCC_DYNLIB_IMPORT(module, "clReleaseContext");
177     __clewGetContextInfo                = (PFNCLGETCONTEXTINFO              )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo");
178     __clewCreateCommandQueue            = (PFNCLCREATECOMMANDQUEUE          )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue");
179     __clewRetainCommandQueue            = (PFNCLRETAINCOMMANDQUEUE          )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue");
180     __clewReleaseCommandQueue           = (PFNCLRELEASECOMMANDQUEUE         )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
181     __clewGetCommandQueueInfo           = (PFNCLGETCOMMANDQUEUEINFO         )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
182     __clewSetCommandQueueProperty       = (PFNCLSETCOMMANDQUEUEPROPERTY     )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
183     __clewCreateBuffer                  = (PFNCLCREATEBUFFER                )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer");
184     __clewCreateImage2D                 = (PFNCLCREATEIMAGE2D               )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D");
185     __clewCreateImage3D                 = (PFNCLCREATEIMAGE3D               )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D");
186     __clewRetainMemObject               = (PFNCLRETAINMEMOBJECT             )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject");
187     __clewReleaseMemObject              = (PFNCLRELEASEMEMOBJECT            )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject");
188     __clewGetSupportedImageFormats      = (PFNCLGETSUPPORTEDIMAGEFORMATS    )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
189     __clewGetMemObjectInfo              = (PFNCLGETMEMOBJECTINFO            )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
190     __clewGetImageInfo                  = (PFNCLGETIMAGEINFO                )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo");
191     __clewCreateSampler                 = (PFNCLCREATESAMPLER               )CLCC_DYNLIB_IMPORT(module, "clCreateSampler");
192     __clewRetainSampler                 = (PFNCLRETAINSAMPLER               )CLCC_DYNLIB_IMPORT(module, "clRetainSampler");
193     __clewReleaseSampler                = (PFNCLRELEASESAMPLER              )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler");
194     __clewGetSamplerInfo                = (PFNCLGETSAMPLERINFO              )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo");
195     __clewCreateProgramWithSource       = (PFNCLCREATEPROGRAMWITHSOURCE     )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
196     __clewCreateProgramWithBinary       = (PFNCLCREATEPROGRAMWITHBINARY     )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
197     __clewRetainProgram                 = (PFNCLRETAINPROGRAM               )CLCC_DYNLIB_IMPORT(module, "clRetainProgram");
198     __clewReleaseProgram                = (PFNCLRELEASEPROGRAM              )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram");
199     __clewBuildProgram                  = (PFNCLBUILDPROGRAM                )CLCC_DYNLIB_IMPORT(module, "clBuildProgram");
200     __clewUnloadCompiler                = (PFNCLUNLOADCOMPILER              )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler");
201     __clewGetProgramInfo                = (PFNCLGETPROGRAMINFO              )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo");
202     __clewGetProgramBuildInfo           = (PFNCLGETPROGRAMBUILDINFO         )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
203     __clewCreateKernel                  = (PFNCLCREATEKERNEL                )CLCC_DYNLIB_IMPORT(module, "clCreateKernel");
204     __clewCreateKernelsInProgram        = (PFNCLCREATEKERNELSINPROGRAM      )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
205     __clewRetainKernel                  = (PFNCLRETAINKERNEL                )CLCC_DYNLIB_IMPORT(module, "clRetainKernel");
206     __clewReleaseKernel                 = (PFNCLRELEASEKERNEL               )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel");
207     __clewSetKernelArg                  = (PFNCLSETKERNELARG                )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg");
208     __clewGetKernelInfo                 = (PFNCLGETKERNELINFO               )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo");
209     __clewGetKernelWorkGroupInfo        = (PFNCLGETKERNELWORKGROUPINFO      )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
210     __clewWaitForEvents                 = (PFNCLWAITFOREVENTS               )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents");
211     __clewGetEventInfo                  = (PFNCLGETEVENTINFO                )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo");
212     __clewRetainEvent                   = (PFNCLRETAINEVENT                 )CLCC_DYNLIB_IMPORT(module, "clRetainEvent");
213     __clewReleaseEvent                  = (PFNCLRELEASEEVENT                )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent");
214     __clewGetEventProfilingInfo         = (PFNCLGETEVENTPROFILINGINFO       )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
215     __clewFlush                         = (PFNCLFLUSH                       )CLCC_DYNLIB_IMPORT(module, "clFlush");
216     __clewFinish                        = (PFNCLFINISH                      )CLCC_DYNLIB_IMPORT(module, "clFinish");
217     __clewEnqueueReadBuffer             = (PFNCLENQUEUEREADBUFFER           )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
218     __clewEnqueueWriteBuffer            = (PFNCLENQUEUEWRITEBUFFER          )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
219     __clewEnqueueCopyBuffer             = (PFNCLENQUEUECOPYBUFFER           )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
220     __clewEnqueueReadImage              = (PFNCLENQUEUEREADIMAGE            )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage");
221     __clewEnqueueWriteImage             = (PFNCLENQUEUEWRITEIMAGE           )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
222     __clewEnqueueCopyImage              = (PFNCLENQUEUECOPYIMAGE            )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
223     __clewEnqueueCopyImageToBuffer      = (PFNCLENQUEUECOPYIMAGETOBUFFER    )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
224     __clewEnqueueCopyBufferToImage      = (PFNCLENQUEUECOPYBUFFERTOIMAGE    )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
225     __clewEnqueueMapBuffer              = (PFNCLENQUEUEMAPBUFFER            )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
226     __clewEnqueueMapImage               = (PFNCLENQUEUEMAPIMAGE             )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage");
227     __clewEnqueueUnmapMemObject         = (PFNCLENQUEUEUNMAPMEMOBJECT       )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
228     __clewEnqueueNDRangeKernel          = (PFNCLENQUEUENDRANGEKERNEL        )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
229     __clewEnqueueTask                   = (PFNCLENQUEUETASK                 )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask");
230     __clewEnqueueNativeKernel           = (PFNCLENQUEUENATIVEKERNEL         )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
231     __clewEnqueueMarker                 = (PFNCLENQUEUEMARKER               )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker");
232     __clewEnqueueWaitForEvents          = (PFNCLENQUEUEWAITFOREVENTS        )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
233     __clewEnqueueBarrier                = (PFNCLENQUEUEBARRIER              )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier");
234     __clewGetExtensionFunctionAddress   = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
235
236     return 1;
237 }
238
239 //! \param error CL error code
240 //! \return a string representation of the error code
241 const char *clErrorString(cl_int error)
242 {
243     static const char* strings[] =
244     {
245         // Error Codes
246           "CL_SUCCESS"                                  //   0
247         , "CL_DEVICE_NOT_FOUND"                         //  -1
248         , "CL_DEVICE_NOT_AVAILABLE"                     //  -2
249         , "CL_COMPILER_NOT_AVAILABLE"                   //  -3
250         , "CL_MEM_OBJECT_ALLOCATION_FAILURE"            //  -4
251         , "CL_OUT_OF_RESOURCES"                         //  -5
252         , "CL_OUT_OF_HOST_MEMORY"                       //  -6
253         , "CL_PROFILING_INFO_NOT_AVAILABLE"             //  -7
254         , "CL_MEM_COPY_OVERLAP"                         //  -8
255         , "CL_IMAGE_FORMAT_MISMATCH"                    //  -9
256         , "CL_IMAGE_FORMAT_NOT_SUPPORTED"               //  -10
257         , "CL_BUILD_PROGRAM_FAILURE"                    //  -11
258         , "CL_MAP_FAILURE"                              //  -12
259
260         , ""    //  -13
261         , ""    //  -14
262         , ""    //  -15
263         , ""    //  -16
264         , ""    //  -17
265         , ""    //  -18
266         , ""    //  -19
267
268         , ""    //  -20
269         , ""    //  -21
270         , ""    //  -22
271         , ""    //  -23
272         , ""    //  -24
273         , ""    //  -25
274         , ""    //  -26
275         , ""    //  -27
276         , ""    //  -28
277         , ""    //  -29
278
279         , "CL_INVALID_VALUE"                            //  -30
280         , "CL_INVALID_DEVICE_TYPE"                      //  -31
281         , "CL_INVALID_PLATFORM"                         //  -32
282         , "CL_INVALID_DEVICE"                           //  -33
283         , "CL_INVALID_CONTEXT"                          //  -34
284         , "CL_INVALID_QUEUE_PROPERTIES"                 //  -35
285         , "CL_INVALID_COMMAND_QUEUE"                    //  -36
286         , "CL_INVALID_HOST_PTR"                         //  -37
287         , "CL_INVALID_MEM_OBJECT"                       //  -38
288         , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"          //  -39
289         , "CL_INVALID_IMAGE_SIZE"                       //  -40
290         , "CL_INVALID_SAMPLER"                          //  -41
291         , "CL_INVALID_BINARY"                           //  -42
292         , "CL_INVALID_BUILD_OPTIONS"                    //  -43
293         , "CL_INVALID_PROGRAM"                          //  -44
294         , "CL_INVALID_PROGRAM_EXECUTABLE"               //  -45
295         , "CL_INVALID_KERNEL_NAME"                      //  -46
296         , "CL_INVALID_KERNEL_DEFINITION"                //  -47
297         , "CL_INVALID_KERNEL"                           //  -48
298         , "CL_INVALID_ARG_INDEX"                        //  -49
299         , "CL_INVALID_ARG_VALUE"                        //  -50
300         , "CL_INVALID_ARG_SIZE"                         //  -51
301         , "CL_INVALID_KERNEL_ARGS"                      //  -52
302         , "CL_INVALID_WORK_DIMENSION"                   //  -53
303         , "CL_INVALID_WORK_GROUP_SIZE"                  //  -54
304         , "CL_INVALID_WORK_ITEM_SIZE"                   //  -55
305         , "CL_INVALID_GLOBAL_OFFSET"                    //  -56
306         , "CL_INVALID_EVENT_WAIT_LIST"                  //  -57
307         , "CL_INVALID_EVENT"                            //  -58
308         , "CL_INVALID_OPERATION"                        //  -59
309         , "CL_INVALID_GL_OBJECT"                        //  -60
310         , "CL_INVALID_BUFFER_SIZE"                      //  -61
311         , "CL_INVALID_MIP_LEVEL"                        //  -62
312         , "CL_INVALID_GLOBAL_WORK_SIZE"                 //  -63
313     };
314
315     return strings[-error];
316 }
317