[gegl] OpenCl texture manager



commit e2de30eef60cf3f4c0ff64cf3985bd6d7ec7227c
Author: Victor Oliveira <victormatheus gmail com>
Date:   Wed Jan 4 02:05:42 2012 -0200

    OpenCl texture manager

 gegl/opencl/Makefile.am                      |    5 +-
 gegl/opencl/gegl-cl-texture-manager.c        |  112 ++++++++++++++++++++++++++
 gegl/opencl/gegl-cl-texture-manager.h        |   12 +++
 gegl/operation/gegl-operation-point-filter.c |   29 +++----
 4 files changed, 141 insertions(+), 17 deletions(-)
---
diff --git a/gegl/opencl/Makefile.am b/gegl/opencl/Makefile.am
index ce6edbd..7880ec0 100644
--- a/gegl/opencl/Makefile.am
+++ b/gegl/opencl/Makefile.am
@@ -21,6 +21,7 @@ libcl_public_HEADERS = \
 	gegl-cl-texture.h \
 	gegl-cl-types.h \
 	gegl-cl-color.h \
+	gegl-cl-texture-manager.h \
 	cl_d3d10.h \
 	cl_ext.h \
 	cl_gl_ext.h \
@@ -36,7 +37,9 @@ libcl_sources = \
 	gegl-cl-texture.c \
 	gegl-cl-texture.h \
 	gegl-cl-color.c \
-	gegl-cl-color.h
+	gegl-cl-color.h \
+	gegl-cl-texture-manager.c \
+	gegl-cl-texture-manager.h
 
 noinst_LTLIBRARIES = libcl.la
 
diff --git a/gegl/opencl/gegl-cl-texture-manager.c b/gegl/opencl/gegl-cl-texture-manager.c
new file mode 100644
index 0000000..312adb5
--- /dev/null
+++ b/gegl/opencl/gegl-cl-texture-manager.c
@@ -0,0 +1,112 @@
+#include "gegl-cl-texture.h"
+#include "gegl-cl-texture-manager.h"
+
+typedef struct
+{
+  gint            used;
+  cl_mem_flags    flags;
+  cl_image_format format;
+  cl_mem          data;
+  size_t          width;
+  size_t          height;
+} TextureInfo;
+
+static GArray *tex_pool = NULL;
+
+static GStaticMutex tex_pool_mutex = G_STATIC_MUTEX_INIT;
+
+cl_mem
+gegl_cl_texture_manager_request (cl_mem_flags flags,
+                                 cl_image_format format,
+                                 size_t width, size_t height)
+{
+  gint i;
+  g_static_mutex_lock (&tex_pool_mutex);
+
+  if (G_UNLIKELY (!tex_pool))
+    {
+      tex_pool = g_array_new (TRUE, TRUE, sizeof (TextureInfo));
+    }
+  for (i=0; i<tex_pool->len; i++)
+    {
+      TextureInfo *info = &g_array_index (tex_pool, TextureInfo, i);
+      if (info->flags == flags &&
+          info->format.image_channel_order     == format.image_channel_order     &&
+          info->format.image_channel_data_type == format.image_channel_data_type &&
+          info->width >= width && info->height >= height &&
+          info->used == 0)
+        {
+          info->used ++;
+          g_static_mutex_unlock (&tex_pool_mutex);
+          return info->data;
+        }
+    }
+  {
+    cl_int errcode;
+
+    TextureInfo info;
+    info.used   = 1;
+    info.flags  = flags;
+    info.format = format;
+    info.width  = width;
+    info.height = height;
+    info.data   = gegl_clCreateImage2D (gegl_cl_get_context (),
+                                        info.flags,
+                                        &info.format,
+                                        info.width, info.height,
+                                        0,  NULL, &errcode);
+    if (errcode != CL_SUCCESS)
+      {
+        /* we could try harder here, like releasing
+           unused memory until this works [or not] */
+        g_static_mutex_unlock (&tex_pool_mutex);
+        return NULL;
+      }
+    else
+      {
+        g_printf ("[OpenCL] New Texture {%d %d}\n", info.width, info.height);
+        g_array_append_val (tex_pool, info);
+        g_static_mutex_unlock (&tex_pool_mutex);
+        return info.data;
+      }
+  }
+}
+
+void
+gegl_cl_texture_manager_give (cl_mem data)
+{
+  gint i;
+  g_static_mutex_lock (&tex_pool_mutex);
+  for (i=0; i<tex_pool->len; i++)
+    {
+      TextureInfo *info = &g_array_index (tex_pool, TextureInfo, i);
+      if (info->data == data)
+        {
+          info->used --;
+          g_static_mutex_unlock (&tex_pool_mutex);
+          return;
+        }
+    }
+  g_assert (0);
+  g_static_mutex_unlock (&tex_pool_mutex);
+}
+
+void
+gegl_cl_texture_manager_release (cl_mem data)
+{
+  gint i;
+  g_static_mutex_lock (&tex_pool_mutex);
+  for (i=0; i<tex_pool->len; i++)
+    {
+      TextureInfo *info = &g_array_index (tex_pool, TextureInfo, i);
+      if (info->data == data)
+        {
+          gegl_clReleaseMemObject(info->data);
+          tex_pool = g_array_remove_index_fast (tex_pool, i);
+          g_static_mutex_unlock (&tex_pool_mutex);
+          return;
+        }
+    }
+  g_assert (0);
+  g_static_mutex_unlock (&tex_pool_mutex);
+}
diff --git a/gegl/opencl/gegl-cl-texture-manager.h b/gegl/opencl/gegl-cl-texture-manager.h
new file mode 100644
index 0000000..dd23605
--- /dev/null
+++ b/gegl/opencl/gegl-cl-texture-manager.h
@@ -0,0 +1,12 @@
+#include "gegl-cl-types.h"
+
+cl_mem
+gegl_cl_texture_manager_request (cl_mem_flags flags,
+                                 cl_image_format format,
+                                 size_t width, size_t height);
+
+void
+gegl_cl_texture_manager_give (cl_mem data);
+
+void
+gegl_cl_texture_manager_release (cl_mem data);
diff --git a/gegl/operation/gegl-operation-point-filter.c b/gegl/operation/gegl-operation-point-filter.c
index b2a20f3..b1a59da 100644
--- a/gegl/operation/gegl-operation-point-filter.c
+++ b/gegl/operation/gegl-operation-point-filter.c
@@ -33,6 +33,7 @@
 #include "gegl-tile-storage.h"
 
 #include "opencl/gegl-cl.h"
