Imported Upstream version 2.81
[platform/upstream/libbullet.git] / Demos / SharedOpenCL / btOpenCLUtils.cpp
1 /*\r
2 Bullet Continuous Collision Detection and Physics Library, http://bulletphysics.org\r
3 Copyright (C) 2006 - 2011 Sony Computer Entertainment Inc. \r
4 \r
5 This software is provided 'as-is', without any express or implied warranty.\r
6 In no event will the authors be held liable for any damages arising from the use of this software.\r
7 Permission is granted to anyone to use this software for any purpose, \r
8 including commercial applications, and to alter it and redistribute it freely, \r
9 subject to the following restrictions:\r
10 \r
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.\r
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.\r
13 3. This notice may not be removed or altered from any source distribution.\r
14 */\r
15 \r
16 //original author: Roman Ponomarev\r
17 //cleanup by Erwin Coumans\r
18 \r
19 #include <string.h>\r
20 \r
21 #include "btOpenCLUtils.h"\r
22 #include <stdio.h>\r
23 #include <stdlib.h>\r
24 \r
25 #define BT_MAX_CL_DEVICES 16 //who needs 16 devices?\r
26 //#define BT_USE_CACHE_DIR\r
27 #ifdef _WIN32\r
28 #include <Windows.h>\r
29 #endif //_WIN32\r
30 \r
31 #include <assert.h>\r
32 #define btAssert assert\r
33 \r
34 //Set the preferred platform vendor using the OpenCL SDK\r
35 static const char* spPlatformVendor =\r
36 #if defined(CL_PLATFORM_MINI_CL)\r
37 "MiniCL, SCEA";\r
38 #elif defined(CL_PLATFORM_AMD)\r
39 "Advanced Micro Devices, Inc.";\r
40 #elif defined(CL_PLATFORM_NVIDIA)\r
41 "NVIDIA Corporation";\r
42 #elif defined(CL_PLATFORM_INTEL)\r
43 "Intel(R) Corporation";\r
44 #else\r
45 "Unknown Vendor";\r
46 #endif\r
47 \r
48 #ifndef CL_PLATFORM_MINI_CL\r
49 #ifdef _WIN32\r
50 #include "CL/cl_gl.h"\r
51 #endif //_WIN32\r
52 #endif\r
53 \r
54 int btOpenCLUtils::getNumPlatforms(cl_int* pErrNum)\r
55 {\r
56         cl_uint numPlatforms=0;\r
57         cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);\r
58 \r
59         if(ciErrNum != CL_SUCCESS)\r
60         {\r
61                 if(pErrNum != NULL) \r
62                         *pErrNum = ciErrNum;\r
63         }\r
64         return numPlatforms;\r
65 }\r
66 \r
67 const char* btOpenCLUtils::getSdkVendorName()\r
68 {\r
69         return spPlatformVendor;\r
70 }\r
71 \r
72 cl_platform_id btOpenCLUtils::getPlatform(int platformIndex, cl_int* pErrNum)\r
73 {\r
74         cl_platform_id platform = 0;\r
75 \r
76         cl_uint numPlatforms;\r
77         cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);\r
78         \r
79         if (platformIndex>=0 && platformIndex<numPlatforms)\r
80         {\r
81                 cl_platform_id* platforms = new cl_platform_id[numPlatforms];\r
82                 ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);\r
83                 if(ciErrNum != CL_SUCCESS)\r
84                 {\r
85                         if(pErrNum != NULL) \r
86                                 *pErrNum = ciErrNum;\r
87                         return platform;\r
88                 }\r
89 \r
90                 platform = platforms[platformIndex];\r
91 \r
92                 delete[] platforms;\r
93         }\r
94 \r
95         return platform;\r
96 }\r
97 \r
98 void btOpenCLUtils::getPlatformInfo(cl_platform_id platform, btOpenCLPlatformInfo& platformInfo)\r
99 {\r
100         cl_int ciErrNum;\r
101 \r
102         ciErrNum = clGetPlatformInfo(   platform,CL_PLATFORM_VENDOR,BT_MAX_STRING_LENGTH,platformInfo.m_platformVendor,NULL);\r
103         oclCHECKERROR(ciErrNum,CL_SUCCESS);\r
104         ciErrNum = clGetPlatformInfo(   platform,CL_PLATFORM_NAME,BT_MAX_STRING_LENGTH,platformInfo.m_platformName,NULL);\r
105         oclCHECKERROR(ciErrNum,CL_SUCCESS);\r
106         ciErrNum = clGetPlatformInfo(   platform,CL_PLATFORM_VERSION,BT_MAX_STRING_LENGTH,platformInfo.m_platformVersion,NULL);\r
107         oclCHECKERROR(ciErrNum,CL_SUCCESS);\r
108 }\r
109 \r
110 cl_context btOpenCLUtils::createContextFromPlatform(cl_platform_id platform, cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC, int preferredDeviceIndex, int preferredPlatformIndex)\r
111 {\r
112         cl_context retContext = 0;\r
113         cl_int ciErrNum=0;\r
114 \r
115         /*     \r
116         * If we could find our platform, use it. Otherwise pass a NULL and get whatever the     \r
117         * implementation thinks we should be using.     \r
118         */\r
119         cl_context_properties cps[7] = {0,0,0,0,0,0,0};\r
120         cps[0] = CL_CONTEXT_PLATFORM;\r
121         cps[1] = (cl_context_properties)platform;\r
122         if (pGLContext && pGLDC)\r
123         {\r
124 #if defined(CL_PLATFORM_AMD) || defined(CL_PLATFORM_NVIDIA)\r
125                 cps[2] = CL_GL_CONTEXT_KHR;\r
126                 cps[3] = (cl_context_properties)pGLContext;\r
127                 cps[4] = CL_WGL_HDC_KHR;\r
128                 cps[5] = (cl_context_properties)pGLDC;\r
129 #endif\r
130         }\r
131 \r
132         cl_uint num_entries = BT_MAX_CL_DEVICES;\r
133         cl_device_id devices[BT_MAX_CL_DEVICES];\r
134 \r
135         cl_uint num_devices=-1;\r
136 \r
137         ciErrNum = clGetDeviceIDs(      \r
138                 platform,\r
139                 deviceType,\r
140                 num_entries,\r
141                 devices,\r
142                 &num_devices);\r
143 \r
144         cl_context_properties* cprops = (NULL == platform) ? NULL : cps;\r
145 \r
146         if (pGLContext)\r
147         {\r
148                 //search for the GPU that relates to the OpenCL context\r
149                 for (int i=0;i<num_devices;i++)\r
150                 {\r
151                         retContext = clCreateContext(cprops,1,&devices[i],NULL,NULL,&ciErrNum);\r
152                         if (ciErrNum==CL_SUCCESS)\r
153                                 break;\r
154                 }\r
155         }\r
156         else\r
157         {\r
158                 if (preferredDeviceIndex>=0 && preferredDeviceIndex<num_devices)\r
159                 {\r
160                         //create a context of the preferred device index\r
161                         retContext = clCreateContext(cprops,1,&devices[preferredDeviceIndex],NULL,NULL,&ciErrNum);\r
162                 } else\r
163                 {\r
164                         //create a context of all devices\r
165                         retContext = clCreateContext(cprops,num_devices,devices,NULL,NULL,&ciErrNum);\r
166                 }\r
167         }\r
168         if(pErrNum != NULL) \r
169         {\r
170                 *pErrNum = ciErrNum;\r
171         };\r
172 \r
173         return retContext;\r
174 }\r
175 \r
176 cl_context btOpenCLUtils::createContextFromType(cl_device_type deviceType, cl_int* pErrNum, void* pGLContext, void* pGLDC , int preferredDeviceIndex, int preferredPlatformIndex)\r
177 {\r
178         cl_uint numPlatforms;\r
179         cl_context retContext = 0;\r
180         \r
181         cl_int ciErrNum = clGetPlatformIDs(0, NULL, &numPlatforms);\r
182         if(ciErrNum != CL_SUCCESS)\r
183         {\r
184                 if(pErrNum != NULL) *pErrNum = ciErrNum;\r
185                 return NULL;\r
186         }\r
187         if(numPlatforms > 0)     \r
188         {        \r
189                 cl_platform_id* platforms = new cl_platform_id[numPlatforms];\r
190                 ciErrNum = clGetPlatformIDs(numPlatforms, platforms, NULL);\r
191                 if(ciErrNum != CL_SUCCESS)\r
192                 {\r
193                         if(pErrNum != NULL) *pErrNum = ciErrNum;\r
194                         return NULL;\r
195                 }\r
196                 int i;\r
197 \r
198 \r
199                 for ( i = 0; i < numPlatforms; ++i)         \r
200                 {            \r
201                         char pbuf[128];            \r
202                         ciErrNum = clGetPlatformInfo(   platforms[i],\r
203                                 CL_PLATFORM_VENDOR,                                       \r
204                                 sizeof(pbuf),                                       \r
205                                 pbuf,                                       \r
206                                 NULL);\r
207                         if(ciErrNum != CL_SUCCESS)\r
208                         {\r
209                                 if(pErrNum != NULL) *pErrNum = ciErrNum;\r
210                                 return NULL;\r
211                         }\r
212 \r
213                         if (preferredPlatformIndex>=0 && i==preferredPlatformIndex)\r
214                         {\r
215                                 cl_platform_id tmpPlatform = platforms[0];\r
216                                 platforms[0] = platforms[i];\r
217                                 platforms[i] = tmpPlatform;\r
218                                 break;\r
219                         } else\r
220                         {\r
221                                 if(!strcmp(pbuf, spPlatformVendor))\r
222                                 {\r
223                                         cl_platform_id tmpPlatform = platforms[0];\r
224                                         platforms[0] = platforms[i];\r
225                                         platforms[i] = tmpPlatform;\r
226                                         break;\r
227                                 }\r
228                         }\r
229                 }\r
230 \r
231                 for (i = 0; i < numPlatforms; ++i)         \r
232                 {\r
233                         cl_platform_id platform = platforms[i];\r
234                         assert(platform);\r
235 \r
236                         retContext = btOpenCLUtils::createContextFromPlatform(platform,deviceType,pErrNum,pGLContext,pGLDC,preferredDeviceIndex);\r
237 \r
238                         if (retContext)\r
239                         {\r
240 //                              printf("OpenCL platform details:\n");\r
241                                 btOpenCLPlatformInfo platformInfo;\r
242 \r
243                                 btOpenCLUtils::getPlatformInfo(platform, platformInfo);\r
244 \r
245                                 printf("  CL_PLATFORM_VENDOR: \t\t\t%s\n",platformInfo.m_platformVendor);\r
246                                 printf("  CL_PLATFORM_NAME: \t\t\t%s\n",platformInfo.m_platformName);\r
247                                 printf("  CL_PLATFORM_VERSION: \t\t\t%s\n",platformInfo.m_platformVersion);\r
248 \r
249                                 break;\r
250                         }\r
251                 }\r
252 \r
253                 delete[] platforms;    \r
254         }\r
255         return retContext;\r
256 }\r
257 \r
258 \r
259 //////////////////////////////////////////////////////////////////////////////\r
260 //! Gets the id of the nth device from the context\r
261 //!\r
262 //! @return the id or -1 when out of range\r
263 //! @param cxMainContext         OpenCL context\r
264 //! @param device_idx            index of the device of interest\r
265 //////////////////////////////////////////////////////////////////////////////\r
266 cl_device_id btOpenCLUtils::getDevice(cl_context cxMainContext, int deviceIndex)\r
267 {\r
268         size_t szParmDataBytes;\r
269         cl_device_id* cdDevices;\r
270 \r
271         // get the list of devices associated with context\r
272         clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);\r
273 \r
274         if( szParmDataBytes / sizeof(cl_device_id) < deviceIndex ) {\r
275                 return (cl_device_id)-1;\r
276         }\r
277 \r
278         cdDevices = (cl_device_id*) malloc(szParmDataBytes);\r
279 \r
280         clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);\r
281 \r
282         cl_device_id device = cdDevices[deviceIndex];\r
283         free(cdDevices);\r
284 \r
285         return device;\r
286 }\r
287 \r
288 int btOpenCLUtils::getNumDevices(cl_context cxMainContext)\r
289 {\r
290         size_t szParamDataBytes;\r
291         clGetContextInfo(cxMainContext, CL_CONTEXT_DEVICES, 0, NULL, &szParamDataBytes);\r
292         int device_count = (int) szParamDataBytes/ sizeof(cl_device_id);\r
293         return device_count;\r
294 }\r
295 \r
296 void btOpenCLUtils::printDeviceInfo(cl_device_id device)\r
297 {\r
298         btOpenCLDeviceInfo info;\r
299         getDeviceInfo(device,info);\r
300 \r
301         printf("  CL_DEVICE_NAME: \t\t\t%s\n", info.m_deviceName);\r
302         printf("  CL_DEVICE_VENDOR: \t\t\t%s\n", info.m_deviceVendor);\r
303         printf("  CL_DRIVER_VERSION: \t\t\t%s\n", info.m_driverVersion);\r
304 \r
305         if( info.m_deviceType & CL_DEVICE_TYPE_CPU )\r
306                 printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_CPU");\r
307         if( info.m_deviceType & CL_DEVICE_TYPE_GPU )\r
308                 printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_GPU");\r
309         if( info.m_deviceType & CL_DEVICE_TYPE_ACCELERATOR )\r
310                 printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_ACCELERATOR");\r
311         if( info.m_deviceType & CL_DEVICE_TYPE_DEFAULT )\r
312                 printf("  CL_DEVICE_TYPE:\t\t\t%s\n", "CL_DEVICE_TYPE_DEFAULT");\r
313 \r
314         printf("  CL_DEVICE_MAX_COMPUTE_UNITS:\t\t%u\n", info.m_computeUnits);\r
315         printf("  CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:\t%zu\n", info.m_workitemDims);\r
316         printf("  CL_DEVICE_MAX_WORK_ITEM_SIZES:\t%zu / %zu / %zu \n", info.m_workItemSize[0], info.m_workItemSize[1], info.m_workItemSize[2]);\r
317         printf("  CL_DEVICE_MAX_WORK_GROUP_SIZE:\t%zu\n", info.m_workgroupSize);\r
318         printf("  CL_DEVICE_MAX_CLOCK_FREQUENCY:\t%u MHz\n", info.m_clockFrequency);\r
319         printf("  CL_DEVICE_ADDRESS_BITS:\t\t%u\n", info.m_addressBits);\r
320         printf("  CL_DEVICE_MAX_MEM_ALLOC_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_maxMemAllocSize/ (1024 * 1024)));\r
321         printf("  CL_DEVICE_GLOBAL_MEM_SIZE:\t\t%u MByte\n", (unsigned int)(info.m_globalMemSize/ (1024 * 1024)));\r
322         printf("  CL_DEVICE_ERROR_CORRECTION_SUPPORT:\t%s\n", info.m_errorCorrectionSupport== CL_TRUE ? "yes" : "no");\r
323         printf("  CL_DEVICE_LOCAL_MEM_TYPE:\t\t%s\n", info.m_localMemType == 1 ? "local" : "global");\r
324         printf("  CL_DEVICE_LOCAL_MEM_SIZE:\t\t%u KByte\n", (unsigned int)(info.m_localMemSize / 1024));\r
325         printf("  CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:\t%u KByte\n", (unsigned int)(info.m_constantBufferSize / 1024));\r
326         if( info.m_queueProperties  & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE )\r
327                 printf("  CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE");    \r
328         if( info.m_queueProperties & CL_QUEUE_PROFILING_ENABLE )\r
329                 printf("  CL_DEVICE_QUEUE_PROPERTIES:\t\t%s\n", "CL_QUEUE_PROFILING_ENABLE");\r
330 \r
331         printf("  CL_DEVICE_IMAGE_SUPPORT:\t\t%u\n", info.m_imageSupport);\r
332 \r
333         printf("  CL_DEVICE_MAX_READ_IMAGE_ARGS:\t%u\n", info.m_maxReadImageArgs);\r
334         printf("  CL_DEVICE_MAX_WRITE_IMAGE_ARGS:\t%u\n", info.m_maxWriteImageArgs);\r
335         printf("\n  CL_DEVICE_IMAGE <dim>"); \r
336         printf("\t\t\t2D_MAX_WIDTH\t %zu\n", info.m_image2dMaxWidth);\r
337         printf("\t\t\t\t\t2D_MAX_HEIGHT\t %zu\n", info.m_image2dMaxHeight);\r
338         printf("\t\t\t\t\t3D_MAX_WIDTH\t %zu\n", info.m_image3dMaxWidth);\r
339         printf("\t\t\t\t\t3D_MAX_HEIGHT\t %zu\n", info.m_image3dMaxHeight);\r
340         printf("\t\t\t\t\t3D_MAX_DEPTH\t %zu\n", info.m_image3dMaxDepth);\r
341         if (info.m_deviceExtensions != 0) \r
342                 printf("\n  CL_DEVICE_EXTENSIONS:%s\n",info.m_deviceExtensions);\r
343         else \r
344                 printf("  CL_DEVICE_EXTENSIONS: None\n");\r
345         printf("  CL_DEVICE_PREFERRED_VECTOR_WIDTH_<t>\t"); \r
346         printf("CHAR %u, SHORT %u, INT %u,LONG %u, FLOAT %u, DOUBLE %u\n\n\n", \r
347                 info.m_vecWidthChar, info.m_vecWidthShort, info.m_vecWidthInt, info.m_vecWidthLong,info.m_vecWidthFloat, info.m_vecWidthDouble); \r
348 \r
349 \r
350 }\r
351 \r
352 void btOpenCLUtils::getDeviceInfo(cl_device_id device, btOpenCLDeviceInfo& info)\r
353 {\r
354 \r
355         // CL_DEVICE_NAME\r
356         clGetDeviceInfo(device, CL_DEVICE_NAME, BT_MAX_STRING_LENGTH, &info.m_deviceName, NULL);\r
357 \r
358         // CL_DEVICE_VENDOR\r
359         clGetDeviceInfo(device, CL_DEVICE_VENDOR, BT_MAX_STRING_LENGTH, &info.m_deviceVendor, NULL);\r
360 \r
361         // CL_DRIVER_VERSION\r
362         clGetDeviceInfo(device, CL_DRIVER_VERSION, BT_MAX_STRING_LENGTH, &info.m_driverVersion, NULL);\r
363 \r
364         // CL_DEVICE_INFO\r
365         clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &info.m_deviceType, NULL);\r
366 \r
367         // CL_DEVICE_MAX_COMPUTE_UNITS\r
368         clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(info.m_computeUnits), &info.m_computeUnits, NULL);\r
369 \r
370         // CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS\r
371         clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(info.m_workitemDims), &info.m_workitemDims, NULL);\r
372 \r
373         // CL_DEVICE_MAX_WORK_ITEM_SIZES\r
374         clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(info.m_workItemSize), &info.m_workItemSize, NULL);\r
375 \r
376         // CL_DEVICE_MAX_WORK_GROUP_SIZE\r
377         clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(info.m_workgroupSize), &info.m_workgroupSize, NULL);\r
378 \r
379         // CL_DEVICE_MAX_CLOCK_FREQUENCY\r
380         clGetDeviceInfo(device, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(info.m_clockFrequency), &info.m_clockFrequency, NULL);\r
381 \r
382         // CL_DEVICE_ADDRESS_BITS\r
383         clGetDeviceInfo(device, CL_DEVICE_ADDRESS_BITS, sizeof(info.m_addressBits), &info.m_addressBits, NULL);\r
384 \r
385         // CL_DEVICE_MAX_MEM_ALLOC_SIZE\r
386         clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(info.m_maxMemAllocSize), &info.m_maxMemAllocSize, NULL);\r
387 \r
388         // CL_DEVICE_GLOBAL_MEM_SIZE\r
389         clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(info.m_globalMemSize), &info.m_globalMemSize, NULL);\r
390 \r
391         // CL_DEVICE_ERROR_CORRECTION_SUPPORT\r
392         clGetDeviceInfo(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT, sizeof(info.m_errorCorrectionSupport), &info.m_errorCorrectionSupport, NULL);\r
393 \r
394         // CL_DEVICE_LOCAL_MEM_TYPE\r
395         clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(info.m_localMemType), &info.m_localMemType, NULL);\r
396 \r
397         // CL_DEVICE_LOCAL_MEM_SIZE\r
398         clGetDeviceInfo(device, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(info.m_localMemSize), &info.m_localMemSize, NULL);\r
399 \r
400         // CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE\r
401         clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(info.m_constantBufferSize), &info.m_constantBufferSize, NULL);\r
402 \r
403         // CL_DEVICE_QUEUE_PROPERTIES\r
404         clGetDeviceInfo(device, CL_DEVICE_QUEUE_PROPERTIES, sizeof(info.m_queueProperties), &info.m_queueProperties, NULL);\r
405 \r
406         // CL_DEVICE_IMAGE_SUPPORT\r
407         clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(info.m_imageSupport), &info.m_imageSupport, NULL);\r
408 \r
409         // CL_DEVICE_MAX_READ_IMAGE_ARGS\r
410         clGetDeviceInfo(device, CL_DEVICE_MAX_READ_IMAGE_ARGS, sizeof(info.m_maxReadImageArgs), &info.m_maxReadImageArgs, NULL);\r
411 \r
412         // CL_DEVICE_MAX_WRITE_IMAGE_ARGS\r
413         clGetDeviceInfo(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS, sizeof(info.m_maxWriteImageArgs), &info.m_maxWriteImageArgs, NULL);\r
414 \r
415         // CL_DEVICE_IMAGE2D_MAX_WIDTH, CL_DEVICE_IMAGE2D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_WIDTH, CL_DEVICE_IMAGE3D_MAX_HEIGHT, CL_DEVICE_IMAGE3D_MAX_DEPTH\r
416         clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &info.m_image2dMaxWidth, NULL);\r
417         clGetDeviceInfo(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT, sizeof(size_t), &info.m_image2dMaxHeight, NULL);\r
418         clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &info.m_image3dMaxWidth, NULL);\r
419         clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &info.m_image3dMaxHeight, NULL);\r
420         clGetDeviceInfo(device, CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &info.m_image3dMaxDepth, NULL);\r
421 \r
422         // CL_DEVICE_EXTENSIONS: get device extensions, and if any then parse & log the string onto separate lines\r
423         clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, BT_MAX_STRING_LENGTH, &info.m_deviceExtensions, NULL);\r
424 \r
425         // CL_DEVICE_PREFERRED_VECTOR_WIDTH_<type>\r
426         clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &info.m_vecWidthChar, NULL);\r
427         clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT, sizeof(cl_uint), &info.m_vecWidthShort, NULL);\r
428         clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT, sizeof(cl_uint), &info.m_vecWidthInt, NULL);\r
429         clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG, sizeof(cl_uint), &info.m_vecWidthLong, NULL);\r
430         clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT, sizeof(cl_uint), &info.m_vecWidthFloat, NULL);\r
431         clGetDeviceInfo(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE, sizeof(cl_uint), &info.m_vecWidthDouble, NULL);\r
432 }\r
433 \r
434 static char* strip1(char* name, const char* pattern,int* numOccurences=0)\r
435 {\r
436           size_t const patlen = strlen(pattern);\r
437           char * oriptr;\r
438           char * patloc;\r
439                 // find how many times the pattern occurs in the original string\r
440           for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)\r
441           {\r
442                   if (numOccurences)\r
443                           (*numOccurences)++;\r
444           }\r
445           return oriptr;\r
446 }\r
447 static const char* strip2(const char* name, const char* pattern,int* numOccurences=0)\r
448 {\r
449           size_t const patlen = strlen(pattern);\r
450           const char * oriptr;\r
451           const char * patloc;\r
452                 // find how many times the pattern occurs in the original string\r
453           for (oriptr = name; patloc = strstr(oriptr, pattern); oriptr = patloc + patlen)\r
454           {\r
455                   if (numOccurences)\r
456                           (*numOccurences)++;\r
457           }\r
458           return oriptr;\r
459 }\r
460 \r
461 cl_program btOpenCLUtils::compileCLProgramFromString(cl_context clContext, cl_device_id device, const char* kernelSource, cl_int* pErrNum, const char* additionalMacros)\r
462 {\r
463 \r
464         cl_int localErrNum;\r
465         size_t program_length = strlen(kernelSource);\r
466 \r
467         cl_program m_cpProgram = clCreateProgramWithSource(clContext, 1, (const char**)&kernelSource, &program_length, &localErrNum);\r
468         if (localErrNum!= CL_SUCCESS)\r
469         {\r
470                 if (pErrNum)\r
471                         *pErrNum = localErrNum;\r
472                 return 0;\r
473         }\r
474 \r
475         // Build the program with 'mad' Optimization option\r
476 \r
477 \r
478 #ifdef MAC\r
479         char* flags = "-cl-mad-enable -DMAC -DGUID_ARG";\r
480 #else\r
481         //const char* flags = "-DGUID_ARG= -fno-alias";\r
482         const char* flags = "-DGUID_ARG= ";\r
483 #endif\r
484 \r
485         char* compileFlags = new char[strlen(additionalMacros) + strlen(flags) + 5];\r
486         sprintf(compileFlags, "%s %s", flags, additionalMacros);\r
487         localErrNum = clBuildProgram(m_cpProgram, 1, &device, compileFlags, NULL, NULL);\r
488         if (localErrNum!= CL_SUCCESS)\r
489         {\r
490                 char *build_log;\r
491                 size_t ret_val_size;\r
492                 clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);\r
493                 build_log = new char[ret_val_size+1];\r
494                 clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);\r
495 \r
496                 // to be carefully, terminate with \0\r
497                 // there's no information in the reference whether the string is 0 terminated or not\r
498                 build_log[ret_val_size] = '\0';\r
499 \r
500 \r
501                 printf("Error in clBuildProgram, Line %u in file %s, Log: \n%s\n !!!\n\n", __LINE__, __FILE__, build_log);\r
502                 delete[] build_log;\r
503                 if (pErrNum)\r
504                         *pErrNum = localErrNum;\r
505                 return 0;\r
506         }\r
507         delete[] compileFlags;\r
508         return m_cpProgram;\r
509 }\r
510 \r
511 cl_program btOpenCLUtils::compileCLProgramFromFile(cl_context clContext, cl_device_id device, cl_int* pErrNum, const char* additionalMacros , const char* clFileNameForCaching)\r
512 {\r
513 \r
514         cl_program m_cpProgram=0;\r
515         cl_int status;\r
516         char binaryFileName[522];\r
517 \r
518         if (clFileNameForCaching)\r
519         {\r
520 #ifdef _WIN32   \r
521                 char deviceName[256];\r
522                 char driverVersion[256];\r
523                 clGetDeviceInfo(device, CL_DEVICE_NAME, 256, &deviceName, NULL);\r
524                 clGetDeviceInfo(device, CL_DRIVER_VERSION, 256, &driverVersion, NULL);\r
525 \r
526                 \r
527                 const char* strippedName = strip2(clFileNameForCaching,"\\");\r
528                 strippedName = strip2(strippedName,"/");\r
529 #ifdef BT_USE_CACHE_DIR\r
530                 sprintf_s(binaryFileName,"cache/%s.%s.%s.bin",strippedName, deviceName,driverVersion );\r
531 #else\r
532                 sprintf_s(binaryFileName,"%s.%s.%s.bin",strippedName, deviceName,driverVersion );\r
533 #endif\r
534                 \r
535         //printf("searching for %s\n", binaryFileName);\r
536 \r
537                 bool fileUpToDate = false;\r
538                 bool binaryFileValid=false;\r
539 \r
540                 FILETIME modtimeBinary; \r
541 \r
542 #ifdef BT_USE_CACHE_DIR\r
543                 CreateDirectory("cache",0);\r
544 #endif //BT_USE_CACHE_DIR\r
545                 {\r
546                         \r
547                         HANDLE binaryFileHandle = CreateFile(binaryFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);\r
548                         if (binaryFileHandle ==INVALID_HANDLE_VALUE)\r
549                         {\r
550                                 DWORD errorCode;\r
551                                 errorCode = GetLastError();\r
552                                 switch (errorCode)\r
553                                 {\r
554                                 case ERROR_FILE_NOT_FOUND:\r
555                                         {\r
556                                                 printf("\nCached file not found %s\n", binaryFileName);\r
557                                                 break;\r
558                                         }\r
559                                 case ERROR_PATH_NOT_FOUND:\r
560                                         {\r
561                                                 printf("\nCached file path not found %s\n", binaryFileName);\r
562                                                 break;\r
563                                         }\r
564                                 default:\r
565                                         {\r
566                                                 printf("\nFailed reading cached file with errorCode = %d\n", errorCode);\r
567                                         }\r
568                                 }\r
569                         } else\r
570                         {\r
571                                 if (GetFileTime(binaryFileHandle, NULL, NULL, &modtimeBinary)==0)\r
572                                 {\r
573                                         DWORD errorCode;\r
574                                         errorCode = GetLastError();\r
575                                         printf("\nGetFileTime errorCode = %d\n", errorCode);\r
576                                 } else\r
577                                 {\r
578                                         binaryFileValid = true;\r
579                                 }\r
580                                 CloseHandle(binaryFileHandle);\r
581                         }\r
582 \r
583                         if (binaryFileValid)\r
584                         {\r
585                                 HANDLE srcFileHandle = CreateFile(clFileNameForCaching,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);\r
586                                 if (srcFileHandle!=INVALID_HANDLE_VALUE)\r
587                                 {\r
588                                         FILETIME modtimeSrc; \r
589                                         if (GetFileTime(srcFileHandle, NULL, NULL, &modtimeSrc)==0)\r
590                                         {\r
591                                                 DWORD errorCode;\r
592                                                 errorCode = GetLastError();\r
593                                                 printf("\nGetFileTime errorCode = %d\n", errorCode);\r
594                                         }\r
595                                         if (  ( modtimeSrc.dwHighDateTime < modtimeBinary.dwHighDateTime)\r
596                                                 ||(( modtimeSrc.dwHighDateTime == modtimeBinary.dwHighDateTime)&&(modtimeSrc.dwLowDateTime <= modtimeBinary.dwLowDateTime)))\r
597                                         {\r
598                                                 fileUpToDate=true;\r
599                                         } else\r
600                                         {\r
601                                                 printf("\nCached binary file out-of-date (%s)\n",binaryFileName);\r
602                                         }\r
603                                         CloseHandle(srcFileHandle);\r
604                                 } \r
605                                 else\r
606                                 {\r
607                                         DWORD errorCode;\r
608                                         errorCode = GetLastError();\r
609                                         switch (errorCode)\r
610                                         {\r
611                                         case ERROR_FILE_NOT_FOUND:\r
612                                                 {\r
613                                                         printf("\nSrc file not found %s\n", clFileNameForCaching);\r
614                                                         break;\r
615                                                 }\r
616                                         case ERROR_PATH_NOT_FOUND:\r
617                                                 {\r
618                                                         printf("\nSrc path not found %s\n", clFileNameForCaching);\r
619                                                         break;\r
620                                                 }\r
621                                         default:\r
622                                                 {\r
623                                                         printf("\nnSrc file reading errorCode = %d\n", errorCode);\r
624                                                 }\r
625                                         }\r
626 \r
627                                         //we should make sure the src file exists so we can verify the timestamp with binary\r
628                                         fileUpToDate = false;\r
629                                 }\r
630                         }\r
631                         \r
632 \r
633                 }\r
634 \r
635                 if( fileUpToDate)\r
636                 {\r
637                         FILE* file = fopen(binaryFileName, "rb");\r
638                         if (file)\r
639                         {\r
640                                 fseek( file, 0L, SEEK_END );\r
641                                 size_t binarySize = ftell( file );\r
642                                 rewind( file );\r
643                                 char* binary = new char[binarySize];\r
644                                 fread( binary, sizeof(char), binarySize, file );\r
645                                 fclose( file );\r
646 \r
647                                 m_cpProgram = clCreateProgramWithBinary( clContext, 1,&device, &binarySize, (const unsigned char**)&binary, 0, &status );\r
648                                 btAssert( status == CL_SUCCESS );\r
649                                 status = clBuildProgram( m_cpProgram, 1, &device, additionalMacros, 0, 0 );\r
650                                 btAssert( status == CL_SUCCESS );\r
651 \r
652                                 if( status != CL_SUCCESS )\r
653                                 {\r
654                                         char *build_log;\r
655                                         size_t ret_val_size;\r
656                                         clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &ret_val_size);\r
657                                         build_log = new char[ret_val_size+1];\r
658                                         clGetProgramBuildInfo(m_cpProgram, device, CL_PROGRAM_BUILD_LOG, ret_val_size, build_log, NULL);\r
659                                         build_log[ret_val_size] = '\0';\r
660                                         printf("%s\n", build_log);\r
661                                         delete build_log;\r
662                                         btAssert(0);\r
663                                         m_cpProgram = 0;\r
664                                 }\r
665                                 delete[] binary;\r
666                         }\r
667                 }\r
668 #endif //_WIN32\r
669                 \r
670         }\r
671         \r
672         if (!m_cpProgram)\r
673         {\r
674                 \r
675                 FILE* file = fopen(clFileNameForCaching, "r");\r
676                 if (file)\r
677                 {\r
678                         fseek( file, 0L, SEEK_END );\r
679                         size_t fileSize= ftell( file );\r
680                         rewind( file );\r
681                         char* kernelSource2 = new char[fileSize+1];\r
682                         fread( kernelSource2, sizeof(char), fileSize, file );\r
683                         fclose( file );\r
684                         kernelSource2[fileSize]=0;\r
685                         int numOccurences = 0;\r
686                         ///patch/remove the MSTRINGIFY( and );\r
687                          char* kernelSource = strip1(kernelSource2,"MSTRINGIFY(",&numOccurences);\r
688                          int newlen = strlen(kernelSource);\r
689                         if (numOccurences)\r
690                         {\r
691                                 int i=newlen-1;\r
692 \r
693                                 for (;i>=0;i--)\r
694                                 {\r
695                                         if (kernelSource[i] == ';')\r
696                                         {\r
697                                                 kernelSource[i] = 0;//' ';\r
698                                                 break;\r
699                                         }\r
700                                 }\r
701                                 for (;i>=0;i--)\r
702                                 {\r
703                                         if (kernelSource[i] == ')')\r
704                                         {\r
705                                                 kernelSource[i] = 0;//' ';\r
706                                                 break;\r
707                                         }\r
708                                 }\r
709                         }\r
710                 \r
711                         m_cpProgram = compileCLProgramFromString(clContext,device,kernelSource,pErrNum,additionalMacros);\r
712                         \r
713                         if( clFileNameForCaching )\r
714                         {       //      write to binary\r
715 \r
716                                 cl_uint numAssociatedDevices;\r
717                                 status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &numAssociatedDevices, 0 );\r
718                                 btAssert( status == CL_SUCCESS );\r
719                                 if (numAssociatedDevices==1)\r
720                                 {\r
721 \r
722                                         size_t binarySize;\r
723                                         status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binarySize, 0 );\r
724                                         btAssert( status == CL_SUCCESS );\r
725 \r
726                                         char* binary = new char[binarySize];\r
727 \r
728                                         status = clGetProgramInfo( m_cpProgram, CL_PROGRAM_BINARIES, sizeof(char*), &binary, 0 );\r
729                                         btAssert( status == CL_SUCCESS );\r
730 \r
731                                         {\r
732                                                 FILE* file = fopen(binaryFileName, "wb");\r
733                                                 if (file)\r
734                                                 {\r
735                                                         fwrite( binary, sizeof(char), binarySize, file );\r
736                                                         fclose( file );\r
737                                                 } else\r
738                                                 {\r
739                                                         printf("cannot write file %s\n", binaryFileName);\r
740                                                 }\r
741                                         }\r
742 \r
743                                         delete [] binary;\r
744                                 }\r
745                         }\r
746                 }\r
747         }\r
748 \r
749         return m_cpProgram;\r
750 }\r
751 \r
752 \r
753 cl_kernel btOpenCLUtils::compileCLKernelFromString(cl_context clContext, cl_device_id device, const char* kernelSource, const char* kernelName, cl_int* pErrNum, cl_program prog, const char* additionalMacros )\r
754 {\r
755         printf("compiling kernel %s ",kernelName);\r
756         cl_kernel kernel;\r
757         cl_int localErrNum;\r
758         //size_t program_length = strlen(kernelSource);\r
759 \r
760 \r
761         cl_program m_cpProgram = prog;\r
762         if (!m_cpProgram)\r
763         {\r
764                 m_cpProgram = compileCLProgramFromString(clContext,device,kernelSource,pErrNum, additionalMacros);\r
765         }\r
766 \r
767 \r
768         // Create the kernel\r
769         kernel = clCreateKernel(m_cpProgram, kernelName, &localErrNum);\r
770         if (localErrNum != CL_SUCCESS)\r
771         {\r
772                 printf("Error in clCreateKernel, Line %u in file %s, cannot find kernel function %s !!!\n\n", __LINE__, __FILE__, kernelName);\r
773                 if (pErrNum)\r
774                         *pErrNum = localErrNum;\r
775                 return 0;\r
776         }\r
777 \r
778         if (!prog && m_cpProgram)\r
779         {\r
780                 clReleaseProgram(m_cpProgram);\r
781         }\r
782         printf("ready. \n");\r
783 \r
784 \r
785         if (pErrNum)\r
786                         *pErrNum = CL_SUCCESS;\r
787         return kernel;\r
788 \r
789 }\r