aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src/cl-utils.c
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2011-11-15 12:17:59 +0100
committerThomas White <taw@physics.org>2012-02-22 15:27:40 +0100
commit469efb904b59f137ac9e85e5ff23edd0c113de5c (patch)
tree71fab5f5715ec9f88984450cdabb592cd49dd46d /libcrystfel/src/cl-utils.c
parent38089071300b8e04ed42236dd08d9055094fb3b8 (diff)
Move a load more stuff into libcrystfel
Diffstat (limited to 'libcrystfel/src/cl-utils.c')
-rw-r--r--libcrystfel/src/cl-utils.c200
1 files changed, 200 insertions, 0 deletions
diff --git a/libcrystfel/src/cl-utils.c b/libcrystfel/src/cl-utils.c
new file mode 100644
index 00000000..65a09363
--- /dev/null
+++ b/libcrystfel/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;
+}