d68eb17288f532e8d490b273f5a562ce42658f6a
[blender.git] / intern / opencl / intern / clew.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 license.txt)
7 //////////////////////////////////////////////////////////////////////////
8
9 #include "clew.h"
10
11 //! \file clew.c
12 //! \brief OpenCL run-time loader source
13
14 #ifndef CLCC_GENERATE_DOCUMENTATION
15 #ifdef _WIN32
16     #define WIN32_LEAN_AND_MEAN
17     #define VC_EXTRALEAN
18     #include <windows.h>
19
20     typedef HMODULE             CLCC_DYNLIB_HANDLE;
21
22     #define CLCC_DYNLIB_OPEN    LoadLibrary
23     #define CLCC_DYNLIB_CLOSE   FreeLibrary
24     #define CLCC_DYNLIB_IMPORT  GetProcAddress
25 #else
26     #include <dlfcn.h>
27     
28     typedef void*                   CLCC_DYNLIB_HANDLE;
29
30     #define CLCC_DYNLIB_OPEN(path)  dlopen(path, RTLD_NOW | RTLD_GLOBAL)
31     #define CLCC_DYNLIB_CLOSE       dlclose
32     #define CLCC_DYNLIB_IMPORT      dlsym
33 #endif
34 #else
35     //typedef implementation_defined  CLCC_DYNLIB_HANDLE;
36     //#define CLCC_DYNLIB_OPEN(path)  implementation_defined
37     //#define CLCC_DYNLIB_CLOSE       implementation_defined
38     //#define CLCC_DYNLIB_IMPORT      implementation_defined
39 #endif
40
41 #include <stdlib.h>
42
43 //! \brief module handle
44 static CLCC_DYNLIB_HANDLE module = NULL;
45
46 //  Variables holding function entry points
47 #ifndef CLCC_GENERATE_DOCUMENTATION
48 PFNCLGETPLATFORMIDS                 __oclGetPlatformIDs                = NULL;
49 PFNCLGETPLATFORMINFO                __oclGetPlatformInfo               = NULL;
50 PFNCLGETDEVICEIDS                   __oclGetDeviceIDs                  = NULL;
51 PFNCLGETDEVICEINFO                  __oclGetDeviceInfo                 = NULL;
52 PFNCLCREATECONTEXT                  __oclCreateContext                 = NULL;
53 PFNCLCREATECONTEXTFROMTYPE          __oclCreateContextFromType         = NULL;
54 PFNCLRETAINCONTEXT                  __oclRetainContext                 = NULL;
55 PFNCLRELEASECONTEXT                 __oclReleaseContext                = NULL;
56 PFNCLGETCONTEXTINFO                 __oclGetContextInfo                = NULL;
57 PFNCLCREATECOMMANDQUEUE             __oclCreateCommandQueue            = NULL;
58 PFNCLRETAINCOMMANDQUEUE             __oclRetainCommandQueue            = NULL;
59 PFNCLRELEASECOMMANDQUEUE            __oclReleaseCommandQueue           = NULL;
60 PFNCLGETCOMMANDQUEUEINFO            __oclGetCommandQueueInfo           = NULL;
61 PFNCLSETCOMMANDQUEUEPROPERTY        __oclSetCommandQueueProperty       = NULL;
62 PFNCLCREATEBUFFER                   __oclCreateBuffer                  = NULL;
63 PFNCLCREATEIMAGE2D                  __oclCreateImage2D                 = NULL;
64 PFNCLCREATEIMAGE3D                  __oclCreateImage3D                 = NULL;
65 PFNCLRETAINMEMOBJECT                __oclRetainMemObject               = NULL;
66 PFNCLRELEASEMEMOBJECT               __oclReleaseMemObject              = NULL;
67 PFNCLGETSUPPORTEDIMAGEFORMATS       __oclGetSupportedImageFormats      = NULL;
68 PFNCLGETMEMOBJECTINFO               __oclGetMemObjectInfo              = NULL;
69 PFNCLGETIMAGEINFO                   __oclGetImageInfo                  = NULL;
70 PFNCLCREATESAMPLER                  __oclCreateSampler                 = NULL;
71 PFNCLRETAINSAMPLER                  __oclRetainSampler                 = NULL;
72 PFNCLRELEASESAMPLER                 __oclReleaseSampler                = NULL;
73 PFNCLGETSAMPLERINFO                 __oclGetSamplerInfo                = NULL;
74 PFNCLCREATEPROGRAMWITHSOURCE        __oclCreateProgramWithSource       = NULL;
75 PFNCLCREATEPROGRAMWITHBINARY        __oclCreateProgramWithBinary       = NULL;
76 PFNCLRETAINPROGRAM                  __oclRetainProgram                 = NULL;
77 PFNCLRELEASEPROGRAM                 __oclReleaseProgram                = NULL;
78 PFNCLBUILDPROGRAM                   __oclBuildProgram                  = NULL;
79 PFNCLUNLOADCOMPILER                 __oclUnloadCompiler                = NULL;
80 PFNCLGETPROGRAMINFO                 __oclGetProgramInfo                = NULL;
81 PFNCLGETPROGRAMBUILDINFO            __oclGetProgramBuildInfo           = NULL;
82 PFNCLCREATEKERNEL                   __oclCreateKernel                  = NULL;
83 PFNCLCREATEKERNELSINPROGRAM         __oclCreateKernelsInProgram        = NULL;
84 PFNCLRETAINKERNEL                   __oclRetainKernel                  = NULL;
85 PFNCLRELEASEKERNEL                  __oclReleaseKernel                 = NULL;
86 PFNCLSETKERNELARG                   __oclSetKernelArg                  = NULL;
87 PFNCLGETKERNELINFO                  __oclGetKernelInfo                 = NULL;
88 PFNCLGETKERNELWORKGROUPINFO         __oclGetKernelWorkGroupInfo        = NULL;
89 PFNCLWAITFOREVENTS                  __oclWaitForEvents                 = NULL;
90 PFNCLGETEVENTINFO                   __oclGetEventInfo                  = NULL;
91 PFNCLRETAINEVENT                    __oclRetainEvent                   = NULL;
92 PFNCLRELEASEEVENT                   __oclReleaseEvent                  = NULL;
93 PFNCLGETEVENTPROFILINGINFO          __oclGetEventProfilingInfo         = NULL;
94 PFNCLFLUSH                          __oclFlush                         = NULL;
95 PFNCLFINISH                         __oclFinish                        = NULL;
96 PFNCLENQUEUEREADBUFFER              __oclEnqueueReadBuffer             = NULL;
97 PFNCLENQUEUEWRITEBUFFER             __oclEnqueueWriteBuffer            = NULL;
98 PFNCLENQUEUECOPYBUFFER              __oclEnqueueCopyBuffer             = NULL;
99 PFNCLENQUEUEREADIMAGE               __oclEnqueueReadImage              = NULL;
100 PFNCLENQUEUEWRITEIMAGE              __oclEnqueueWriteImage             = NULL;
101 PFNCLENQUEUECOPYIMAGE               __oclEnqueueCopyImage              = NULL;
102 PFNCLENQUEUECOPYIMAGETOBUFFER       __oclEnqueueCopyImageToBuffer      = NULL;
103 PFNCLENQUEUECOPYBUFFERTOIMAGE       __oclEnqueueCopyBufferToImage      = NULL;
104 PFNCLENQUEUEMAPBUFFER               __oclEnqueueMapBuffer              = NULL;
105 PFNCLENQUEUEMAPIMAGE                __oclEnqueueMapImage               = NULL;
106 PFNCLENQUEUEUNMAPMEMOBJECT          __oclEnqueueUnmapMemObject         = NULL;
107 PFNCLENQUEUENDRANGEKERNEL           __oclEnqueueNDRangeKernel          = NULL;
108 PFNCLENQUEUETASK                    __oclEnqueueTask                   = NULL;
109 PFNCLENQUEUENATIVEKERNEL            __oclEnqueueNativeKernel           = NULL;
110 PFNCLENQUEUEMARKER                  __oclEnqueueMarker                 = NULL;
111 PFNCLENQUEUEWAITFOREVENTS           __oclEnqueueWaitForEvents          = NULL;
112 PFNCLENQUEUEBARRIER                 __oclEnqueueBarrier                = NULL;
113 PFNCLGETEXTENSIONFUNCTIONADDRESS    __oclGetExtensionFunctionAddress   = NULL;
114 #endif  //  CLCC_GENERATE_DOCUMENTATION
115
116
117 //! \brief Unloads OpenCL dynamic library, should not be called directly
118 static void clewExit(void)
119 {
120     if (module != NULL)
121     {
122         //  Ignore errors
123         CLCC_DYNLIB_CLOSE(module);
124         module = NULL;
125     }
126 }
127
128 //! \param path path to dynamic library to load
129 //! \return CLEW_ERROR_OPEN_FAILED if the library could not be opened
130 //! CLEW_ERROR_ATEXIT_FAILED if atexit(clewExit) failed
131 //! CLEW_SUCCESS when the library was succesfully loaded
132 int clewInit(const char* path)
133 {
134     int error = 0;
135
136     //  Check if already initialized
137     if (module != NULL)
138     {
139         return CLEW_SUCCESS;
140     }
141
142     //  Load library
143     module = CLCC_DYNLIB_OPEN(path);
144
145     //  Check for errors
146     if (module == NULL)
147     {
148         return CLEW_ERROR_OPEN_FAILED;
149     }
150
151     //  Set unloading
152     error = atexit(clewExit);
153
154     if (error)
155     {
156         //  Failure queing atexit, shutdown with error
157         CLCC_DYNLIB_CLOSE(module);
158         module = NULL;
159
160         return CLEW_ERROR_ATEXIT_FAILED;
161     }
162
163     //  Determine function entry-points
164     __oclGetPlatformIDs                = (PFNCLGETPLATFORMIDS              )CLCC_DYNLIB_IMPORT(module, "clGetPlatformIDs");
165     __oclGetPlatformInfo               = (PFNCLGETPLATFORMINFO             )CLCC_DYNLIB_IMPORT(module, "clGetPlatformInfo");
166     __oclGetDeviceIDs                  = (PFNCLGETDEVICEIDS                )CLCC_DYNLIB_IMPORT(module, "clGetDeviceIDs");
167     __oclGetDeviceInfo                 = (PFNCLGETDEVICEINFO               )CLCC_DYNLIB_IMPORT(module, "clGetDeviceInfo");
168     __oclCreateContext                 = (PFNCLCREATECONTEXT               )CLCC_DYNLIB_IMPORT(module, "clCreateContext");
169     __oclCreateContextFromType         = (PFNCLCREATECONTEXTFROMTYPE       )CLCC_DYNLIB_IMPORT(module, "clCreateContextFromType");
170     __oclRetainContext                 = (PFNCLRETAINCONTEXT               )CLCC_DYNLIB_IMPORT(module, "clRetainContext");
171     __oclReleaseContext                = (PFNCLRELEASECONTEXT              )CLCC_DYNLIB_IMPORT(module, "clReleaseContext");
172     __oclGetContextInfo                = (PFNCLGETCONTEXTINFO              )CLCC_DYNLIB_IMPORT(module, "clGetContextInfo");
173     __oclCreateCommandQueue            = (PFNCLCREATECOMMANDQUEUE          )CLCC_DYNLIB_IMPORT(module, "clCreateCommandQueue");
174     __oclRetainCommandQueue            = (PFNCLRETAINCOMMANDQUEUE          )CLCC_DYNLIB_IMPORT(module, "clRetainCommandQueue");
175     __oclReleaseCommandQueue           = (PFNCLRELEASECOMMANDQUEUE         )CLCC_DYNLIB_IMPORT(module, "clReleaseCommandQueue");
176     __oclGetCommandQueueInfo           = (PFNCLGETCOMMANDQUEUEINFO         )CLCC_DYNLIB_IMPORT(module, "clGetCommandQueueInfo");
177     __oclSetCommandQueueProperty       = (PFNCLSETCOMMANDQUEUEPROPERTY     )CLCC_DYNLIB_IMPORT(module, "clSetCommandQueueProperty");
178     __oclCreateBuffer                  = (PFNCLCREATEBUFFER                )CLCC_DYNLIB_IMPORT(module, "clCreateBuffer");
179     __oclCreateImage2D                 = (PFNCLCREATEIMAGE2D               )CLCC_DYNLIB_IMPORT(module, "clCreateImage2D");
180     __oclCreateImage3D                 = (PFNCLCREATEIMAGE3D               )CLCC_DYNLIB_IMPORT(module, "clCreateImage3D");
181     __oclRetainMemObject               = (PFNCLRETAINMEMOBJECT             )CLCC_DYNLIB_IMPORT(module, "clRetainMemObject");
182     __oclReleaseMemObject              = (PFNCLRELEASEMEMOBJECT            )CLCC_DYNLIB_IMPORT(module, "clReleaseMemObject");
183     __oclGetSupportedImageFormats      = (PFNCLGETSUPPORTEDIMAGEFORMATS    )CLCC_DYNLIB_IMPORT(module, "clGetSupportedImageFormats");
184     __oclGetMemObjectInfo              = (PFNCLGETMEMOBJECTINFO            )CLCC_DYNLIB_IMPORT(module, "clGetMemObjectInfo");
185     __oclGetImageInfo                  = (PFNCLGETIMAGEINFO                )CLCC_DYNLIB_IMPORT(module, "clGetImageInfo");
186     __oclCreateSampler                 = (PFNCLCREATESAMPLER               )CLCC_DYNLIB_IMPORT(module, "clCreateSampler");
187     __oclRetainSampler                 = (PFNCLRETAINSAMPLER               )CLCC_DYNLIB_IMPORT(module, "clRetainSampler");
188     __oclReleaseSampler                = (PFNCLRELEASESAMPLER              )CLCC_DYNLIB_IMPORT(module, "clReleaseSampler");
189     __oclGetSamplerInfo                = (PFNCLGETSAMPLERINFO              )CLCC_DYNLIB_IMPORT(module, "clGetSamplerInfo");
190     __oclCreateProgramWithSource       = (PFNCLCREATEPROGRAMWITHSOURCE     )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithSource");
191     __oclCreateProgramWithBinary       = (PFNCLCREATEPROGRAMWITHBINARY     )CLCC_DYNLIB_IMPORT(module, "clCreateProgramWithBinary");
192     __oclRetainProgram                 = (PFNCLRETAINPROGRAM               )CLCC_DYNLIB_IMPORT(module, "clRetainProgram");
193     __oclReleaseProgram                = (PFNCLRELEASEPROGRAM              )CLCC_DYNLIB_IMPORT(module, "clReleaseProgram");
194     __oclBuildProgram                  = (PFNCLBUILDPROGRAM                )CLCC_DYNLIB_IMPORT(module, "clBuildProgram");
195     __oclUnloadCompiler                = (PFNCLUNLOADCOMPILER              )CLCC_DYNLIB_IMPORT(module, "clUnloadCompiler");
196     __oclGetProgramInfo                = (PFNCLGETPROGRAMINFO              )CLCC_DYNLIB_IMPORT(module, "clGetProgramInfo");
197     __oclGetProgramBuildInfo           = (PFNCLGETPROGRAMBUILDINFO         )CLCC_DYNLIB_IMPORT(module, "clGetProgramBuildInfo");
198     __oclCreateKernel                  = (PFNCLCREATEKERNEL                )CLCC_DYNLIB_IMPORT(module, "clCreateKernel");
199     __oclCreateKernelsInProgram        = (PFNCLCREATEKERNELSINPROGRAM      )CLCC_DYNLIB_IMPORT(module, "clCreateKernelsInProgram");
200     __oclRetainKernel                  = (PFNCLRETAINKERNEL                )CLCC_DYNLIB_IMPORT(module, "clRetainKernel");
201     __oclReleaseKernel                 = (PFNCLRELEASEKERNEL               )CLCC_DYNLIB_IMPORT(module, "clReleaseKernel");
202     __oclSetKernelArg                  = (PFNCLSETKERNELARG                )CLCC_DYNLIB_IMPORT(module, "clSetKernelArg");
203     __oclGetKernelInfo                 = (PFNCLGETKERNELINFO               )CLCC_DYNLIB_IMPORT(module, "clGetKernelInfo");
204     __oclGetKernelWorkGroupInfo        = (PFNCLGETKERNELWORKGROUPINFO      )CLCC_DYNLIB_IMPORT(module, "clGetKernelWorkGroupInfo");
205     __oclWaitForEvents                 = (PFNCLWAITFOREVENTS               )CLCC_DYNLIB_IMPORT(module, "clWaitForEvents");
206     __oclGetEventInfo                  = (PFNCLGETEVENTINFO                )CLCC_DYNLIB_IMPORT(module, "clGetEventInfo");
207     __oclRetainEvent                   = (PFNCLRETAINEVENT                 )CLCC_DYNLIB_IMPORT(module, "clRetainEvent");
208     __oclReleaseEvent                  = (PFNCLRELEASEEVENT                )CLCC_DYNLIB_IMPORT(module, "clReleaseEvent");
209     __oclGetEventProfilingInfo         = (PFNCLGETEVENTPROFILINGINFO       )CLCC_DYNLIB_IMPORT(module, "clGetEventProfilingInfo");
210     __oclFlush                         = (PFNCLFLUSH                       )CLCC_DYNLIB_IMPORT(module, "clFlush");
211     __oclFinish                        = (PFNCLFINISH                      )CLCC_DYNLIB_IMPORT(module, "clFinish");
212     __oclEnqueueReadBuffer             = (PFNCLENQUEUEREADBUFFER           )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadBuffer");
213     __oclEnqueueWriteBuffer            = (PFNCLENQUEUEWRITEBUFFER          )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteBuffer");
214     __oclEnqueueCopyBuffer             = (PFNCLENQUEUECOPYBUFFER           )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBuffer");
215     __oclEnqueueReadImage              = (PFNCLENQUEUEREADIMAGE            )CLCC_DYNLIB_IMPORT(module, "clEnqueueReadImage");
216     __oclEnqueueWriteImage             = (PFNCLENQUEUEWRITEIMAGE           )CLCC_DYNLIB_IMPORT(module, "clEnqueueWriteImage");
217     __oclEnqueueCopyImage              = (PFNCLENQUEUECOPYIMAGE            )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImage");
218     __oclEnqueueCopyImageToBuffer      = (PFNCLENQUEUECOPYIMAGETOBUFFER    )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyImageToBuffer");
219     __oclEnqueueCopyBufferToImage      = (PFNCLENQUEUECOPYBUFFERTOIMAGE    )CLCC_DYNLIB_IMPORT(module, "clEnqueueCopyBufferToImage");
220     __oclEnqueueMapBuffer              = (PFNCLENQUEUEMAPBUFFER            )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapBuffer");
221     __oclEnqueueMapImage               = (PFNCLENQUEUEMAPIMAGE             )CLCC_DYNLIB_IMPORT(module, "clEnqueueMapImage");
222     __oclEnqueueUnmapMemObject         = (PFNCLENQUEUEUNMAPMEMOBJECT       )CLCC_DYNLIB_IMPORT(module, "clEnqueueUnmapMemObject");
223     __oclEnqueueNDRangeKernel          = (PFNCLENQUEUENDRANGEKERNEL        )CLCC_DYNLIB_IMPORT(module, "clEnqueueNDRangeKernel");
224     __oclEnqueueTask                   = (PFNCLENQUEUETASK                 )CLCC_DYNLIB_IMPORT(module, "clEnqueueTask");
225     __oclEnqueueNativeKernel           = (PFNCLENQUEUENATIVEKERNEL         )CLCC_DYNLIB_IMPORT(module, "clEnqueueNativeKernel");
226     __oclEnqueueMarker                 = (PFNCLENQUEUEMARKER               )CLCC_DYNLIB_IMPORT(module, "clEnqueueMarker");
227     __oclEnqueueWaitForEvents          = (PFNCLENQUEUEWAITFOREVENTS        )CLCC_DYNLIB_IMPORT(module, "clEnqueueWaitForEvents");
228     __oclEnqueueBarrier                = (PFNCLENQUEUEBARRIER              )CLCC_DYNLIB_IMPORT(module, "clEnqueueBarrier");
229     __oclGetExtensionFunctionAddress   = (PFNCLGETEXTENSIONFUNCTIONADDRESS )CLCC_DYNLIB_IMPORT(module, "clGetExtensionFunctionAddress");
230
231     return CLEW_SUCCESS;
232 }
233
234 //! \param error CL error code
235 //! \return a string representation of the error code
236 const char* clewErrorString(cl_int error)
237 {
238     static const char* strings[] =
239     {
240         // Error Codes
241           "CL_SUCCESS"                                  //   0
242         , "CL_DEVICE_NOT_FOUND"                         //  -1
243         , "CL_DEVICE_NOT_AVAILABLE"                     //  -2
244         , "CL_COMPILER_NOT_AVAILABLE"                   //  -3
245         , "CL_MEM_OBJECT_ALLOCATION_FAILURE"            //  -4
246         , "CL_OUT_OF_RESOURCES"                         //  -5
247         , "CL_OUT_OF_HOST_MEMORY"                       //  -6
248         , "CL_PROFILING_INFO_NOT_AVAILABLE"             //  -7
249         , "CL_MEM_COPY_OVERLAP"                         //  -8
250         , "CL_IMAGE_FORMAT_MISMATCH"                    //  -9
251         , "CL_IMAGE_FORMAT_NOT_SUPPORTED"               //  -10
252         , "CL_BUILD_PROGRAM_FAILURE"                    //  -11
253         , "CL_MAP_FAILURE"                              //  -12
254
255         , ""    //  -13
256         , ""    //  -14
257         , ""    //  -15
258         , ""    //  -16
259         , ""    //  -17
260         , ""    //  -18
261         , ""    //  -19
262
263         , ""    //  -20
264         , ""    //  -21
265         , ""    //  -22
266         , ""    //  -23
267         , ""    //  -24
268         , ""    //  -25
269         , ""    //  -26
270         , ""    //  -27
271         , ""    //  -28
272         , ""    //  -29
273
274         , "CL_INVALID_VALUE"                            //  -30
275         , "CL_INVALID_DEVICE_TYPE"                      //  -31
276         , "CL_INVALID_PLATFORM"                         //  -32
277         , "CL_INVALID_DEVICE"                           //  -33
278         , "CL_INVALID_CONTEXT"                          //  -34
279         , "CL_INVALID_QUEUE_PROPERTIES"                 //  -35
280         , "CL_INVALID_COMMAND_QUEUE"                    //  -36
281         , "CL_INVALID_HOST_PTR"                         //  -37
282         , "CL_INVALID_MEM_OBJECT"                       //  -38
283         , "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"          //  -39
284         , "CL_INVALID_IMAGE_SIZE"                       //  -40
285         , "CL_INVALID_SAMPLER"                          //  -41
286         , "CL_INVALID_BINARY"                           //  -42
287         , "CL_INVALID_BUILD_OPTIONS"                    //  -43
288         , "CL_INVALID_PROGRAM"                          //  -44
289         , "CL_INVALID_PROGRAM_EXECUTABLE"               //  -45
290         , "CL_INVALID_KERNEL_NAME"                      //  -46
291         , "CL_INVALID_KERNEL_DEFINITION"                //  -47
292         , "CL_INVALID_KERNEL"                           //  -48
293         , "CL_INVALID_ARG_INDEX"                        //  -49
294         , "CL_INVALID_ARG_VALUE"                        //  -50
295         , "CL_INVALID_ARG_SIZE"                         //  -51
296         , "CL_INVALID_KERNEL_ARGS"                      //  -52
297         , "CL_INVALID_WORK_DIMENSION"                   //  -53
298         , "CL_INVALID_WORK_GROUP_SIZE"                  //  -54
299         , "CL_INVALID_WORK_ITEM_SIZE"                   //  -55
300         , "CL_INVALID_GLOBAL_OFFSET"                    //  -56
301         , "CL_INVALID_EVENT_WAIT_LIST"                  //  -57
302         , "CL_INVALID_EVENT"                            //  -58
303         , "CL_INVALID_OPERATION"                        //  -59
304         , "CL_INVALID_GL_OBJECT"                        //  -60
305         , "CL_INVALID_BUFFER_SIZE"                      //  -61
306         , "CL_INVALID_MIP_LEVEL"                        //  -62
307         , "CL_INVALID_GLOBAL_WORK_SIZE"                 //  -63
308     };
309
310     return strings[-error];
311 }