/// Returns the address of the \p function_name extension /// function. Returns \c 0 if \p function_name is invalid. void* get_extension_function_address(const char *function_name) const { #ifdef BOOST_COMPUTE_CL_VERSION_1_2 return clGetExtensionFunctionAddressForPlatform(m_platform, function_name); #else return clGetExtensionFunctionAddress(function_name); #endif }
void * CLDevice::get_extension_function (const char *func_name) { XCAM_ASSERT (func_name); void *ext_func = NULL; #if defined (CL_VERSION_1_2) && (CL_VERSION_1_2 == 1) ext_func = (void *) clGetExtensionFunctionAddressForPlatform (_platform_id, func_name); #else ext_func = (void *) clGetExtensionFunctionAddress (func_name); #endif if (!ext_func) XCAM_LOG_ERROR ("ocl driver get extension function (%s) failed", func_name); return ext_func; }
JNIEXPORT jlong JNICALL Java_org_lwjgl_opencl_CL12_nclGetExtensionFunctionAddressForPlatform(JNIEnv *env, jclass clazz, jlong platform, jlong func_name, jlong function_pointer) { const cl_char *func_name_address = (const cl_char *)(intptr_t)func_name; clGetExtensionFunctionAddressForPlatformPROC clGetExtensionFunctionAddressForPlatform = (clGetExtensionFunctionAddressForPlatformPROC)((intptr_t)function_pointer); void * __result = clGetExtensionFunctionAddressForPlatform((cl_platform_id)(intptr_t)platform, func_name_address); return (intptr_t)__result; }
Context& initializeContextFromVA(VADisplay display) { (void)display; #if !defined(HAVE_VAAPI) NO_VAAPI_SUPPORT_ERROR; #elif !defined(HAVE_OPENCL) NO_OPENCL_SUPPORT_ERROR; #else contextInitialized = false; cl_uint numPlatforms; cl_int status = clGetPlatformIDs(0, NULL, &numPlatforms); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get number of platforms"); if (numPlatforms == 0) CV_Error(cv::Error::OpenCLInitError, "OpenCL: No available platforms"); std::vector<cl_platform_id> platforms(numPlatforms); status = clGetPlatformIDs(numPlatforms, &platforms[0], NULL); if (status != CL_SUCCESS) CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't get platform Id list"); // For CL-VA interop, we must find platform/device with "cl_intel_va_api_media_sharing" extension. // With standard initialization procedure, we should examine platform extension string for that. // But in practice, the platform ext string doesn't contain it, while device ext string does. // Follow Intel procedure (see tutorial), we should obtain device IDs by extension call. // Note that we must obtain function pointers using specific platform ID, and can't provide pointers in advance. // So, we iterate and select the first platform, for which we got non-NULL pointers, device, and CL context. int found = -1; cl_context context = 0; cl_device_id device = 0; for (int i = 0; i < (int)numPlatforms; ++i) { // Get extension function pointers clGetDeviceIDsFromVA_APIMediaAdapterINTEL = (clGetDeviceIDsFromVA_APIMediaAdapterINTEL_fn) clGetExtensionFunctionAddressForPlatform(platforms[i], "clGetDeviceIDsFromVA_APIMediaAdapterINTEL"); clCreateFromVA_APIMediaSurfaceINTEL = (clCreateFromVA_APIMediaSurfaceINTEL_fn) clGetExtensionFunctionAddressForPlatform(platforms[i], "clCreateFromVA_APIMediaSurfaceINTEL"); clEnqueueAcquireVA_APIMediaSurfacesINTEL = (clEnqueueAcquireVA_APIMediaSurfacesINTEL_fn) clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueAcquireVA_APIMediaSurfacesINTEL"); clEnqueueReleaseVA_APIMediaSurfacesINTEL = (clEnqueueReleaseVA_APIMediaSurfacesINTEL_fn) clGetExtensionFunctionAddressForPlatform(platforms[i], "clEnqueueReleaseVA_APIMediaSurfacesINTEL"); if (((void*)clGetDeviceIDsFromVA_APIMediaAdapterINTEL == NULL) || ((void*)clCreateFromVA_APIMediaSurfaceINTEL == NULL) || ((void*)clEnqueueAcquireVA_APIMediaSurfacesINTEL == NULL) || ((void*)clEnqueueReleaseVA_APIMediaSurfacesINTEL == NULL)) { continue; } // Query device list cl_uint numDevices = 0; status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, 0, NULL, &numDevices); if ((status != CL_SUCCESS) || !(numDevices > 0)) continue; numDevices = 1; // initializeContextFromHandle() expects only 1 device status = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platforms[i], CL_VA_API_DISPLAY_INTEL, display, CL_PREFERRED_DEVICES_FOR_VA_API_INTEL, numDevices, &device, NULL); if (status != CL_SUCCESS) continue; // Creating CL-VA media sharing OpenCL context cl_context_properties props[] = { CL_CONTEXT_VA_API_DISPLAY_INTEL, (cl_context_properties) display, CL_CONTEXT_INTEROP_USER_SYNC, CL_FALSE, // no explicit sync required 0 }; context = clCreateContext(props, numDevices, &device, NULL, NULL, &status); if (status != CL_SUCCESS) { clReleaseDevice(device); } else { found = i; break; } } if (found < 0) CV_Error(cv::Error::OpenCLInitError, "OpenCL: Can't create context for VA-API interop"); Context& ctx = Context::getDefault(false); initializeContextFromHandle(ctx, platforms[found], context, device); contextInitialized = true; return ctx; #endif }
// OpenCL functions int InitialiseCLEnvironment(cl_platform_id **platform, cl_device_id ***device_id, cl_program *program, renderStruct *render) { // error flag cl_int err; char infostring[1024]; char deviceInfo[1024]; // need to ensure platform supports OpenGL OpenCL interop before querying devices // to avoid segfault when calling clGetGLContextInfoKHR int *platformSupportsInterop; //get kernel from file FILE* kernelFile = fopen(kernelFileName, "rb"); fseek(kernelFile, 0, SEEK_END); long fileLength = ftell(kernelFile); rewind(kernelFile); char *kernelSource = malloc(fileLength*sizeof(char)); long read = fread(kernelSource, sizeof(char), fileLength, kernelFile); if (fileLength != read) printf("Error reading kernel file, line %d\n", __LINE__); fclose(kernelFile); //get platform and device information cl_uint numPlatforms; err = clGetPlatformIDs(0, NULL, &numPlatforms); *platform = malloc(numPlatforms * sizeof(cl_platform_id)); *device_id = malloc(numPlatforms * sizeof(cl_device_id*)); platformSupportsInterop = malloc(numPlatforms * sizeof(*platformSupportsInterop)); err |= clGetPlatformIDs(numPlatforms, *platform, NULL); CheckOpenCLError(err, __LINE__); cl_uint *numDevices; numDevices = malloc(numPlatforms * sizeof(cl_uint)); for (cl_uint i = 0; i < numPlatforms; i++) { clGetPlatformInfo((*platform)[i], CL_PLATFORM_VENDOR, sizeof(infostring), infostring, NULL); printf("\n---OpenCL: Platform Vendor %d: %s\n", i, infostring); err = clGetDeviceIDs((*platform)[i], CL_DEVICE_TYPE_ALL, 0, NULL, &(numDevices[i])); CheckOpenCLError(err, __LINE__); (*device_id)[i] = malloc(numDevices[i] * sizeof(cl_device_id)); platformSupportsInterop[i] = 0; err = clGetDeviceIDs((*platform)[i], CL_DEVICE_TYPE_ALL, numDevices[i], (*device_id)[i], NULL); CheckOpenCLError(err, __LINE__); for (cl_uint j = 0; j < numDevices[i]; j++) { char deviceName[200]; clGetDeviceInfo((*device_id)[i][j], CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL); printf("---OpenCL: Device found %d. %s\n", j, deviceName); clGetDeviceInfo((*device_id)[i][j], CL_DEVICE_EXTENSIONS, sizeof(deviceInfo), deviceInfo, NULL); if (strstr(deviceInfo, "cl_khr_gl_sharing") != NULL) { printf("---OpenCL: cl_khr_gl_sharing supported!\n"); platformSupportsInterop[i] = 1; } else { printf("---OpenCL: cl_khr_gl_sharing NOT supported!\n"); platformSupportsInterop[i] |= 0; } if (strstr(deviceInfo, "cl_khr_fp64") != NULL) { printf("---OpenCL: cl_khr_fp64 supported!\n"); } else { printf("---OpenCL: cl_khr_fp64 NOT supported!\n"); } } } printf("\n"); //////////////////////////////// // This part is different to how we usually do things. Need to get context and device from existing // OpenGL context. Loop through all platforms looking for the device: cl_device_id device = NULL; int deviceFound = 0; cl_uint checkPlatform = 0; #ifdef TRYINTEROP while (!deviceFound) { if (platformSupportsInterop[checkPlatform]) { printf("---OpenCL: Looking for OpenGL Context device on platform %d ... ", checkPlatform); clGetGLContextInfoKHR_fn pclGetGLContextInfoKHR; PTR_FUNC_PTR pclGetGLContextInfoKHR = clGetExtensionFunctionAddressForPlatform((*platform)[checkPlatform], "clGetGLContextInfoKHR"); cl_context_properties properties[] = { CL_GL_CONTEXT_KHR, (cl_context_properties) glfwGetGLXContext(render->window), CL_GLX_DISPLAY_KHR, (cl_context_properties) glfwGetX11Display(), CL_CONTEXT_PLATFORM, (cl_context_properties) (*platform)[checkPlatform], 0}; err = pclGetGLContextInfoKHR(properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, sizeof(cl_device_id), &device, NULL); if (err != CL_SUCCESS) { printf("Not Found.\n"); checkPlatform++; if (checkPlatform > numPlatforms-1) { printf("---OpenCL: Error! Could not find OpenGL sharing device.\n"); deviceFound = 1; render->glclInterop = 0; } } else { printf("Found!\n"); deviceFound = 1; render->glclInterop = 1; } } else { checkPlatform++; } } if (render->glclInterop) { // Check the device we've found supports double precision clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS, sizeof(deviceInfo), deviceInfo, NULL); if (strstr(deviceInfo, "cl_khr_fp64") == NULL) { printf("---OpenCL: Interop device doesn't support double precision! We cannot use it.\n"); } else { cl_context_properties properties[] = { CL_GL_CONTEXT_KHR, (cl_context_properties) glfwGetGLXContext(render->window), CL_GLX_DISPLAY_KHR, (cl_context_properties) glfwGetX11Display(), CL_CONTEXT_PLATFORM, (cl_context_properties) (*platform)[checkPlatform], 0}; render->contextCL = clCreateContext(properties, 1, &device, NULL, 0, &err); CheckOpenCLError(err, __LINE__); } } #endif // if render->glclInterop is 0, either we are not trying to use it, we couldn't find an interop // device, or we found an interop device but it doesn't support double precision. // In these cases, have the user choose a platform and device manually. if (!(render->glclInterop)) { printf("Choose a platform and device.\n"); checkPlatform = numPlatforms; while (checkPlatform >= numPlatforms) { printf("Platform: "); scanf("%u", &checkPlatform); if (checkPlatform >= numPlatforms) { printf("Invalid Platform choice.\n"); } } cl_uint chooseDevice = numDevices[checkPlatform]; while (chooseDevice >= numDevices[checkPlatform]) { printf("Device: "); scanf("%u", &chooseDevice); if (chooseDevice >= numDevices[checkPlatform]) { printf("Invalid Device choice.\n"); } else { // Check the device we've chosen supports double precision clGetDeviceInfo((*device_id)[checkPlatform][chooseDevice], CL_DEVICE_EXTENSIONS, sizeof(deviceInfo), deviceInfo, NULL); if (strstr(deviceInfo, "cl_khr_fp64") == NULL) { printf("---OpenCL: Interop device doesn't support double precision! We cannot use it.\n"); chooseDevice = numDevices[checkPlatform]; } } } // Create non-interop context render->contextCL = clCreateContext(NULL, 1, &((*device_id)[checkPlatform][chooseDevice]), NULL, NULL, &err); device = (*device_id)[checkPlatform][chooseDevice]; } //////////////////////////////// // device is now fixed. Query its max global memory allocation size and store it, used in // HighResolutionRender routine, to determine into how many tiles we need to split the // computation. clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(render->deviceMaxAlloc), &(render->deviceMaxAlloc), NULL); printf("---OpenCL: Selected device has CL_DEVICE_MAX_MEM_ALLOC_SIZE: %lfMB\n", render->deviceMaxAlloc/1024.0/1024.0); // create a command queue render->queue = clCreateCommandQueue(render->contextCL, device, 0, &err); CheckOpenCLError(err, __LINE__); //create the program with the source above // printf("Creating CL Program...\n"); *program = clCreateProgramWithSource(render->contextCL, 1, (const char**)&kernelSource, NULL, &err); if (err != CL_SUCCESS) { printf("Error in clCreateProgramWithSource: %d, line %d.\n", err, __LINE__); return EXIT_FAILURE; } //build program executable err = clBuildProgram(*program, 0, NULL, "-I. -I src/", NULL, NULL); if (err != CL_SUCCESS) { printf("Error in clBuildProgram: %d, line %d.\n", err, __LINE__); char buffer[5000]; clGetProgramBuildInfo(*program, device, CL_PROGRAM_BUILD_LOG, sizeof(buffer), buffer, NULL); printf("%s\n", buffer); return EXIT_FAILURE; } // dump ptx size_t binSize; clGetProgramInfo(*program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binSize, NULL); unsigned char *bin = malloc(binSize); clGetProgramInfo(*program, CL_PROGRAM_BINARIES, sizeof(unsigned char *), &bin, NULL); FILE *fp = fopen("openclPTX.ptx", "wb"); fwrite(bin, sizeof(char), binSize, fp); fclose(fp); free(bin); free(numDevices); free(kernelSource); printf("\n"); return EXIT_SUCCESS; }
bool CLContextWrapper::createContextWithOpengl() { cl_platform_id platform; cl_int err = clGetPlatformIDs(1, &platform, nullptr); if(err) { logError("Error: Failed get platorm id" , getError(err)); return false; } // Create CL context properties, add handle & share-group enum auto glContext = wglGetCurrentContext(); auto glDc = wglGetCurrentDC(); cl_context_properties properties[] = { CL_GL_CONTEXT_KHR, (cl_context_properties) glContext, CL_WGL_HDC_KHR, (cl_context_properties) glDc, CL_CONTEXT_PLATFORM,(cl_context_properties) platform, 0 }; // Get Device Info // The easy way cl_device_id computeDeviceId; err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &computeDeviceId, NULL); if (err) { // The "hard" way if (!clGetGLContextInfoKHR) { clGetGLContextInfoKHR = (clGetGLContextInfoKHR_fn) clGetExtensionFunctionAddressForPlatform(platform, "clGetGLContextInfoKHR"); if (!clGetGLContextInfoKHR) { logError("Error: Failed to locate a compute device!" , "Failed to query proc address for clGetGLContextInfoKHR"); return false; } // Get the first err = clGetGLContextInfoKHR(properties, CL_DEVICES_FOR_GL_CONTEXT_KHR, sizeof(cl_device_id), &computeDeviceId, nullptr); if(!computeDeviceId) { logError("Error: Failed to locate a compute device!" , getError(err)); } } } // Create a context with device in the CGL share group cl_context context = clCreateContext(properties, 1, &computeDeviceId, nullptr, 0, &err); size_t returnedSize = 0; size_t maxWorkGroupSize = 0; err = clGetDeviceInfo(computeDeviceId, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &maxWorkGroupSize, &returnedSize); if (err != CL_SUCCESS) { logError("Error: Failed to retrieve device info!", getError(err)); return false; } if(err) { logError("Error creating OpenCL shared with with shared Opengl", getError(err)); return false; } // Create Command Queue auto commandQueue = clCreateCommandQueue(context, computeDeviceId, 0, &err); if (!commandQueue) { logError("Error: Failed to create a command ComputeCommands with shared Opengl!", getError(err)); return false; } _this->deviceId = computeDeviceId; _this->context = context; _this->commandQueue = commandQueue; _this->maxWorkGroupSize = maxWorkGroupSize; _hasCreatedContext = true; _deviceType = DeviceType::GPU_DEVICE; return true; return false; }