00001 #include <opencl_utils.h>
00002
00003 #define HDASHLINE "-----------------------------------------------------------\n"
00004
00005 #include <fstream>
00006 #include <vector>
00007 #include <string.h>
00008 #include <iostream>
00009 #include <algorithm>
00010 #include <stdarg.h>
00011 #include <stdlib.h>
00012
00013 cl_context g_clDeviceContext;
00014 cl_command_queue g_clDeviceQueue;
00015
00016 cl_context oclGetGlobalContext( ) {
00017 return g_clDeviceContext;
00018 }
00019
00020 cl_command_queue oclGetGlobalQueue( ) {
00021 return g_clDeviceQueue;
00022 }
00023
00030 cl_int oclGetPlatformID(cl_platform_id* clSelectedPlatformID)
00031 {
00032 char chBuffer[1024];
00033 cl_uint num_platforms;
00034 cl_platform_id* clPlatformIDs;
00035 cl_int ciErrNum;
00036 *clSelectedPlatformID = NULL;
00037
00038
00039 ciErrNum = clGetPlatformIDs (0, NULL, &num_platforms);
00040 if (ciErrNum != CL_SUCCESS)
00041 {
00042 printf(" Error %i in clGetPlatformIDs Call !!!\n\n", ciErrNum);
00043 return -1000;
00044 }
00045 else
00046 {
00047 if(num_platforms == 0)
00048 {
00049 printf("No OpenCL platform found!\n\n");
00050 return -2000;
00051 }
00052 else
00053 {
00054
00055 if ((clPlatformIDs = (cl_platform_id*)malloc(num_platforms * sizeof(cl_platform_id))) == NULL)
00056 {
00057 printf("Failed to allocate memory for cl_platform ID's!\n\n");
00058 return -3000;
00059 }
00060
00061
00062 ciErrNum = clGetPlatformIDs (num_platforms, clPlatformIDs, NULL);
00063 for(cl_uint i = 0; i < num_platforms; ++i)
00064 {
00065 ciErrNum = clGetPlatformInfo (clPlatformIDs[i], CL_PLATFORM_NAME, 1024, &chBuffer, NULL);
00066 if(ciErrNum == CL_SUCCESS)
00067 {
00068 if(strstr(chBuffer, "NVIDIA") != NULL)
00069 {
00070 *clSelectedPlatformID = clPlatformIDs[i];
00071 break;
00072 }
00073 }
00074 }
00075
00076
00077 if(*clSelectedPlatformID == NULL)
00078 {
00079 printf("WARNING: NVIDIA OpenCL platform not found - defaulting to first platform!\n\n");
00080 *clSelectedPlatformID = clPlatformIDs[0];
00081 }
00082
00083 free(clPlatformIDs);
00084 }
00085 }
00086
00087 return CL_SUCCESS;
00088 }
00089
00096 cl_device_id oclGetFirstDev(cl_context cxGPUContext)
00097 {
00098 size_t szParmDataBytes;
00099 cl_device_id* cdDevices;
00100
00101
00102 clGetContextInfo(cxGPUContext, CL_CONTEXT_DEVICES, 0, NULL, &szParmDataBytes);
00103 cdDevices = (cl_device_id*) malloc(szParmDataBytes);
00104
00105 clGetContextInfo(cxGPUContext, CL_CONTEXT_DEVICES, szParmDataBytes, cdDevices, NULL);
00106
00107 cl_device_id first = cdDevices[0];
00108 free(cdDevices);
00109
00110 return first;
00111 }
00112
00116 void oclInit( ) {
00117 cl_platform_id cpPlatform;
00118 cl_device_id cdDevice;
00119 cl_int ciErrNum;
00120
00121 ciErrNum = oclGetPlatformID(&cpPlatform);
00122 oclCheckError(ciErrNum, CL_SUCCESS);
00123
00124 ciErrNum = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, NULL);
00125 oclCheckError(ciErrNum, CL_SUCCESS);
00126
00127 g_clDeviceContext = clCreateContext(0, 1, &cdDevice, NULL, NULL, &ciErrNum);
00128 oclCheckError(ciErrNum, CL_SUCCESS);
00129
00130 g_clDeviceQueue = clCreateCommandQueue(g_clDeviceContext, cdDevice, 0, &ciErrNum);
00131 oclCheckError(ciErrNum, CL_SUCCESS);
00132 }
00133
00140 void oclShutdown(cl_context clContext, cl_command_queue clQueue) {
00141 cl_int ciErrNum;
00142 ciErrNum = clReleaseCommandQueue(clQueue);
00143 ciErrNum |= clReleaseContext(clContext);
00144 oclCheckError(ciErrNum, CL_SUCCESS);
00145 }
00146
00155 char* oclLoadProgSource(const char* cFilename, const char* cPreamble, size_t* szFinalLength)
00156 {
00157
00158 FILE* pFileStream = NULL;
00159 size_t szSourceLength;
00160
00161
00162 #ifdef _WIN32 // Windows version
00163 if(fopen_s(&pFileStream, cFilename, "rb") != 0)
00164 {
00165 return NULL;
00166 }
00167 #else // Linux version
00168 pFileStream = fopen(cFilename, "rb");
00169 if(pFileStream == 0)
00170 {
00171 return NULL;
00172 }
00173 #endif
00174
00175 size_t szPreambleLength = strlen(cPreamble);
00176
00177
00178 fseek(pFileStream, 0, SEEK_END);
00179 szSourceLength = ftell(pFileStream);
00180 fseek(pFileStream, 0, SEEK_SET);
00181
00182
00183 char* cSourceString = (char *)malloc(szSourceLength + szPreambleLength + 1);
00184 memcpy(cSourceString, cPreamble, szPreambleLength);
00185 if (fread((cSourceString) + szPreambleLength, szSourceLength, 1, pFileStream) != 1)
00186 {
00187 fclose(pFileStream);
00188 free(cSourceString);
00189 return 0;
00190 }
00191
00192
00193 fclose(pFileStream);
00194 if(szFinalLength != 0)
00195 {
00196 *szFinalLength = szSourceLength + szPreambleLength;
00197 }
00198 cSourceString[szSourceLength + szPreambleLength] = '\0';
00199
00200 return cSourceString;
00201 }
00202
00211 void oclGetProgBinary( cl_program cpProgram, cl_device_id cdDevice, char** binary, size_t* length)
00212 {
00213
00214 cl_uint num_devices;
00215 clGetProgramInfo(cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &num_devices, NULL);
00216
00217
00218 cl_device_id* devices = (cl_device_id*) malloc(num_devices * sizeof(cl_device_id));
00219 clGetProgramInfo(cpProgram, CL_PROGRAM_DEVICES, num_devices * sizeof(cl_device_id), devices, 0);
00220
00221
00222 size_t* binary_sizes = (size_t*)malloc(num_devices * sizeof(size_t));
00223 clGetProgramInfo(cpProgram, CL_PROGRAM_BINARY_SIZES, num_devices * sizeof(size_t), binary_sizes, NULL);
00224
00225
00226 char** ptx_code = (char**) malloc(num_devices * sizeof(char*));
00227 for( unsigned int i=0; i<num_devices; ++i) {
00228 ptx_code[i]= (char*)malloc(binary_sizes[i]);
00229 }
00230 clGetProgramInfo(cpProgram, CL_PROGRAM_BINARIES, 0, ptx_code, NULL);
00231
00232
00233 unsigned int idx = 0;
00234 while( idx<num_devices && devices[idx] != cdDevice ) ++idx;
00235
00236
00237 if( idx < num_devices )
00238 {
00239 *binary = ptx_code[idx];
00240 *length = binary_sizes[idx];
00241 }
00242
00243
00244 free( devices );
00245 free( binary_sizes );
00246 for( unsigned int i=0; i<num_devices; ++i) {
00247 if( i != idx ) free(ptx_code[i]);
00248 }
00249 free( ptx_code );
00250 }
00251
00259 void oclLogPtx(cl_program cpProgram, cl_device_id cdDevice, const char* cPtxFileName)
00260 {
00261
00262 cl_uint num_devices;
00263 clGetProgramInfo(cpProgram, CL_PROGRAM_NUM_DEVICES, sizeof(cl_uint), &num_devices, NULL);
00264
00265
00266 cl_device_id* devices = (cl_device_id*) malloc(num_devices * sizeof(cl_device_id));
00267 clGetProgramInfo(cpProgram, CL_PROGRAM_DEVICES, num_devices * sizeof(cl_device_id), devices, 0);
00268
00269
00270 size_t* binary_sizes = (size_t*)malloc(num_devices * sizeof(size_t));
00271 clGetProgramInfo(cpProgram, CL_PROGRAM_BINARY_SIZES, num_devices * sizeof(size_t), binary_sizes, NULL);
00272
00273
00274 char** ptx_code = (char**)malloc(num_devices * sizeof(char*));
00275 for( unsigned int i=0; i<num_devices; ++i)
00276 {
00277 ptx_code[i] = (char*)malloc(binary_sizes[i]);
00278 }
00279 clGetProgramInfo(cpProgram, CL_PROGRAM_BINARIES, 0, ptx_code, NULL);
00280
00281
00282 unsigned int idx = 0;
00283 while((idx < num_devices) && (devices[idx] != cdDevice))
00284 {
00285 ++idx;
00286 }
00287
00288
00289 if(idx < num_devices)
00290 {
00291
00292
00293 if (NULL != cPtxFileName)
00294 {
00295 printf("\nWriting ptx to separate file: %s ...\n\n", cPtxFileName);
00296 FILE* pFileStream = NULL;
00297 #ifdef _WIN32
00298 fopen_s(&pFileStream, cPtxFileName, "wb");
00299 #else
00300 pFileStream = fopen(cPtxFileName, "wb");
00301 #endif
00302
00303 fwrite(ptx_code[idx], binary_sizes[idx], 1, pFileStream);
00304 fclose(pFileStream);
00305 }
00306 else
00307 {
00308 printf("\n%s\nProgram Binary:\n%s\n%s\n", HDASHLINE, ptx_code[idx], HDASHLINE);
00309 }
00310 }
00311
00312
00313 free(devices);
00314 free(binary_sizes);
00315 for(unsigned int i = 0; i < num_devices; ++i)
00316 {
00317 free(ptx_code[i]);
00318 }
00319 free( ptx_code );
00320 }
00321
00328 void oclLogBuildInfo(cl_program cpProgram, cl_device_id cdDevice)
00329 {
00330 char *cBuildLog;
00331 size_t retValSize;
00332
00333 clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, 0, NULL, &retValSize);
00334 cBuildLog = new char[retValSize+1];
00335
00336 clGetProgramBuildInfo(cpProgram, cdDevice, CL_PROGRAM_BUILD_LOG, retValSize, cBuildLog, NULL);
00337 cBuildLog[retValSize] = '\0';
00338
00339 printf("\n%s\nBUILD LOG:\n%s\n%s\n", HDASHLINE, cBuildLog, HDASHLINE);
00340
00341 delete[] cBuildLog;
00342 }
00343
00344
00345
00346 const char* oclErrorString(cl_int error)
00347 {
00348 static const char* errorString[] = {
00349 "CL_SUCCESS",
00350 "CL_DEVICE_NOT_FOUND",
00351 "CL_DEVICE_NOT_AVAILABLE",
00352 "CL_COMPILER_NOT_AVAILABLE",
00353 "CL_MEM_OBJECT_ALLOCATION_FAILURE",
00354 "CL_OUT_OF_RESOURCES",
00355 "CL_OUT_OF_HOST_MEMORY",
00356 "CL_PROFILING_INFO_NOT_AVAILABLE",
00357 "CL_MEM_COPY_OVERLAP",
00358 "CL_IMAGE_FORMAT_MISMATCH",
00359 "CL_IMAGE_FORMAT_NOT_SUPPORTED",
00360 "CL_BUILD_PROGRAM_FAILURE",
00361 "CL_MAP_FAILURE",
00362 "",
00363 "",
00364 "",
00365 "",
00366 "",
00367 "",
00368 "",
00369 "",
00370 "",
00371 "",
00372 "",
00373 "",
00374 "",
00375 "",
00376 "",
00377 "",
00378 "",
00379 "CL_INVALID_VALUE",
00380 "CL_INVALID_DEVICE_TYPE",
00381 "CL_INVALID_PLATFORM",
00382 "CL_INVALID_DEVICE",
00383 "CL_INVALID_CONTEXT",
00384 "CL_INVALID_QUEUE_PROPERTIES",
00385 "CL_INVALID_COMMAND_QUEUE",
00386 "CL_INVALID_HOST_PTR",
00387 "CL_INVALID_MEM_OBJECT",
00388 "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR",
00389 "CL_INVALID_IMAGE_SIZE",
00390 "CL_INVALID_SAMPLER",
00391 "CL_INVALID_BINARY",
00392 "CL_INVALID_BUILD_OPTIONS",
00393 "CL_INVALID_PROGRAM",
00394 "CL_INVALID_PROGRAM_EXECUTABLE",
00395 "CL_INVALID_KERNEL_NAME",
00396 "CL_INVALID_KERNEL_DEFINITION",
00397 "CL_INVALID_KERNEL",
00398 "CL_INVALID_ARG_INDEX",
00399 "CL_INVALID_ARG_VALUE",
00400 "CL_INVALID_ARG_SIZE",
00401 "CL_INVALID_KERNEL_ARGS",
00402 "CL_INVALID_WORK_DIMENSION",
00403 "CL_INVALID_WORK_GROUP_SIZE",
00404 "CL_INVALID_WORK_ITEM_SIZE",
00405 "CL_INVALID_GLOBAL_OFFSET",
00406 "CL_INVALID_EVENT_WAIT_LIST",
00407 "CL_INVALID_EVENT",
00408 "CL_INVALID_OPERATION",
00409 "CL_INVALID_GL_OBJECT",
00410 "CL_INVALID_BUFFER_SIZE",
00411 "CL_INVALID_MIP_LEVEL",
00412 "CL_INVALID_GLOBAL_WORK_SIZE",
00413 };
00414
00415 const int errorCount = sizeof(errorString) / sizeof(errorString[0]);
00416 const int index = -error;
00417
00418 return (index >= 0 && index < errorCount) ? errorString[index] : "Unspecified Error";
00419 }
00420
00421 char* oclFindFilePath(const char* filename, const char* executable_path)
00422 {
00423
00424
00425
00426
00427 const char* searchPath[] =
00428 {
00429 "./",
00430 "./data/",
00431 "./src/",
00432 "./src/<executable_name>/data/",
00433 "./include/",
00434 "./include/<executable_name>/",
00435 "../",
00436 "../data/",
00437 "../src/",
00438 "../include/",
00439 "../OpenCL/src/<executable_name>/",
00440 "../OpenCL/src/<executable_name>/data/",
00441 "../OpenCL/src/<executable_name>/src/",
00442 "../OpenCL/src/<executable_name>/inc/",
00443 "../C/src/<executable_name>/",
00444 "../C/src/<executable_name>/data/",
00445 "../C/src/<executable_name>/src/",
00446 "../C/src/<executable_name>/inc/",
00447 "../../",
00448 "../../data/",
00449 "../../src/",
00450 "../../inc/",
00451 "../../../",
00452 "../../../src/<executable_name>/",
00453 "../../../src/<executable_name>/data/",
00454 "../../../src/<executable_name>/src/",
00455 "../../../src/<executable_name>/inc/",
00456 "../../../sandbox/<executable_name>/",
00457 "../../../sandbox/<executable_name>/data/",
00458 "../../../sandbox/<executable_name>/src/",
00459 "../../../sandbox/<executable_name>/inc/"
00460 };
00461
00462
00463 std::string executable_name;
00464 if (executable_path != 0)
00465 {
00466 executable_name = std::string(executable_path);
00467
00468 #ifdef _WIN32
00469
00470 size_t delimiter_pos = executable_name.find_last_of('\\');
00471 executable_name.erase(0, delimiter_pos + 1);
00472
00473 if (executable_name.rfind(".exe") != string::npos)
00474 {
00475
00476 executable_name.resize(executable_name.size() - 4);
00477 }
00478 #else
00479
00480 size_t delimiter_pos = executable_name.find_last_of('/');
00481 executable_name.erase(0,delimiter_pos+1);
00482 #endif
00483
00484 }
00485
00486
00487 for( unsigned int i = 0; i < sizeof(searchPath)/sizeof(char*); ++i )
00488 {
00489 std::string path(searchPath[i]);
00490 size_t executable_name_pos = path.find("<executable_name>");
00491
00492
00493
00494 if(executable_name_pos != std::string::npos)
00495 {
00496 if(executable_path != 0)
00497 {
00498 path.replace(executable_name_pos, strlen("<executable_name>"), executable_name);
00499
00500 }
00501 else
00502 {
00503
00504 continue;
00505 }
00506 }
00507
00508
00509 path.append(filename);
00510 std::fstream fh(path.c_str(), std::fstream::in);
00511 if (fh.good())
00512 {
00513
00514
00515 char* file_path = (char*) malloc(path.length() + 1);
00516 #ifdef _WIN32
00517 strcpy_s(file_path, path.length() + 1, path.c_str());
00518 #else
00519 strcpy(file_path, path.c_str());
00520 #endif
00521 return file_path;
00522 }
00523 }
00524
00525
00526 return 0;
00527 }