#include #include #include "ocl_utilities.h" /* Return the OpenCL error string for a given error number. */ const char *opencl_error_string(cl_int error) { int errorCount; int index; static const char *errorString[] = { [CL_SUCCESS] = "CL_SUCCESS", [-CL_DEVICE_NOT_FOUND] = "CL_DEVICE_NOT_FOUND", [-CL_DEVICE_NOT_AVAILABLE] = "CL_DEVICE_NOT_AVAILABLE", [-CL_COMPILER_NOT_AVAILABLE] = "CL_COMPILER_NOT_AVAILABLE", [-CL_MEM_OBJECT_ALLOCATION_FAILURE] = "CL_MEM_OBJECT_ALLOCATION_FAILURE", [-CL_OUT_OF_RESOURCES] = "CL_OUT_OF_RESOURCES", [-CL_OUT_OF_HOST_MEMORY] = "CL_OUT_OF_HOST_MEMORY", [-CL_PROFILING_INFO_NOT_AVAILABLE] = "CL_PROFILING_INFO_NOT_AVAILABLE", [-CL_MEM_COPY_OVERLAP] = "CL_MEM_COPY_OVERLAP", [-CL_IMAGE_FORMAT_MISMATCH] = "CL_IMAGE_FORMAT_MISMATCH", [-CL_IMAGE_FORMAT_NOT_SUPPORTED] = "CL_IMAGE_FORMAT_NOT_SUPPORTED", [-CL_BUILD_PROGRAM_FAILURE] = "CL_BUILD_PROGRAM_FAILURE", [-CL_MAP_FAILURE] = "CL_MAP_FAILURE", [-CL_INVALID_VALUE] = "CL_INVALID_VALUE", [-CL_INVALID_DEVICE_TYPE] = "CL_INVALID_DEVICE_TYPE", [-CL_INVALID_PLATFORM] = "CL_INVALID_PLATFORM", [-CL_INVALID_DEVICE] = "CL_INVALID_DEVICE", [-CL_INVALID_CONTEXT] = "CL_INVALID_CONTEXT", [-CL_INVALID_QUEUE_PROPERTIES] = "CL_INVALID_QUEUE_PROPERTIES", [-CL_INVALID_COMMAND_QUEUE] = "CL_INVALID_COMMAND_QUEUE", [-CL_INVALID_HOST_PTR] = "CL_INVALID_HOST_PTR", [-CL_INVALID_MEM_OBJECT] = "CL_INVALID_MEM_OBJECT", [-CL_INVALID_IMAGE_FORMAT_DESCRIPTOR] = "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR", [-CL_INVALID_IMAGE_SIZE] = "CL_INVALID_IMAGE_SIZE", [-CL_INVALID_SAMPLER] = "CL_INVALID_SAMPLER", [-CL_INVALID_BINARY] = "CL_INVALID_BINARY", [-CL_INVALID_BUILD_OPTIONS] = "CL_INVALID_BUILD_OPTIONS", [-CL_INVALID_PROGRAM] = "CL_INVALID_PROGRAM", [-CL_INVALID_PROGRAM_EXECUTABLE] = "CL_INVALID_PROGRAM_EXECUTABLE", [-CL_INVALID_KERNEL_NAME] = "CL_INVALID_KERNEL_NAME", [-CL_INVALID_KERNEL_DEFINITION] = "CL_INVALID_KERNEL_DEFINITION", [-CL_INVALID_KERNEL] = "CL_INVALID_KERNEL", [-CL_INVALID_ARG_INDEX] = "CL_INVALID_ARG_INDEX", [-CL_INVALID_ARG_VALUE] = "CL_INVALID_ARG_VALUE", [-CL_INVALID_ARG_SIZE] = "CL_INVALID_ARG_SIZE", [-CL_INVALID_KERNEL_ARGS] = "CL_INVALID_KERNEL_ARGS", [-CL_INVALID_WORK_DIMENSION] = "CL_INVALID_WORK_DIMENSION", [-CL_INVALID_WORK_GROUP_SIZE] = "CL_INVALID_WORK_GROUP_SIZE", [-CL_INVALID_WORK_ITEM_SIZE] = "CL_INVALID_WORK_ITEM_SIZE", [-CL_INVALID_GLOBAL_OFFSET] = "CL_INVALID_GLOBAL_OFFSET", [-CL_INVALID_EVENT_WAIT_LIST] = "CL_INVALID_EVENT_WAIT_LIST", [-CL_INVALID_EVENT] = "CL_INVALID_EVENT", [-CL_INVALID_OPERATION] = "CL_INVALID_OPERATION", [-CL_INVALID_GL_OBJECT] = "CL_INVALID_GL_OBJECT", [-CL_INVALID_BUFFER_SIZE] = "CL_INVALID_BUFFER_SIZE", [-CL_INVALID_MIP_LEVEL] = "CL_INVALID_MIP_LEVEL", [-CL_INVALID_GLOBAL_WORK_SIZE] = "CL_INVALID_GLOBAL_WORK_SIZE", [-CL_INVALID_PROPERTY] = "CL_INVALID_PROPERTY" }; errorCount = sizeof(errorString) / sizeof(errorString[0]); index = -error; return (index >= 0 && index < errorCount) ? errorString[index] : "Unspecified Error"; } /* Find a GPU or a CPU associated with the first available platform. * If use_gpu is set, then this function first tries to look for a GPU * in the first available platform. * If this fails or if use_gpu is not set, then it tries to use the CPU. */ cl_device_id opencl_create_device(int use_gpu) { cl_platform_id platform; cl_device_id dev; int err; err = clGetPlatformIDs(1, &platform, NULL); if (err < 0) { fprintf(stderr, "Error %s while looking for a platform.\n", opencl_error_string(err)); exit(1); } err = CL_DEVICE_NOT_FOUND; if (use_gpu) err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &dev, NULL); if (err == CL_DEVICE_NOT_FOUND) err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 1, &dev, NULL); if (err < 0) { fprintf(stderr, "Error %s while looking for a device.\n", opencl_error_string(err)); exit(1); } return dev; } /* Create an OpenCL program from a string and compile it. */ cl_program opencl_build_program_from_string(cl_context ctx, cl_device_id dev, const char *program_source, size_t program_size, const char *opencl_options) { int err; cl_program program; char *program_log; size_t log_size; program = clCreateProgramWithSource(ctx, 1, &program_source, &program_size, &err); if (err < 0) { fprintf(stderr, "Could not create the program\n"); exit(1); } err = clBuildProgram(program, 0, NULL, opencl_options, NULL, NULL); if (err < 0) { fprintf(stderr, "Could not build the program.\n"); clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size); program_log = (char *) malloc(log_size + 1); program_log[log_size] = '\0'; clGetProgramBuildInfo(program, dev, CL_PROGRAM_BUILD_LOG, log_size + 1, program_log, NULL); fprintf(stderr, "%s\n", program_log); free(program_log); exit(1); } return program; } /* Create an OpenCL program from a source file and compile it. */ cl_program opencl_build_program_from_file(cl_context ctx, cl_device_id dev, const char* filename, const char* opencl_options) { cl_program program; FILE *program_file; char *program_source; size_t program_size, read; program_file = fopen(filename, "r"); if (program_file == NULL) { fprintf(stderr, "Could not find the source file.\n"); exit(1); } fseek(program_file, 0, SEEK_END); program_size = ftell(program_file); rewind(program_file); program_source = (char *) malloc(program_size + 1); program_source[program_size] = '\0'; read = fread(program_source, sizeof(char), program_size, program_file); if (read != program_size) { fprintf(stderr, "Error while reading the kernel.\n"); exit(1); } fclose(program_file); program = opencl_build_program_from_string(ctx, dev, program_source, program_size, opencl_options); free(program_source); return program; }