diff options
Diffstat (limited to 'src/cl-utils.c')
-rw-r--r-- | src/cl-utils.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/cl-utils.c b/src/cl-utils.c new file mode 100644 index 00000000..65a09363 --- /dev/null +++ b/src/cl-utils.c @@ -0,0 +1,200 @@ +/* + * cl-utils.c + * + * OpenCL utility functions + * + * (c) 2006-2011 Thomas White <taw@physics.org> + * + * Part of CrystFEL - crystallography with a FEL + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_CL_CL_H +#include <CL/cl.h> +#else +#include <cl.h> +#endif + +#include "utils.h" + + +const char *clError(cl_int err) +{ + switch ( err ) { + case CL_SUCCESS : return "no error"; + case CL_INVALID_PLATFORM : return "invalid platform"; + case CL_INVALID_KERNEL : return "invalid kernel"; + case CL_INVALID_ARG_INDEX : return "invalid argument index"; + case CL_INVALID_ARG_VALUE : return "invalid argument value"; + case CL_INVALID_MEM_OBJECT : return "invalid memory object"; + case CL_INVALID_SAMPLER : return "invalid sampler"; + case CL_INVALID_ARG_SIZE : return "invalid argument size"; + case CL_INVALID_COMMAND_QUEUE : return "invalid command queue"; + case CL_INVALID_CONTEXT : return "invalid context"; + case CL_INVALID_VALUE : return "invalid value"; + case CL_INVALID_EVENT_WAIT_LIST : return "invalid wait list"; + case CL_MAP_FAILURE : return "map failure"; + case CL_MEM_OBJECT_ALLOCATION_FAILURE : return "object allocation failure"; + case CL_OUT_OF_HOST_MEMORY : return "out of host memory"; + case CL_OUT_OF_RESOURCES : return "out of resources"; + case CL_INVALID_KERNEL_NAME : return "invalid kernel name"; + case CL_INVALID_KERNEL_ARGS : return "invalid kernel arguments"; + case CL_INVALID_WORK_GROUP_SIZE : return "invalid work group size"; + case CL_IMAGE_FORMAT_NOT_SUPPORTED : return "image format not supported"; + case CL_INVALID_WORK_DIMENSION : return "invalid work dimension"; + default : + return "unknown error"; + } +} + + +static char *get_device_string(cl_device_id dev, cl_device_info info) +{ + int r; + size_t size; + char *val; + + r = clGetDeviceInfo(dev, info, 0, NULL, &size); + if ( r != CL_SUCCESS ) { + ERROR("Couldn't get device vendor size: %s\n", + clError(r)); + return NULL; + } + val = malloc(size); + r = clGetDeviceInfo(dev, info, size, val, NULL); + if ( r != CL_SUCCESS ) { + ERROR("Couldn't get dev vendor: %s\n", clError(r)); + return NULL; + } + + return val; +} + + +cl_device_id get_cl_dev(cl_context ctx, int n) +{ + cl_device_id *dev; + cl_int r; + size_t size; + int i, num_devs; + + /* Get the required size of the array */ + r = clGetContextInfo(ctx, CL_CONTEXT_DEVICES, 0, NULL, &size); + if ( r != CL_SUCCESS ) { + ERROR("Couldn't get array size for devices: %s\n", clError(r)); + return 0; + } + + dev = malloc(size); + r = clGetContextInfo(ctx, CL_CONTEXT_DEVICES, size, dev, NULL); + if ( r != CL_SUCCESS ) { + ERROR("Couldn't get device: %s\n", clError(r)); + return 0; + } + num_devs = size/sizeof(cl_device_id); + + if ( n >= num_devs ) { + ERROR("Device ID out of range\n"); + return 0; + } + + if ( n < 0 ) { + + STATUS("Available devices:\n"); + for ( i=0; i<num_devs; i++ ) { + + char *vendor; + char *name; + + vendor = get_device_string(dev[i], CL_DEVICE_VENDOR); + name = get_device_string(dev[i], CL_DEVICE_NAME); + + STATUS("Device %i: %s %s\n", i, vendor, name); + + } + n = 0; + + STATUS("Using device 0. Use --gpu-dev to choose another.\n"); + + } else { + + char *vendor; + char *name; + + vendor = get_device_string(dev[n], CL_DEVICE_VENDOR); + name = get_device_string(dev[n], CL_DEVICE_NAME); + + STATUS("Using device %i: %s %s\n", n, vendor, name); + + } + + return dev[n]; +} + + +static void show_build_log(cl_program prog, cl_device_id dev) +{ + cl_int r; + char log[4096]; + size_t s; + + r = clGetProgramBuildInfo(prog, dev, CL_PROGRAM_BUILD_LOG, 4096, log, + &s); + + STATUS("%s\n", log); +} + + +cl_program load_program(const char *filename, cl_context ctx, + cl_device_id dev, cl_int *err, const char *extra_cflags) +{ + FILE *fh; + cl_program prog; + char *source; + size_t len; + cl_int r; + char cflags[1024] = ""; + + fh = fopen(filename, "r"); + if ( fh == NULL ) { + ERROR("Couldn't open '%s'\n", filename); + *err = CL_INVALID_PROGRAM; + return 0; + } + source = malloc(16384); + len = fread(source, 1, 16383, fh); + fclose(fh); + source[len] = '\0'; + + prog = clCreateProgramWithSource(ctx, 1, (const char **)&source, + NULL, err); + if ( *err != CL_SUCCESS ) { + ERROR("Couldn't load source\n"); + return 0; + } + + snprintf(cflags, 1023, "-Werror "); + strncat(cflags, "-I"DATADIR"/crystfel/ ", 1023-strlen(cflags)); + strncat(cflags, "-cl-no-signed-zeros ", 1023-strlen(cflags)); + strncat(cflags, extra_cflags, 1023-strlen(cflags)); + + r = clBuildProgram(prog, 0, NULL, cflags, NULL, NULL); + if ( r != CL_SUCCESS ) { + ERROR("Couldn't build program '%s'\n", filename); + show_build_log(prog, dev); + *err = r; + return 0; + } + + free(source); + *err = CL_SUCCESS; + return prog; +} |