+#include "opencl/gegl-cl-texture-manager.h"
 
 static gboolean gegl_operation_point_filter_process
                               (GeglOperation       *operation,
@@ -159,19 +160,15 @@ gegl_operation_point_filter_cl_process_full (GeglOperation       *operation,
         GeglRectangle r = {x, y, region[0], region[1]};
         input_tex.region[i] = output_tex.region[i] = r;
 
-        input_tex.tex[i]  = gegl_clCreateImage2D (gegl_cl_get_context(),
-                                                  CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
-                                                  &in_image_format,
-                                                  region[0], region[1],
-                                                  0,  NULL, &errcode);
-        if (errcode != CL_SUCCESS) CL_ERROR;
+        input_tex.tex[i]  = gegl_cl_texture_manager_request (CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
+                                                             in_image_format,
+                                                             region[0], region[1]);
+        if (input_tex.tex[i]  == NULL) CL_ERROR;
 
-        output_tex.tex[i] = gegl_clCreateImage2D (gegl_cl_get_context(),
-                                                  CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
-                                                  &out_image_format,
-                                                  region[0], region[1],
-                                                  0,  NULL, &errcode);
-        if (errcode != CL_SUCCESS) CL_ERROR;
+        output_tex.tex[i] = gegl_cl_texture_manager_request (CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE,
+                                                             out_image_format,
+                                                             region[0], region[1]);
+        if (output_tex.tex[i] == NULL) CL_ERROR;
 
         i++;
       }
@@ -272,8 +269,8 @@ gegl_operation_point_filter_cl_process_full (GeglOperation       *operation,
 
   for (i=0; i < ntex; i++)
     {
-      gegl_clReleaseMemObject (input_tex.tex[i]);
-      gegl_clReleaseMemObject (output_tex.tex[i]);
+      gegl_cl_texture_manager_give (input_tex.tex[i]);
+      gegl_cl_texture_manager_give (output_tex.tex[i]);
     }
 
   g_free(input_tex.tex);
@@ -287,8 +284,8 @@ error:
 
     for (i=0; i < ntex; i++)
       {
-        if (input_tex.tex[i])  gegl_clReleaseMemObject (input_tex.tex[i]);
-        if (output_tex.tex[i]) gegl_clReleaseMemObject (output_tex.tex[i]);
+        if (input_tex.tex[i])  gegl_cl_texture_manager_give (input_tex.tex[i]);
+        if (output_tex.tex[i]) gegl_cl_texture_manager_give (output_tex.tex[i]);
       }
 
   if (input_tex.tex)     g_free(input_tex.tex);



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