[gegl/gsoc2011-opencl: 15/21] cache for OpenCL kernel compilation



commit cf91b092056548828afdde782710455a5de2ef85
Author: Victor Oliveira <victormatheus gmail com>
Date:   Thu Aug 18 13:33:03 2011 -0300

    cache for OpenCL kernel compilation

 gegl/opencl/gegl-cl-init.c |   63 +++++++++++++++++++++++++++++++++++++++++---
 gegl/opencl/gegl-cl-init.h |   14 +++++++++-
 2 files changed, 72 insertions(+), 5 deletions(-)
---
diff --git a/gegl/opencl/gegl-cl-init.c b/gegl/opencl/gegl-cl-init.c
index aaf1bcc..3c48976 100644
--- a/gegl/opencl/gegl-cl-init.c
+++ b/gegl/opencl/gegl-cl-init.c
@@ -1,11 +1,12 @@
-#define __GEGL_CL_INIT_MAIN__
-#include "gegl-cl-init.h"
-#undef __GEGL_CL_INIT_MAIN__
-
+#include <glib.h>
 #include <gmodule.h>
 #include <string.h>
 #include <stdio.h>
 
+#define __GEGL_CL_INIT_MAIN__
+#include "gegl-cl-init.h"
+#undef __GEGL_CL_INIT_MAIN__
+
 guint
 gegl_cl_count_lines(const char* kernel_source[])
 {
@@ -73,6 +74,7 @@ static cl_platform_id   platform = NULL;
 static cl_device_id     device   = NULL;
 static cl_context       ctx      = NULL;
 static cl_command_queue cq       = NULL;
+static GHashTable *cl_program_hash = NULL;
 
 gboolean
 gegl_cl_is_accelerated (void)
@@ -187,9 +189,62 @@ gegl_cl_init (GError **error)
 
       ctx = gegl_clCreateContext(0, 1, &device, NULL, NULL, NULL);
       cq  = gegl_clCreateCommandQueue(ctx, device, 0, NULL);
+
+      /* XXX: is this dict being leaked? */
+      cl_program_hash = g_hash_table_new (g_str_hash, g_str_equal);
     }
 
   return TRUE;
 }
 
 #undef CL_LOAD_FUNCTION
+
+/* TODO: same program_source with different kernel_name[], context or device
+ *       will retrieve the same key
+ */
+gegl_cl_run_data *
+gegl_cl_compile_and_build (const char *program_source, cl_context ctx, cl_device_id device,
+                           const char *kernel_name[])
+{
+  gint errcode;
+  gegl_cl_run_data *cl_data = NULL;
+
+  if ((cl_data = (gegl_cl_run_data *)g_hash_table_lookup(cl_program_hash, program_source)) == NULL)
+    {
+      size_t length = strlen(program_source);
+
+      gint i;
+      guint kernel_n = 0;
+      while (kernel_name[++kernel_n] != NULL);
+
+      cl_data = (gegl_cl_run_data *) g_malloc(sizeof(gegl_cl_run_data)+sizeof(cl_kernel)*kernel_n);
+
+      CL_SAFE_CALL( cl_data->program = gegl_clCreateProgramWithSource(ctx, 1, &program_source,
+                                                                      &length, &errcode) );
+      cl_data->ctx    = ctx;
+      cl_data->device = device;
+
+      errcode = gegl_clBuildProgram(cl_data->program, 0, NULL, NULL, NULL, NULL);
+      if (errcode != CL_SUCCESS)
+        {
+          char buffer[2000];
+          char *err_msg;
+          CL_SAFE_CALL( errcode = gegl_clGetProgramBuildInfo(cl_data->program,
+                                                             cl_data->device,
+                                                             CL_PROGRAM_BUILD_LOG,
+                                                             sizeof(buffer), buffer, NULL) );
+          g_warning("OpenCL Build Error:%s\n%s",
+                    err_msg = gegl_cl_errstring(errcode), buffer);
+          free(err_msg);
+          return NULL;
+        }
+
+      for (i=0; i<kernel_n; i++)
+        CL_SAFE_CALL( cl_data->kernel[i] =
+                      gegl_clCreateKernel(cl_data->program, kernel_name[i], &errcode) );
+
+      g_hash_table_insert(cl_program_hash, g_strdup (program_source), (void*)cl_data);
+    }
+
+  return cl_data;
+}
diff --git a/gegl/opencl/gegl-cl-init.h b/gegl/opencl/gegl-cl-init.h
index 58c13b6..62e2d02 100644
--- a/gegl/opencl/gegl-cl-init.h
+++ b/gegl/opencl/gegl-cl-init.h
@@ -1,8 +1,8 @@
 #ifndef __GEGL_CL_INIT_H__
 #define __GEGL_CL_INIT_H__
 
-#include "gegl-cl-types.h"
 #include <gmodule.h>
+#include "gegl-cl-types.h"
 
 #define CL_SAFE_CALL(func)                                          \
 func;                                                               \
@@ -28,6 +28,18 @@ cl_context gegl_cl_get_context (void);
 
 cl_command_queue gegl_cl_get_command_queue (void);
 
+typedef struct _gegl_cl_run_data
+{
+  cl_context ctx;
+  cl_device_id device;
+  cl_program program;
+  cl_kernel  kernel[];
+} gegl_cl_run_data;
+
+gegl_cl_run_data *gegl_cl_compile_and_build (const char *program_source,
+                                             cl_context ctx, cl_device_id device,
+                                             const char *kernel_name[]);
+
 #ifdef __GEGL_CL_INIT_MAIN__
 t_clGetPlatformIDs  gegl_clGetPlatformIDs  = NULL;
 t_clGetPlatformInfo gegl_clGetPlatformInfo = NULL;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]