clutils.cpp 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398
  1. /****************************************************************************\
  2. * Copyright (c) 2011, Advanced Micro Devices, Inc. *
  3. * All rights reserved. *
  4. * *
  5. * Redistribution and use in source and binary forms, with or without *
  6. * modification, are permitted provided that the following conditions *
  7. * are met: *
  8. * *
  9. * Redistributions of source code must retain the above copyright notice, *
  10. * this list of conditions and the following disclaimer. *
  11. * *
  12. * Redistributions in binary form must reproduce the above copyright notice, *
  13. * this list of conditions and the following disclaimer in the documentation *
  14. * and/or other materials provided with the distribution. *
  15. * *
  16. * Neither the name of the copyright holder nor the names of its contributors *
  17. * may be used to endorse or promote products derived from this software *
  18. * without specific prior written permission. *
  19. * *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
  21. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
  22. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR *
  23. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR *
  24. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
  25. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
  27. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
  28. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
  29. * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
  30. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
  31. * *
  32. * If you use the software (in whole or in part), you shall adhere to all *
  33. * applicable U.S., European, and other export laws, including but not *
  34. * limited to the U.S. Export Administration Regulations (“EAR”), (15 C.F.R. *
  35. * Sections 730 through 774), and E.U. Council Regulation (EC) No 1334/2000 *
  36. * of 22 June 2000. Further, pursuant to Section 740.6 of the EAR, you *
  37. * hereby certify that, except pursuant to a license granted by the United *
  38. * States Department of Commerce Bureau of Industry and Security or as *
  39. * otherwise permitted pursuant to a License Exception under the U.S. Export *
  40. * Administration Regulations ("EAR"), you will not (1) export, re-export or *
  41. * release to a national of a country in Country Groups D:1, E:1 or E:2 any *
  42. * restricted technology, software, or source code you receive hereunder, *
  43. * or (2) export to Country Groups D:1, E:1 or E:2 the direct product of such *
  44. * technology or software, if such foreign produced direct product is subject *
  45. * to national security controls as identified on the Commerce Control List *
  46. *(currently found in Supplement 1 to Part 774 of EAR). For the most current *
  47. * Country Group listings, or for additional information about the EAR or *
  48. * your obligations under those regulations, please refer to the U.S. Bureau *
  49. * of Industry and Security’s website at http://www.bis.doc.gov/. *
  50. \****************************************************************************/
  51. #include <stdlib.h>
  52. #include <stdio.h>
  53. #include <string.h>
  54. #include <math.h>
  55. #include <CL/cl.h>
  56. #include "clutils.h"
  57. #include "utils.h"
  58. // The following variables have file scope to simplify
  59. // the utility functions
  60. //! All discoverable OpenCL platforms
  61. static cl_platform_id* platforms = NULL;
  62. static cl_uint numPlatforms;
  63. //! All discoverable OpenCL devices (one pointer per platform)
  64. static cl_device_id** devices = NULL;
  65. static cl_uint* numDevices;
  66. //! The chosen OpenCL platform
  67. static cl_platform_id platform = NULL;
  68. //! The chosen OpenCL device
  69. static cl_device_id device = NULL;
  70. //! OpenCL context
  71. static cl_context context = NULL;
  72. //! OpenCL command queue
  73. static cl_command_queue commandQueue = NULL;
  74. static cl_command_queue commandQueueProf = NULL;
  75. static cl_command_queue commandQueueNoProf = NULL;
  76. //! Global status of events
  77. static bool eventsEnabled = false;
  78. //-------------------------------------------------------
  79. // Initialization and Cleanup
  80. //-------------------------------------------------------
  81. //! Initialize OpenCl environment on one device
  82. /*!
  83. Init function for one device. Looks for supported devices and creates a context
  84. \return returns a context initialized
  85. */
  86. cl_context cl_init(char devicePreference)
  87. {
  88. cl_int status;
  89. // Discover and populate the platforms
  90. status = clGetPlatformIDs(0, NULL, &numPlatforms);
  91. cl_errChk(status, "Getting platform IDs", true);
  92. if (numPlatforms > 0)
  93. {
  94. // Get all the platforms
  95. platforms = (cl_platform_id*)alloc(numPlatforms *
  96. sizeof(cl_platform_id));
  97. status = clGetPlatformIDs(numPlatforms, platforms, NULL);
  98. cl_errChk(status, "Getting platform IDs", true);
  99. }
  100. else
  101. {
  102. // If no platforms are available, we shouldn't continue
  103. printf("No OpenCL platforms found\n");
  104. exit(-1);
  105. }
  106. // Allocate space for the device lists and lengths
  107. numDevices = (cl_uint*)alloc(sizeof(cl_uint)*numPlatforms);
  108. devices = (cl_device_id**)alloc(sizeof(cl_device_id*)*numPlatforms);
  109. // If a device preference was supplied, we'll limit the search of devices
  110. // based on type
  111. cl_device_type deviceType = CL_DEVICE_TYPE_ALL;
  112. if(devicePreference == 'c') {
  113. deviceType = CL_DEVICE_TYPE_CPU;
  114. }
  115. if(devicePreference == 'g') {
  116. deviceType = CL_DEVICE_TYPE_GPU;
  117. }
  118. // Traverse the platforms array printing information and
  119. // populating devices
  120. for(unsigned int i = 0; i < numPlatforms ; i++)
  121. {
  122. // Print out some basic info about the platform
  123. char* platformName = NULL;
  124. char* platformVendor = NULL;
  125. platformName = cl_getPlatformName(platforms[i]);
  126. platformVendor = cl_getPlatformVendor(platforms[i]);
  127. status = clGetDeviceIDs(platforms[i], deviceType, 0, NULL, &numDevices[i]);
  128. cl_errChk(status, "Getting device IDs", false);
  129. if(status != CL_SUCCESS) {
  130. printf("This is a known NVIDIA bug (if platform == AMD then die)\n");
  131. printf("Setting number of devices to 0 and continuing\n");
  132. numDevices[i] = 0;
  133. }
  134. printf("Platform %d (%d devices):\n", i, numDevices[i]);
  135. printf("\tName: %s\n", platformName);
  136. printf("\tVendor: %s\n", platformVendor);
  137. free(platformName);
  138. free(platformVendor);
  139. // Populate OpenCL devices if any exist
  140. if(numDevices[i] != 0)
  141. {
  142. // Allocate an array of devices of size "numDevices"
  143. devices[i] = (cl_device_id*)alloc(sizeof(cl_device_id)*numDevices[i]);
  144. // Populate Arrray with devices
  145. status = clGetDeviceIDs(platforms[i], deviceType, numDevices[i],
  146. devices[i], NULL);
  147. cl_errChk(status, "Getting device IDs", true);
  148. }
  149. // Print some information about each device
  150. for( unsigned int j = 0; j < numDevices[i]; j++)
  151. {
  152. char* deviceName = NULL;
  153. char* deviceVendor = NULL;
  154. printf("\tDevice %d:\n", j);
  155. deviceName = cl_getDeviceName(devices[i][j]);
  156. deviceVendor = cl_getDeviceVendor(devices[i][j]);
  157. printf("\t\tName: %s\n", deviceName);
  158. printf("\t\tVendor: %s\n", deviceVendor);
  159. free(deviceName);
  160. free(deviceVendor);
  161. }
  162. }
  163. // Hard-code in the platform/device to use, or uncomment 'scanf'
  164. // to decide at runtime
  165. cl_uint chosen_platform, chosen_device;
  166. // UNCOMMENT the following two lines to manually select device each time
  167. //printf("Enter Platform and Device No (Seperated by Space) \n");
  168. //scanf("%d %d", &chosen_platform, &chosen_device);
  169. chosen_platform = 0;
  170. chosen_device = 0;
  171. printf("Using Platform %d, Device %d \n", chosen_platform, chosen_device);
  172. // Do a sanity check of platform/device selection
  173. if(chosen_platform >= numPlatforms ||
  174. chosen_device >= numDevices[chosen_platform]) {
  175. printf("Invalid platform/device combination\n");
  176. exit(-1);
  177. }
  178. // Set the selected platform and device
  179. platform = platforms[chosen_platform];
  180. device = devices[chosen_platform][chosen_device];
  181. // Create the context
  182. cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM,
  183. (cl_context_properties)(platform), 0};
  184. context = clCreateContext(cps, 1, &device, NULL, NULL, &status);
  185. cl_errChk(status, "Creating context", true);
  186. // Create the command queue
  187. commandQueueProf = clCreateCommandQueue(context, device,
  188. CL_QUEUE_PROFILING_ENABLE, &status);
  189. cl_errChk(status, "creating command queue", true);
  190. commandQueueNoProf = clCreateCommandQueue(context, device, 0, &status);
  191. cl_errChk(status, "creating command queue", true);
  192. if(eventsEnabled) {
  193. printf("Profiling enabled\n");
  194. commandQueue = commandQueueProf;
  195. }
  196. else {
  197. printf("Profiling disabled\n");
  198. commandQueue = commandQueueNoProf;
  199. }
  200. return context;
  201. }
  202. cl_context cl_init_context(int platform_id, int device_id, int quiet, int use_gpu) {
  203. int printInfo=1;
  204. if (platform_id >= 0 && device_id >= 0) printInfo = 0;
  205. cl_int status;
  206. // Used to iterate through the platforms and devices, respectively
  207. cl_uint numPlatforms;
  208. cl_uint numDevices;
  209. // Prepare the device type on the basis of what received as argument, in this
  210. // way we can specialize the code
  211. cl_device_type device_type = use_gpu ? CL_DEVICE_TYPE_GPU : CL_DEVICE_TYPE_CPU;
  212. // These will hold the platform and device we select (can potentially be
  213. // multiple, but we're just doing one for now)
  214. // cl_platform_id platform = NULL;
  215. status = clGetPlatformIDs(0, NULL, &numPlatforms);
  216. if (printInfo) printf("Number of platforms detected:%d\n", numPlatforms);
  217. // Print some information about the available platforms
  218. cl_platform_id *platforms = NULL;
  219. cl_device_id * devices = NULL;
  220. if (numPlatforms > 0)
  221. {
  222. // get all the platforms
  223. platforms = (cl_platform_id*)malloc(numPlatforms *
  224. sizeof(cl_platform_id));
  225. status = clGetPlatformIDs(numPlatforms, platforms, NULL);
  226. // Traverse the platforms array
  227. if (printInfo) printf("Checking For OpenCl Compatible Devices\n");
  228. for(unsigned int i = 0; i < numPlatforms ; i++)
  229. {
  230. char pbuf[100];
  231. if (printInfo) printf("Platform %d:\t", i);
  232. status = clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR,
  233. sizeof(pbuf), pbuf, NULL);
  234. if (printInfo) printf("Vendor: %s\n", pbuf);
  235. //unsigned int numDevices;
  236. status = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
  237. if(cl_errChk(status, "checking for devices",true))
  238. exit(1);
  239. if(numDevices == 0) {
  240. printf("There are no devices for Platform %d\n",i);
  241. exit(0);
  242. }
  243. else
  244. {
  245. if (printInfo) printf("\tNo of devices for Platform %d is %u\n",i, numDevices);
  246. //! Allocate an array of devices of size "numDevices"
  247. devices = (cl_device_id*)malloc(sizeof(cl_device_id)*numDevices);
  248. //! Populate Arrray with devices
  249. status = clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, numDevices,
  250. devices, NULL);
  251. if(cl_errChk(status, "getting device IDs",true)) {
  252. exit(1);
  253. }
  254. }
  255. for( unsigned int j = 0; j < numDevices; j++)
  256. {
  257. char dbuf[100];
  258. char deviceStr[100];
  259. if (printInfo) printf("\tDevice: %d\t", j);
  260. status = clGetDeviceInfo(devices[j], CL_DEVICE_VENDOR, sizeof(dbuf),
  261. deviceStr, NULL);
  262. cl_errChk(status, "Getting Device Info\n",true);
  263. if (printInfo) printf("Vendor: %s", deviceStr);
  264. status = clGetDeviceInfo(devices[j], CL_DEVICE_NAME, sizeof(dbuf),
  265. dbuf, NULL);
  266. if (printInfo) printf("\n\t\tName: %s\n", dbuf);
  267. }
  268. }
  269. }
  270. else
  271. {
  272. // If no platforms are available, we're sunk!
  273. printf("No OpenCL platforms found\n");
  274. exit(0);
  275. }
  276. int platform_touse;
  277. unsigned int device_touse;
  278. if (printInfo) printf("Enter Platform and Device No (Seperated by Space) \n");
  279. if (printInfo) scanf("%d %d", &platform_touse, &device_touse);
  280. else {
  281. platform_touse = platform_id;
  282. device_touse = device_id;
  283. }
  284. if (!quiet) printf("Using Platform %d \t Device No %d \n",platform_touse, device_touse);
  285. //! Recheck how many devices does our chosen platform have
  286. status = clGetDeviceIDs(platforms[platform_touse], CL_DEVICE_TYPE_ALL, 0, NULL, &numDevices);
  287. if(device_touse > numDevices)
  288. {
  289. printf("Invalid Device Number\n");
  290. exit(1);
  291. }
  292. //! Populate devices array with all the visible devices of our chosen platform
  293. devices = (cl_device_id *)malloc(sizeof(cl_device_id)*numDevices);
  294. status = clGetDeviceIDs(platforms[platform_touse],
  295. CL_DEVICE_TYPE_ALL, numDevices,
  296. devices, NULL);
  297. if(cl_errChk(status,"Error in Getting Devices\n",true)) exit(1);
  298. //!Check if Device requested is a CPU or a GPU
  299. cl_device_type dtype;
  300. device = devices[device_touse];
  301. status = clGetDeviceInfo(devices[device_touse],
  302. CL_DEVICE_TYPE,
  303. sizeof(dtype),
  304. (void *)&dtype,
  305. NULL);
  306. if(cl_errChk(status,"Error in Getting Device Info\n",true)) exit(1);
  307. if(dtype == CL_DEVICE_TYPE_GPU) {
  308. if (!quiet) printf("Creating GPU Context\n\n");
  309. }
  310. else if (dtype == CL_DEVICE_TYPE_CPU) {
  311. if (!quiet) printf("Creating CPU Context\n\n");
  312. }
  313. else perror("This Context Type Not Supported\n");
  314. cl_context_properties cps[3] = {CL_CONTEXT_PLATFORM,
  315. (cl_context_properties)(platforms[platform_touse]), 0};
  316. cl_context_properties *cprops = cps;
  317. context = clCreateContextFromType(
  318. cprops, (cl_device_type)dtype,
  319. NULL, NULL, &status);
  320. if(cl_errChk(status, "creating Context",true)) {
  321. exit(1);
  322. }
  323. #define PROFILING
  324. #ifdef PROFILING
  325. commandQueue = clCreateCommandQueue(context,
  326. devices[device_touse], CL_QUEUE_PROFILING_ENABLE, &status);
  327. #else
  328. clCommandQueue = clCreateCommandQueue(clGPUContext,
  329. devices[device_touse], NULL, &status);
  330. #endif // PROFILING
  331. if(cl_errChk(status, "creating command queue",true)) {
  332. exit(1);
  333. }
  334. return context;
  335. }
  336. /*!
  337. Release all resources that the user doesn't have access to.
  338. */
  339. void cl_cleanup()
  340. {
  341. // Free the command queue
  342. if(commandQueue) {
  343. clReleaseCommandQueue(commandQueue);
  344. }
  345. // Free the context
  346. if(context) {
  347. clReleaseContext(context);
  348. }
  349. free(devices);
  350. free(numDevices);
  351. // Free the platforms
  352. free(platforms);
  353. }
  354. //! Release a kernel object
  355. /*!
  356. \param mem The kernel object to release
  357. */
  358. void cl_freeKernel(cl_kernel kernel)
  359. {
  360. cl_int status;
  361. if(kernel != NULL) {
  362. status = clReleaseKernel(kernel);
  363. cl_errChk(status, "Releasing kernel object", true);
  364. }
  365. }
  366. //! Release memory allocated on the device
  367. /*!
  368. \param mem The device pointer to release
  369. */
  370. void cl_freeMem(cl_mem mem)
  371. {
  372. cl_int status;
  373. if(mem != NULL) {
  374. status = clReleaseMemObject(mem);
  375. cl_errChk(status, "Releasing mem object", true);
  376. }
  377. }
  378. //! Release a program object
  379. /*!
  380. \param mem The program object to release
  381. */
  382. void cl_freeProgram(cl_program program)
  383. {
  384. cl_int status;
  385. if(program != NULL) {
  386. status = clReleaseProgram(program);
  387. cl_errChk(status, "Releasing program object", true);
  388. }
  389. }
  390. //! Returns a reference to the command queue
  391. /*!
  392. Returns a reference to the command queue \n
  393. Used for any OpenCl call that needs the command queue declared in clutils.cpp
  394. */
  395. cl_command_queue cl_getCommandQueue()
  396. {
  397. return commandQueue;
  398. }
  399. //-------------------------------------------------------
  400. // Synchronization functions
  401. //-------------------------------------------------------
  402. /*!
  403. Wait till all pending commands in queue are finished
  404. */
  405. void cl_sync()
  406. {
  407. clFinish(commandQueue);
  408. }
  409. //-------------------------------------------------------
  410. // Memory allocation
  411. //-------------------------------------------------------
  412. //! Allocate a buffer on a device
  413. /*!
  414. \param mem_size Size of memory in bytes
  415. \param flags Optional cl_mem_flags
  416. \return Returns a cl_mem object that points to device memory
  417. */
  418. cl_mem cl_allocBuffer(size_t mem_size, cl_mem_flags flags)
  419. {
  420. cl_mem mem;
  421. cl_int status;
  422. /*!
  423. Logging information for keeping track of device memory
  424. */
  425. static int allocationCount = 1;
  426. static size_t allocationSize = 0;
  427. allocationCount++;
  428. allocationSize += mem_size;
  429. mem = clCreateBuffer(context, flags, mem_size, NULL, &status);
  430. cl_errChk(status, "creating buffer", true);
  431. return mem;
  432. }
  433. //! Allocate constant memory on device
  434. /*!
  435. \param mem_size Size of memory in bytes
  436. \param host_ptr Host pointer that contains the data
  437. \return Returns a cl_mem object that points to device memory
  438. */
  439. cl_mem cl_allocBufferConst(size_t mem_size, void* host_ptr)
  440. {
  441. cl_mem mem;
  442. cl_int status;
  443. mem = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
  444. mem_size, host_ptr, &status);
  445. cl_errChk(status, "Error creating const mem buffer", true);
  446. return mem;
  447. }
  448. //! Allocate a buffer on device pinning the host memory at host_ptr
  449. /*!
  450. \param mem_size Size of memory in bytes
  451. \return Returns a cl_mem object that points to pinned memory on the host
  452. */
  453. cl_mem cl_allocBufferPinned(size_t mem_size)
  454. {
  455. cl_mem mem;
  456. cl_int status;
  457. mem = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR,
  458. mem_size, NULL, &status);
  459. cl_errChk(status, "Error allocating pinned memory", true);
  460. return mem;
  461. }
  462. //! Allocate an image on a device
  463. /*!
  464. \param height Number of rows in the image
  465. \param width Number of columns in the image
  466. \param elemSize Size of the elements in the image
  467. \param flags Optional cl_mem_flags
  468. \return Returns a cl_mem object that points to device memory
  469. */
  470. cl_mem cl_allocImage(size_t height, size_t width, char type, cl_mem_flags flags)
  471. {
  472. cl_mem mem;
  473. cl_int status;
  474. size_t elemSize = 0;
  475. cl_image_format format;
  476. format.image_channel_order = CL_R;
  477. switch(type) {
  478. case 'f':
  479. elemSize = sizeof(float);
  480. format.image_channel_data_type = CL_FLOAT;
  481. break;
  482. case 'i':
  483. elemSize = sizeof(int);
  484. format.image_channel_data_type = CL_SIGNED_INT32;
  485. break;
  486. default:
  487. printf("Error creating image: Unsupported image type.\n");
  488. exit(-1);
  489. }
  490. /*!
  491. Logging information for keeping track of device memory
  492. */
  493. static int allocationCount = 1;
  494. static size_t allocationSize = 0;
  495. allocationCount++;
  496. allocationSize += height*width*elemSize;
  497. // Create the image
  498. mem = clCreateImage2D(context, flags, &format, width, height, 0, NULL, &status);
  499. //cl_errChk(status, "creating image", true);
  500. if(status != CL_SUCCESS) {
  501. printf("Error creating image: Images may not be supported for this device.\n");
  502. printSupportedImageFormats();
  503. getchar();
  504. exit(-1);
  505. }
  506. return mem;
  507. }
  508. //-------------------------------------------------------
  509. // Data transfers
  510. //-------------------------------------------------------
  511. // Copy and map a buffer
  512. void* cl_copyAndMapBuffer(cl_mem dst, cl_mem src, size_t size) {
  513. void* ptr; // Pointer to the pinned memory that will be returned
  514. cl_copyBufferToBuffer(dst, src, size);
  515. ptr = cl_mapBuffer(dst, size, CL_MAP_READ);
  516. return ptr;
  517. }
  518. // Copy a buffer
  519. void cl_copyBufferToBuffer(cl_mem dst, cl_mem src, size_t size)
  520. {
  521. cl_int status;
  522. status = clEnqueueCopyBuffer(commandQueue, src, dst, 0, 0, size, 0, NULL,
  523. NULL);
  524. cl_errChk(status, "Copying buffer", true);
  525. }
  526. //! Copy a buffer to the device
  527. /*!
  528. \param dst Valid device pointer
  529. \param src Host pointer that contains the data
  530. \param mem_size Size of data to copy
  531. \param blocking Blocking or non-blocking operation
  532. */
  533. void cl_copyBufferToDevice(cl_mem dst, void* src, size_t mem_size, cl_bool blocking)
  534. {
  535. cl_int status;
  536. status = clEnqueueWriteBuffer(commandQueue, dst, blocking, 0,
  537. mem_size, src, 0, NULL, NULL);
  538. cl_errChk(status, "Writing buffer", true);
  539. }
  540. //! Copy a buffer to the host
  541. /*!
  542. \param dst Valid host pointer
  543. \param src Device pointer that contains the data
  544. \param mem_size Size of data to copy
  545. \param blocking Blocking or non-blocking operation
  546. */
  547. void cl_copyBufferToHost(void* dst, cl_mem src, size_t mem_size, cl_bool blocking)
  548. {
  549. cl_int status;
  550. status = clEnqueueReadBuffer(commandQueue, src, blocking, 0,
  551. mem_size, dst, 0, NULL, NULL);
  552. cl_errChk(status, "Reading buffer", true);
  553. }
  554. //! Copy a buffer to a 2D image
  555. /*!
  556. \param src Valid device buffer
  557. \param dst Empty device image
  558. \param mem_size Size of data to copy
  559. */
  560. void cl_copyBufferToImage(cl_mem buffer, cl_mem image, int height, int width)
  561. {
  562. size_t origin[3] = {0, 0, 0};
  563. size_t region[3] = {width, height, 1};
  564. cl_int status;
  565. status = clEnqueueCopyBufferToImage(commandQueue, buffer, image, 0,
  566. origin, region, 0, NULL, NULL);
  567. cl_errChk(status, "Copying buffer to image", true);
  568. }
  569. // Copy data to an image on the device
  570. /*!
  571. \param dst Valid device pointer
  572. \param src Host pointer that contains the data
  573. \param height Height of the image
  574. \param width Width of the image
  575. */
  576. void cl_copyImageToDevice(cl_mem dst, void* src, size_t height, size_t width)
  577. {
  578. cl_int status;
  579. size_t origin[3] = {0, 0, 0};
  580. size_t region[3] = {width, height, 1};
  581. status = clEnqueueWriteImage(commandQueue, dst, CL_TRUE, origin,
  582. region, 0, 0, src, 0, NULL, NULL);
  583. cl_errChk(status, "Writing image", true);
  584. }
  585. //! Copy an image to the host
  586. /*!
  587. \param dst Valid host pointer
  588. \param src Device pointer that contains the data
  589. \param height Height of the image
  590. \param width Width of the image
  591. */
  592. void cl_copyImageToHost(void* dst, cl_mem src, size_t height, size_t width)
  593. {
  594. cl_int status;
  595. size_t origin[3] = {0, 0, 0};
  596. size_t region[3] = {width, height, 1};
  597. status = clEnqueueReadImage(commandQueue, src, CL_TRUE, origin,
  598. region, 0, 0, dst, 0, NULL, NULL);
  599. cl_errChk(status, "Reading image", true);
  600. }
  601. //! Map a buffer into a host address
  602. /*!
  603. \param mem cl_mem object
  604. \param mem_size Size of memory in bytes
  605. \param flags Optional cl_mem_flags
  606. \return Returns a host pointer that points to the mapped region
  607. */
  608. void *cl_mapBuffer(cl_mem mem, size_t mem_size, cl_mem_flags flags)
  609. {
  610. cl_int status;
  611. void *ptr;
  612. ptr = (void *)clEnqueueMapBuffer(commandQueue, mem, CL_TRUE, flags,
  613. 0, mem_size, 0, NULL, NULL, &status);
  614. cl_errChk(status, "Error mapping a buffer", true);
  615. return ptr;
  616. }
  617. //! Unmap a buffer or image
  618. /*!
  619. \param mem cl_mem object
  620. \param ptr A host pointer that points to the mapped region
  621. */
  622. void cl_unmapBuffer(cl_mem mem, void *ptr)
  623. {
  624. // TODO It looks like AMD doesn't support profiling unmapping yet. Leaving the
  625. // commented code here until it's supported
  626. cl_int status;
  627. status = clEnqueueUnmapMemObject(commandQueue, mem, ptr, 0, NULL, NULL);
  628. cl_errChk(status, "Error unmapping a buffer or image", true);
  629. }
  630. void cl_writeToZCBuffer(cl_mem mem, void* data, size_t size)
  631. {
  632. void* ptr;
  633. ptr = cl_mapBuffer(mem, size, CL_MAP_WRITE);
  634. memcpy(ptr, data, size);
  635. cl_unmapBuffer(mem, ptr);
  636. }
  637. //-------------------------------------------------------
  638. // Program and kernels
  639. //-------------------------------------------------------
  640. //! Convert source code file into cl_program
  641. /*!
  642. Compile Opencl source file into a cl_program. The cl_program will be made into a kernel in PrecompileKernels()
  643. \param kernelPath Filename of OpenCl code
  644. \param compileoptions Compilation options
  645. \param verbosebuild Switch to enable verbose Output
  646. */
  647. cl_program cl_compileProgram(char* kernelPath, char* compileoptions, bool verbosebuild )
  648. {
  649. cl_int status;
  650. FILE *fp = NULL;
  651. char *source = NULL;
  652. long int size;
  653. printf("\t%s\n", kernelPath);
  654. // Determine the size of the source file
  655. #ifdef _WIN32
  656. fopen_s(&fp, kernelPath, "rb");
  657. #else
  658. fp = fopen(kernelPath, "rb");
  659. #endif
  660. if(!fp) {
  661. printf("Could not open kernel file\n");
  662. exit(-1);
  663. }
  664. status = fseek(fp, 0, SEEK_END);
  665. if(status != 0) {
  666. printf("Error seeking to end of file\n");
  667. exit(-1);
  668. }
  669. size = ftell(fp);
  670. if(size < 0) {
  671. printf("Error getting file position\n");
  672. exit(-1);
  673. }
  674. rewind(fp);
  675. // Allocate enough space for the source code
  676. source = (char *)alloc(size + 1);
  677. // fill with NULLs (just for fun)
  678. for (int i = 0; i < size+1; i++) {
  679. source[i] = '\0';
  680. }
  681. // Read in the source code
  682. fread(source, 1, size, fp);
  683. source[size] = '\0';
  684. // Create the program object
  685. cl_program clProgramReturn = clCreateProgramWithSource(context, 1,
  686. (const char **)&source, NULL, &status);
  687. cl_errChk(status, "Creating program", true);
  688. free(source);
  689. fclose(fp);
  690. // Try to compile the program
  691. status = clBuildProgram(clProgramReturn, 0, NULL, compileoptions, NULL, NULL);
  692. if(cl_errChk(status, "Building program", false) || verbosebuild == 1)
  693. {
  694. cl_build_status build_status;
  695. clGetProgramBuildInfo(clProgramReturn, device, CL_PROGRAM_BUILD_STATUS,
  696. sizeof(cl_build_status), &build_status, NULL);
  697. if(build_status == CL_SUCCESS && verbosebuild == 0) {
  698. return clProgramReturn;
  699. }
  700. //char *build_log;
  701. size_t ret_val_size;
  702. printf("Device: %p",device);
  703. clGetProgramBuildInfo(clProgramReturn, device, CL_PROGRAM_BUILD_LOG, 0,
  704. NULL, &ret_val_size);
  705. char *build_log = (char*)alloc(ret_val_size+1);
  706. clGetProgramBuildInfo(clProgramReturn, device, CL_PROGRAM_BUILD_LOG,
  707. ret_val_size+1, build_log, NULL);
  708. // to be careful, terminate with \0
  709. // there's no information in the reference whether the string is 0
  710. // terminated or not
  711. build_log[ret_val_size] = '\0';
  712. printf("Build log:\n %s...\n", build_log);
  713. if(build_status != CL_SUCCESS) {
  714. getchar();
  715. exit(-1);
  716. }
  717. else
  718. return clProgramReturn;
  719. }
  720. // print the ptx information
  721. // printBinaries(clProgram);
  722. return clProgramReturn;
  723. }
  724. //! Create a kernel from compiled source
  725. /*!
  726. Create a kernel from compiled source
  727. \param program Compiled OpenCL program
  728. \param kernel_name Name of the kernel in the program
  729. \return Returns a cl_kernel object for the specified kernel
  730. */
  731. cl_kernel cl_createKernel(cl_program program, const char* kernel_name) {
  732. cl_kernel kernel;
  733. cl_int status;
  734. kernel = clCreateKernel(program, kernel_name, &status);
  735. cl_errChk(status, "Creating kernel", true);
  736. return kernel;
  737. }
  738. //! Set an argument for a OpenCL kernel
  739. /*!
  740. Set an argument for a OpenCL kernel
  741. \param kernel The kernel for which the argument is being set
  742. \param index The argument index
  743. \param size The size of the argument
  744. \param data A pointer to the argument
  745. */
  746. void cl_setKernelArg(cl_kernel kernel, unsigned int index, size_t size,
  747. void* data)
  748. {
  749. cl_int status;
  750. status = clSetKernelArg(kernel, index, size, data);
  751. cl_errChk(status, "Setting kernel arg", true);
  752. }
  753. //-------------------------------------------------------
  754. // Profiling/events
  755. //-------------------------------------------------------
  756. //! Time kernel execution using cl_event
  757. /*!
  758. Prints out the time taken between the start and end of an event
  759. \param event_time
  760. */
  761. double cl_computeExecTime(cl_event event_time)
  762. {
  763. cl_int status;
  764. cl_ulong starttime;
  765. cl_ulong endtime;
  766. double elapsed;
  767. status = clGetEventProfilingInfo(event_time, CL_PROFILING_COMMAND_START,
  768. sizeof(cl_ulong), &starttime, NULL);
  769. cl_errChk(status, "profiling start", true);
  770. status = clGetEventProfilingInfo(event_time, CL_PROFILING_COMMAND_END,
  771. sizeof(cl_ulong), &endtime, NULL);
  772. cl_errChk(status, "profiling end", true);
  773. // Convert to ms
  774. elapsed = (double)(endtime-starttime)/1000000.0;
  775. return elapsed;
  776. }
  777. //! Compute the elapsed time between two timer values
  778. double cl_computeTime(cl_time start, cl_time end)
  779. {
  780. #ifdef _WIN32
  781. __int64 freq;
  782. int status;
  783. status = QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
  784. if(status == 0) {
  785. perror("QueryPerformanceFrequency");
  786. exit(-1);
  787. }
  788. // Return time in ms
  789. return double(end-start)/(double(freq)/1000.0);
  790. #else
  791. return end-start;
  792. #endif
  793. }
  794. //! Grab the current time using a system-specific timer
  795. void cl_getTime(cl_time* time)
  796. {
  797. #ifdef _WIN32
  798. int status = QueryPerformanceCounter((LARGE_INTEGER*)time);
  799. if(status == 0) {
  800. perror("QueryPerformanceCounter");
  801. exit(-1);
  802. }
  803. #else
  804. // Use gettimeofday to get the current time
  805. struct timeval curTime;
  806. gettimeofday(&curTime, NULL);
  807. // Convert timeval into double
  808. *time = curTime.tv_sec * 1000 + (double)curTime.tv_usec/1000;
  809. #endif
  810. }
  811. //-------------------------------------------------------
  812. // Error handling
  813. //-------------------------------------------------------
  814. //! OpenCl error code list
  815. /*!
  816. An array of character strings used to give the error corresponding to the error code \n
  817. The error code is the index within this array
  818. */
  819. char *cl_errs[MAX_ERR_VAL] = {
  820. (char *)"CL_SUCCESS", // 0
  821. (char *)"CL_DEVICE_NOT_FOUND", //-1
  822. (char *)"CL_DEVICE_NOT_AVAILABLE", //-2
  823. (char *)"CL_COMPILER_NOT_AVAILABLE", //-3
  824. (char *)"CL_MEM_OBJECT_ALLOCATION_FAILURE", //-4
  825. (char *)"CL_OUT_OF_RESOURCES", //-5
  826. (char *)"CL_OUT_OF_HOST_MEMORY", //-6
  827. (char *)"CL_PROFILING_INFO_NOT_AVAILABLE", //-7
  828. (char *)"CL_MEM_COPY_OVERLAP", //-8
  829. (char *)"CL_IMAGE_FORMAT_MISMATCH", //-9
  830. (char *)"CL_IMAGE_FORMAT_NOT_SUPPORTED", //-10
  831. (char *)"CL_BUILD_PROGRAM_FAILURE", //-11
  832. (char *)"CL_MAP_FAILURE", //-12
  833. (char *)"", //-13
  834. (char *)"", //-14
  835. (char *)"", //-15
  836. (char *)"", //-16
  837. (char *)"", //-17
  838. (char *)"", //-18
  839. (char *)"", //-19
  840. (char *)"", //-20
  841. (char *)"", //-21
  842. (char *)"", //-22
  843. (char *)"", //-23
  844. (char *)"", //-24
  845. (char *)"", //-25
  846. (char *)"", //-26
  847. (char *)"", //-27
  848. (char *)"", //-28
  849. (char *)"", //-29
  850. (char *)"CL_INVALID_VALUE", //-30
  851. (char *)"CL_INVALID_DEVICE_TYPE", //-31
  852. (char *)"CL_INVALID_PLATFORM", //-32
  853. (char *)"CL_INVALID_DEVICE", //-33
  854. (char *)"CL_INVALID_CONTEXT", //-34
  855. (char *)"CL_INVALID_QUEUE_PROPERTIES", //-35
  856. (char *)"CL_INVALID_COMMAND_QUEUE", //-36
  857. (char *)"CL_INVALID_HOST_PTR", //-37
  858. (char *)"CL_INVALID_MEM_OBJECT", //-38
  859. (char *)"CL_INVALID_IMAGE_FORMAT_DESCRIPTOR", //-39
  860. (char *)"CL_INVALID_IMAGE_SIZE", //-40
  861. (char *)"CL_INVALID_SAMPLER", //-41
  862. (char *)"CL_INVALID_BINARY", //-42
  863. (char *)"CL_INVALID_BUILD_OPTIONS", //-43
  864. (char *)"CL_INVALID_PROGRAM", //-44
  865. (char *)"CL_INVALID_PROGRAM_EXECUTABLE", //-45
  866. (char *)"CL_INVALID_KERNEL_NAME", //-46
  867. (char *)"CL_INVALID_KERNEL_DEFINITION", //-47
  868. (char *)"CL_INVALID_KERNEL", //-48
  869. (char *)"CL_INVALID_ARG_INDEX", //-49
  870. (char *)"CL_INVALID_ARG_VALUE", //-50
  871. (char *)"CL_INVALID_ARG_SIZE", //-51
  872. (char *)"CL_INVALID_KERNEL_ARGS", //-52
  873. (char *)"CL_INVALID_WORK_DIMENSION ", //-53
  874. (char *)"CL_INVALID_WORK_GROUP_SIZE", //-54
  875. (char *)"CL_INVALID_WORK_ITEM_SIZE", //-55
  876. (char *)"CL_INVALID_GLOBAL_OFFSET", //-56
  877. (char *)"CL_INVALID_EVENT_WAIT_LIST", //-57
  878. (char *)"CL_INVALID_EVENT", //-58
  879. (char *)"CL_INVALID_OPERATION", //-59
  880. (char *)"CL_INVALID_GL_OBJECT", //-60
  881. (char *)"CL_INVALID_BUFFER_SIZE", //-61
  882. (char *)"CL_INVALID_MIP_LEVEL", //-62
  883. (char *)"CL_INVALID_GLOBAL_WORK_SIZE"}; //-63
  884. //! OpenCl Error checker
  885. /*!
  886. Checks for error code as per cl_int returned by OpenCl
  887. \param status Error value as cl_int
  888. \param msg User provided error message
  889. \return True if Error Seen, False if no error
  890. */
  891. int cl_errChk(const cl_int status, const char * msg, bool exitOnErr)
  892. {
  893. if(status != CL_SUCCESS) {
  894. printf("OpenCL Error: %d %s %s\n", status, cl_errs[-status], msg);
  895. if(exitOnErr) {
  896. exit(-1);
  897. }
  898. return true;
  899. }
  900. return false;
  901. }
  902. // Queries the supported image formats for the device and prints
  903. // them to the screen
  904. void printSupportedImageFormats()
  905. {
  906. cl_uint numFormats;
  907. cl_int status;
  908. status = clGetSupportedImageFormats(context, 0, CL_MEM_OBJECT_IMAGE2D,
  909. 0, NULL, &numFormats);
  910. cl_errChk(status, "getting supported image formats", true);
  911. cl_image_format* imageFormats = NULL;
  912. imageFormats = (cl_image_format*)alloc(sizeof(cl_image_format)*numFormats);
  913. status = clGetSupportedImageFormats(context, 0, CL_MEM_OBJECT_IMAGE2D,
  914. numFormats, imageFormats, NULL);
  915. printf("There are %d supported image formats\n", numFormats);
  916. cl_uint orders[]={CL_R, CL_A, CL_INTENSITY, CL_LUMINANCE, CL_RG,
  917. CL_RA, CL_RGB, CL_RGBA, CL_ARGB, CL_BGRA};
  918. char *orderstr[]={(char *)"CL_R", (char *)"CL_A",(char *)"CL_INTENSITY", (char *)"CL_LUMINANCE", (char *)"CL_RG",
  919. (char *)"CL_RA", (char *)"CL_RGB", (char *)"CL_RGBA", (char *)"CL_ARGB", (char *)"CL_BGRA"};
  920. cl_uint types[]={
  921. CL_SNORM_INT8 , CL_SNORM_INT16, CL_UNORM_INT8, CL_UNORM_INT16,
  922. CL_UNORM_SHORT_565, CL_UNORM_SHORT_555, CL_UNORM_INT_101010,CL_SIGNED_INT8,
  923. CL_SIGNED_INT16, CL_SIGNED_INT32, CL_UNSIGNED_INT8, CL_UNSIGNED_INT16,
  924. CL_UNSIGNED_INT32, CL_HALF_FLOAT, CL_FLOAT};
  925. char * typesstr[]={
  926. (char *)"CL_SNORM_INT8" ,(char *)"CL_SNORM_INT16",(char *)"CL_UNORM_INT8",(char *)"CL_UNORM_INT16",
  927. (char *)"CL_UNORM_SHORT_565",(char *)"CL_UNORM_SHORT_555",(char *)"CL_UNORM_INT_101010",
  928. (char *)"CL_SIGNED_INT8",(char *)"CL_SIGNED_INT16",(char *)"CL_SIGNED_INT32",(char *)"CL_UNSIGNED_INT8",
  929. (char *)"CL_UNSIGNED_INT16",(char *)"CL_UNSIGNED_INT32",(char *)"CL_HALF_FLOAT",(char *)"CL_FLOAT"};
  930. printf("Supported Formats:\n");
  931. for(int i = 0; i < (int)numFormats; i++) {
  932. printf("\tFormat %d: ", i);
  933. for(int j = 0; j < (int)(sizeof(orders)/sizeof(cl_int)); j++) {
  934. if(imageFormats[i].image_channel_order == orders[j]) {
  935. printf("%s, ", orderstr[j]);
  936. }
  937. }
  938. for(int j = 0; j < (int)(sizeof(types)/sizeof(cl_int)); j++) {
  939. if(imageFormats[i].image_channel_data_type == types[j]) {
  940. printf("%s, ", typesstr[j]);
  941. }
  942. }
  943. printf("\n");
  944. }
  945. free(imageFormats);
  946. }
  947. //-------------------------------------------------------
  948. // Platform and device information
  949. //-------------------------------------------------------
  950. //! Returns true if AMD is the device vendor
  951. bool cl_deviceIsAMD(cl_device_id dev) {
  952. bool retval = false;
  953. char* vendor = cl_getDeviceVendor(dev);
  954. if(strncmp(vendor, "Advanced", 8) == 0) {
  955. retval = true;
  956. }
  957. free(vendor);
  958. return retval;
  959. }
  960. //! Returns true if NVIDIA is the device vendor
  961. bool cl_deviceIsNVIDIA(cl_device_id dev) {
  962. bool retval = false;
  963. char* vendor = cl_getDeviceVendor(dev);
  964. if(strncmp(vendor, "NVIDIA", 6) == 0) {
  965. retval = true;
  966. }
  967. free(vendor);
  968. return retval;
  969. }
  970. //! Returns true if NVIDIA is the device vendor
  971. bool cl_platformIsNVIDIA(cl_platform_id plat) {
  972. bool retval = false;
  973. char* vendor = cl_getPlatformVendor(plat);
  974. if(strncmp(vendor, "NVIDIA", 6) == 0) {
  975. retval = true;
  976. }
  977. free(vendor);
  978. return retval;
  979. }
  980. //! Get the name of the vendor for a device
  981. char* cl_getDeviceDriverVersion(cl_device_id dev)
  982. {
  983. cl_int status;
  984. size_t devInfoSize;
  985. char* devInfoStr = NULL;
  986. // If dev is NULL, set it to the default device
  987. if(dev == NULL) {
  988. dev = device;
  989. }
  990. // Print the vendor
  991. status = clGetDeviceInfo(dev, CL_DRIVER_VERSION, 0,
  992. NULL, &devInfoSize);
  993. cl_errChk(status, "Getting vendor name", true);
  994. devInfoStr = (char*)alloc(devInfoSize);
  995. status = clGetDeviceInfo(dev, CL_DRIVER_VERSION, devInfoSize,
  996. devInfoStr, NULL);
  997. cl_errChk(status, "Getting vendor name", true);
  998. return devInfoStr;
  999. }
  1000. //! The the name of the device as supplied by the OpenCL implementation
  1001. char* cl_getDeviceName(cl_device_id dev)
  1002. {
  1003. cl_int status;
  1004. size_t devInfoSize;
  1005. char* devInfoStr = NULL;
  1006. // If dev is NULL, set it to the default device
  1007. if(dev == NULL) {
  1008. dev = device;
  1009. }
  1010. // Print the name
  1011. status = clGetDeviceInfo(dev, CL_DEVICE_NAME, 0,
  1012. NULL, &devInfoSize);
  1013. cl_errChk(status, "Getting device name", true);
  1014. devInfoStr = (char*)alloc(devInfoSize);
  1015. status = clGetDeviceInfo(dev, CL_DEVICE_NAME, devInfoSize,
  1016. devInfoStr, NULL);
  1017. cl_errChk(status, "Getting device name", true);
  1018. return(devInfoStr);
  1019. }
  1020. //! Get the name of the vendor for a device
  1021. char* cl_getDeviceVendor(cl_device_id dev)
  1022. {
  1023. cl_int status;
  1024. size_t devInfoSize;
  1025. char* devInfoStr = NULL;
  1026. // If dev is NULL, set it to the default device
  1027. if(dev == NULL) {
  1028. dev = device;
  1029. }
  1030. // Print the vendor
  1031. status = clGetDeviceInfo(dev, CL_DEVICE_VENDOR, 0,
  1032. NULL, &devInfoSize);
  1033. cl_errChk(status, "Getting vendor name", true);
  1034. devInfoStr = (char*)alloc(devInfoSize);
  1035. status = clGetDeviceInfo(dev, CL_DEVICE_VENDOR, devInfoSize,
  1036. devInfoStr, NULL);
  1037. cl_errChk(status, "Getting vendor name", true);
  1038. return devInfoStr;
  1039. }
  1040. //! Get the name of the vendor for a device
  1041. char* cl_getDeviceVersion(cl_device_id dev)
  1042. {
  1043. cl_int status;
  1044. size_t devInfoSize;
  1045. char* devInfoStr = NULL;
  1046. // If dev is NULL, set it to the default device
  1047. if(dev == NULL) {
  1048. dev = device;
  1049. }
  1050. // Print the vendor
  1051. status = clGetDeviceInfo(dev, CL_DEVICE_VERSION, 0,
  1052. NULL, &devInfoSize);
  1053. cl_errChk(status, "Getting vendor name", true);
  1054. devInfoStr = (char*)alloc(devInfoSize);
  1055. status = clGetDeviceInfo(dev, CL_DEVICE_VERSION, devInfoSize,
  1056. devInfoStr, NULL);
  1057. cl_errChk(status, "Getting vendor name", true);
  1058. return devInfoStr;
  1059. }
  1060. //! The the name of the device as supplied by the OpenCL implementation
  1061. char* cl_getPlatformName(cl_platform_id platform)
  1062. {
  1063. cl_int status;
  1064. size_t platformInfoSize;
  1065. char* platformInfoStr = NULL;
  1066. // Print the name
  1067. status = clGetPlatformInfo(platform, CL_PLATFORM_NAME, 0,
  1068. NULL, &platformInfoSize);
  1069. cl_errChk(status, "Getting platform name", true);
  1070. platformInfoStr = (char*)alloc(platformInfoSize);
  1071. status = clGetPlatformInfo(platform, CL_PLATFORM_NAME, platformInfoSize,
  1072. platformInfoStr, NULL);
  1073. cl_errChk(status, "Getting platform name", true);
  1074. return(platformInfoStr);
  1075. }
  1076. //! The the name of the device as supplied by the OpenCL implementation
  1077. char* cl_getPlatformVendor(cl_platform_id platform)
  1078. {
  1079. cl_int status;
  1080. size_t platformInfoSize;
  1081. char* platformInfoStr = NULL;
  1082. // Print the name
  1083. status = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, 0,
  1084. NULL, &platformInfoSize);
  1085. cl_errChk(status, "Getting platform name", true);
  1086. platformInfoStr = (char*)alloc(platformInfoSize);
  1087. status = clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, platformInfoSize,
  1088. platformInfoStr, NULL);
  1089. cl_errChk(status, "Getting platform name", true);
  1090. return(platformInfoStr);
  1091. }
  1092. //-------------------------------------------------------
  1093. // Utility functions
  1094. //-------------------------------------------------------
  1095. //! Take a string and an int, and return a string
  1096. char* catStringWithInt(const char* string, int integer) {
  1097. if(integer > 99999) {
  1098. printf("Can't handle event identifiers with 6 digits\n");
  1099. exit(-1);
  1100. }
  1101. // 5 characters for the identifier, 1 for the null terminator
  1102. int strLen = strlen(string)+5+1;
  1103. char* eventStr = (char*)alloc(sizeof(char)*strLen);
  1104. char tmp[6];
  1105. strcpy(eventStr, string);
  1106. strncat(eventStr, itoa_portable(integer, tmp, 10), 5);
  1107. return eventStr;
  1108. }
  1109. /**
  1110. ** C++ version 0.4 char* style "itoa":
  1111. ** Written by Lukás Chmela
  1112. ** Released under GPLv3.
  1113. **/
  1114. //portable itoa function
  1115. char* itoa_portable(int value, char* result, int base) {
  1116. // check that the base if valid
  1117. if (base < 2 || base > 36) { *result = '\0'; return result; }
  1118. char* ptr = result, *ptr1 = result, tmp_char;
  1119. int tmp_value;
  1120. do {
  1121. tmp_value = value;
  1122. value /= base;
  1123. *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
  1124. } while ( value );
  1125. //Apply negative sign
  1126. if (tmp_value < 0) *ptr++ = '-';
  1127. *ptr-- = '\0';
  1128. while(ptr1 < ptr) {
  1129. tmp_char = *ptr;
  1130. *ptr--= *ptr1;
  1131. *ptr1++ = tmp_char;
  1132. }
  1133. return result;
  1134. }