[gegl] OpenCl Cache for Buffer regions



commit c3e7b5e6a7a96d0053861f43a3124fcb50bcedaf
Author: Victor Oliveira <victormatheus gmail com>
Date:   Mon Feb 6 10:52:31 2012 -0200

    OpenCl Cache for Buffer regions
    
    Adapting buffer to use OpenCl cache

 gegl/buffer/Makefile.am               |    3 +-
 gegl/buffer/gegl-buffer-access.c      |   17 ++
 gegl/buffer/gegl-buffer-cl-cache.c    |  334 +++++++++++++++++++++++++++++++++
 gegl/buffer/gegl-buffer-cl-cache.h    |   37 ++++
 gegl/buffer/gegl-buffer-cl-iterator.c |  110 ++++++------
 gegl/buffer/gegl-buffer.c             |    3 +
 gegl/gegl-config.c                    |    2 +
 gegl/opencl/gegl-cl-init.c            |    6 +
 gegl/opencl/gegl-cl-init.h            |    6 +
 gegl/opencl/gegl-cl-types.h           |    4 +-
 10 files changed, 466 insertions(+), 56 deletions(-)
---
diff --git a/gegl/buffer/Makefile.am b/gegl/buffer/Makefile.am
index 10f9628..a1b3c18 100644
--- a/gegl/buffer/Makefile.am
+++ b/gegl/buffer/Makefile.am
@@ -21,6 +21,7 @@ libbuffer_la_SOURCES = \
     gegl-buffer-index.h		\
     gegl-buffer-iterator.c	\
     gegl-buffer-cl-iterator.c	\
+    gegl-buffer-cl-cache.c	\
     gegl-buffer-linear.c	\
     gegl-buffer-save.c		\
     gegl-buffer-load.c		\
@@ -50,6 +51,7 @@ libbuffer_la_SOURCES = \
     gegl-buffer-private.h	\
     gegl-buffer-iterator.h	\
     gegl-buffer-cl-iterator.h	\
+    gegl-buffer-cl-cache.h	\
     gegl-buffer-load.h		\
     gegl-buffer-save.h		\
     gegl-buffer-types.h		\
@@ -76,4 +78,3 @@ libbuffer_la_SOURCES = \
     gegl-tile-handler-log.h	\
     gegl-tile-handler-zoom.h	\
     gegl-id-pool.h
-
diff --git a/gegl/buffer/gegl-buffer-access.c b/gegl/buffer/gegl-buffer-access.c
index b063022..3f2f8c9 100644
--- a/gegl/buffer/gegl-buffer-access.c
+++ b/gegl/buffer/gegl-buffer-access.c
@@ -947,6 +947,20 @@ gegl_buffer_get_unlocked (GeglBuffer          *buffer,
     }
 #endif
 
+  if (cl_state.is_accelerated)
+    {
+      if (GEGL_FLOAT_EQUAL (scale, 1.0))
+        {
+          if (gegl_buffer_cl_cache_from (buffer, rect, dest_buf, format, rowstride))
+            return;
+        }
+      else
+        {
+          /* doesn't support scaling in the GPU */
+          gegl_buffer_cl_cache_invalidate (buffer, rect);
+        }
+    }
+
   if (!rect && scale == 1.0)
     {
       gegl_buffer_iterate (buffer, NULL, dest_buf, rowstride, FALSE, format, 0);
@@ -1181,6 +1195,9 @@ gegl_buffer_clear (GeglBuffer          *dst,
 
   pxsize = babl_format_get_bytes_per_pixel (dst->format);
 
+  if (cl_state.is_accelerated)
+    gegl_buffer_cl_cache_remove (dst, dst_rect);
+
   /* FIXME: this can be even further optimized by special casing it so
    * that fully voided tiles are dropped.
    */
diff --git a/gegl/buffer/gegl-buffer-cl-cache.c b/gegl/buffer/gegl-buffer-cl-cache.c
new file mode 100644
index 0000000..c1433b1
--- /dev/null
+++ b/gegl/buffer/gegl-buffer-cl-cache.c
@@ -0,0 +1,334 @@
+#include <glib.h>
+
+#include "gegl.h"
+#include "gegl-utils.h"
+#include "gegl-types-internal.h"
+#include "gegl-buffer-types.h"
+#include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
+#include "gegl-buffer-cl-cache.h"
+#include "opencl/gegl-cl.h"
+
+//#define GEGL_CL_BUFFER_CACHE_LOG
+
+typedef struct
+{
+  GeglBuffer           *buffer;
+  GeglRectangle         roi;
+  cl_mem                tex;
+} CacheEntry;
+
+static GArray *cache_entries = NULL;
+
+typedef struct
+{
+  GeglBuffer   *buffer;
+  GeglBuffer   *buffer_origin;
+  GeglRectangle roi;
+} CacheBuffer;
+
+static CacheBuffer cache_buffer = {NULL, NULL, {-1, -1, -1, -1}};
+
+cl_mem
+gegl_buffer_cl_cache_get (GeglBuffer          *buffer,
+                          const GeglRectangle *roi)
+{
+  gint i;
+
+  if (!roi)
+    roi = &buffer->extent;
+
+  if (G_UNLIKELY (!cache_entries))
+    {
+      cache_entries = g_array_new (TRUE, TRUE, sizeof (CacheEntry));
+    }
+
+  for (i=0; i<cache_entries->len; i++)
+    {
+      CacheEntry *e = &g_array_index (cache_entries, CacheEntry, i);
+      if (e->buffer == buffer && gegl_rectangle_equal (&e->roi, roi))
+        {
+          return e->tex;
+        }
+    }
+  return NULL;
+}
+
+void
+gegl_buffer_cl_cache_new (GeglBuffer            *buffer,
+                          const GeglRectangle   *roi,
+                          cl_mem                 tex)
+{
+  CacheEntry e;
+
+  if (!roi)
+    roi = &buffer->extent;
+
+  e.buffer =  buffer;
+  e.roi    = *roi;
+  e.tex    =  tex;
+
+  if (G_UNLIKELY (!cache_entries))
+    {
+      cache_entries = g_array_new (TRUE, TRUE, sizeof (CacheEntry));
+    }
+
+  g_array_append_val (cache_entries, e);
+}
+
+gboolean
+gegl_buffer_cl_cache_merge (GeglBuffer          *buffer,
+                            const GeglRectangle *roi)
+{
+  size_t size;
+  gint i;
+  GeglRectangle tmp;
+  cl_int cl_err = 0;
+
+  if (!roi)
+    roi = &buffer->extent;
+
+  gegl_cl_color_babl (buffer->format, NULL, &size);
+
+  if (G_UNLIKELY (!cache_entries))
+    {
+      cache_entries = g_array_new (TRUE, TRUE, sizeof (CacheEntry));
+    }
+
+  for (i=0; i<cache_entries->len; i++)
+    {
+      CacheEntry *entry = &g_array_index (cache_entries, CacheEntry, i);
+      if (entry->buffer == buffer &&
+          gegl_rectangle_intersect (&tmp, roi, &entry->roi))
+        {
+          gpointer data;
+
+          data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), entry->tex, CL_TRUE,
+                                         CL_MAP_READ, 0, roi->width * roi->height * size,
+                                         0, NULL, NULL, &cl_err);
+          if (cl_err != CL_SUCCESS) return FALSE;
+
+          /* tile-ize */
+          gegl_buffer_set (entry->buffer, &entry->roi, entry->buffer->format, data, GEGL_AUTO_ROWSTRIDE);
+
+          cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), entry->tex, data,
+                                                 0, NULL, NULL);
+          if (cl_err != CL_SUCCESS) return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+void
+gegl_buffer_cl_cache_remove (GeglBuffer          *buffer,
+                             const GeglRectangle *roi)
+{
+  GeglRectangle tmp;
+  gint i;
+  gboolean found;
+
+  if (!roi)
+    roi = &buffer->extent;
+
+  if (cache_buffer.buffer_origin == buffer &&
+      gegl_rectangle_intersect (&tmp, &cache_buffer.roi, roi))
+    {
+      gegl_buffer_destroy (cache_buffer.buffer);
+      cache_buffer.buffer_origin = NULL;
+    }
+
+  if (G_UNLIKELY (!cache_entries))
+    {
+      cache_entries = g_array_new (TRUE, TRUE, sizeof (CacheEntry));
+    }
+
+  do
+    {
+      found = FALSE;
+      for (i=0; i<cache_entries->len; i++)
+        {
+          CacheEntry *e = &g_array_index (cache_entries, CacheEntry, i);
+          if (e->buffer == buffer &&
+              gegl_rectangle_intersect (&tmp, roi, &e->roi))
+            {
+              gegl_clReleaseMemObject (e->tex);
+              g_array_remove_index_fast (cache_entries, i);
+              found = TRUE;
+              break;
+            }
+        }
+    }
+  while (found);
+}
+
+void
+gegl_buffer_cl_cache_invalidate (GeglBuffer          *buffer,
+                                 const GeglRectangle *roi)
+{
+  if (G_UNLIKELY (!cache_entries))
+    {
+      cache_entries = g_array_new (TRUE, TRUE, sizeof (CacheEntry));
+      return;
+    }
+
+  if (cache_entries->len > 0)
+    {
+      gegl_buffer_cl_cache_merge (buffer, roi);
+      gegl_clFinish (gegl_cl_get_command_queue ());
+      gegl_buffer_cl_cache_remove (buffer, roi);
+    }
+}
+
+#define CL_ERROR {g_printf("[OpenCL] Error in %s:%d %s - %s\n", __FILE__, __LINE__, __func__, gegl_cl_errstring(cl_err)); goto error;}
+
+gboolean
+gegl_buffer_cl_cache_from (GeglBuffer          *buffer,
+                           const GeglRectangle *roi,
+                           gpointer             dest_buf,
+                           const Babl          *format,
+                           gint                 rowstride)
+{
+  size_t buf_size, dest_size;
+  cl_mem tex_dest = NULL;
+
+  gint i;
+
+  gegl_cl_color_op conv = gegl_cl_color_supported (buffer->format, format);
+  gegl_cl_color_babl (buffer->format, NULL, &buf_size);
+  gegl_cl_color_babl (format,         NULL, &dest_size);
+
+  if (G_UNLIKELY (!cache_entries))
+    {
+      cache_entries = g_array_new (TRUE, TRUE, sizeof (CacheEntry));
+    }
+
+  if (cache_entries->len == 0)
+    return FALSE;
+
+  if (roi->width >= 256 && roi->height >= 256) /* no point in using the GPU to get small textures */
+    for (i=0; i<cache_entries->len; i++)
+      {
+        CacheEntry *entry = &g_array_index (cache_entries, CacheEntry, i);
+        if (entry->buffer == buffer && gegl_rectangle_contains (&entry->roi, roi))
+          {
+            cl_int cl_err;
+            const size_t origin_buf[3] = {(entry->roi.x - roi->x) * buf_size,  roi->y - entry->roi.y, 0};
+            const size_t region_buf[3] = {(roi->width) * buf_size,  roi->height, 1};
+
+            /* const size_t origin_dest[3] = {(entry->roi.x - roi->x) * dest_size, roi->y - entry->roi.y, 0};
+               const size_t region_dest[3] = {(roi->width) * dest_size, roi->height, 1}; */
+
+            const size_t origin_zero[3] = {0, 0, 0};
+
+            switch (conv)
+              {
+                case GEGL_CL_COLOR_NOT_SUPPORTED:
+
+                {
+                gegl_buffer_cl_cache_invalidate (buffer, &entry->roi);
+
+                return FALSE;
+                }
+
+                case GEGL_CL_COLOR_EQUAL:
+
+                {
+                cl_err = gegl_clEnqueueReadBufferRect (gegl_cl_get_command_queue (),
+                                                       entry->tex, TRUE,
+                                                       origin_buf, origin_zero, region_buf,
+                                                       0, 0,
+                                                       (rowstride == GEGL_AUTO_ROWSTRIDE)? 0 : rowstride, 0,
+                                                       dest_buf,
+                                                       0, NULL, NULL);
+                if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                gegl_clFinish (gegl_cl_get_command_queue ());
+
+                return TRUE;
+                }
+
+                case GEGL_CL_COLOR_CONVERT:
+
+                {
+                if (cache_buffer.buffer &&
+                    cache_buffer.buffer_origin == buffer &&
+                    cache_buffer.buffer->format == format &&
+                    gegl_rectangle_contains (&cache_buffer.roi, roi))
+                  {
+                    gegl_buffer_get (cache_buffer.buffer,
+                                     1.0,
+                                     roi,
+                                     format,
+                                     dest_buf,
+                                     rowstride);
+                    return TRUE;
+                  }
+                else
+                  {
+                    gpointer data;
+
+                    if (cache_buffer.buffer)
+                      {
+                        gegl_buffer_destroy (cache_buffer.buffer);
+                        cache_buffer.buffer_origin = NULL;
+                      }
+
+                    cache_buffer.buffer        = gegl_buffer_new (&entry->roi, format);
+                    cache_buffer.buffer_origin = buffer;
+                    cache_buffer.roi           = entry->roi;
+
+                    tex_dest = gegl_clCreateBuffer (gegl_cl_get_context (),
+                                                    CL_MEM_WRITE_ONLY,
+                                                    entry->roi.width * entry->roi.height * dest_size,
+                                                    NULL, &cl_err);
+                    if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                    cl_err = gegl_cl_color_conv (entry->tex, tex_dest, entry->roi.width * entry->roi.height, buffer->format, format);
+                    if (cl_err == FALSE) CL_ERROR;
+
+                    data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), tex_dest, CL_TRUE,
+                                                   CL_MAP_READ,
+                                                   0, entry->roi.width * entry->roi.height * dest_size,
+                                                   0, NULL, NULL, &cl_err);
+                    if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                    gegl_buffer_set (cache_buffer.buffer, &entry->roi, format, data, GEGL_AUTO_ROWSTRIDE);
+
+                    cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), tex_dest, data,
+                                                           0, NULL, NULL);
+                    if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                    gegl_clFinish (gegl_cl_get_command_queue ());
+
+                    gegl_buffer_get (cache_buffer.buffer,
+                                     1.0,
+                                     roi,
+                                     format,
+                                     dest_buf,
+                                     rowstride);
+
+                    if (tex_dest) gegl_clReleaseMemObject (tex_dest);
+
+                    return TRUE;
+                  }
+                }
+              }
+          }
+      }
+
+  gegl_buffer_cl_cache_invalidate (buffer, roi);
+
+  return FALSE;
+
+error:
+
+  /* this function isn`t supposed to fail, there is no memory alloc here */
+  gegl_buffer_cl_cache_invalidate (buffer, roi);
+
+  if (tex_dest) gegl_clReleaseMemObject (tex_dest);
+
+  return FALSE;
+}
+
+#undef CL_ERROR
diff --git a/gegl/buffer/gegl-buffer-cl-cache.h b/gegl/buffer/gegl-buffer-cl-cache.h
new file mode 100644
index 0000000..4145558
--- /dev/null
+++ b/gegl/buffer/gegl-buffer-cl-cache.h
@@ -0,0 +1,37 @@
+#ifndef __GEGL_BUFFER_CL_CACHE_H__
+#define __GEGL_BUFFER_CL_CACHE_H__
+
+#include "gegl.h"
+#include "gegl-types-internal.h"
+#include "gegl-buffer-types.h"
+#include "gegl-buffer.h"
+#include "gegl-buffer-private.h"
+#include "opencl/gegl-cl.h"
+
+cl_mem
+gegl_buffer_cl_cache_get (GeglBuffer          *buffer,
+                          const GeglRectangle *roi);
+
+void
+gegl_buffer_cl_cache_new (GeglBuffer            *buffer,
+                          const GeglRectangle   *roi,
+                          cl_mem                 tex);
+gboolean
+gegl_buffer_cl_cache_merge (GeglBuffer          *buffer,
+                            const GeglRectangle *roi);
+
+void
+gegl_buffer_cl_cache_remove (GeglBuffer          *buffer,
+                             const GeglRectangle *roi);
+
+void
+gegl_buffer_cl_cache_invalidate (GeglBuffer          *buffer,
+                                 const GeglRectangle *roi);
+
+gboolean
+gegl_buffer_cl_cache_from (GeglBuffer          *buffer,
+                           const GeglRectangle *roi,
+                           gpointer             dest_buf,
+                           const Babl          *format,
+                           gint                 rowstride);
+#endif
diff --git a/gegl/buffer/gegl-buffer-cl-iterator.c b/gegl/buffer/gegl-buffer-cl-iterator.c
index bce2bbe..9456ba8 100644
--- a/gegl/buffer/gegl-buffer-cl-iterator.c
+++ b/gegl/buffer/gegl-buffer-cl-iterator.c
@@ -10,6 +10,7 @@
 
 #include "gegl-buffer-types.h"
 #include "gegl-buffer-cl-iterator.h"
+#include "gegl-buffer-cl-cache.h"
 #include "gegl-buffer-private.h"
 #include "gegl-tile-storage.h"
 #include "gegl-utils.h"
@@ -202,18 +203,9 @@ gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator, gboolean *err)
                     }
                   else
                     {
-                      data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), i->tex_buf[no][j], CL_TRUE,
-                                                     CL_MAP_READ,
-                                                     0, i->size[no][j] * i->buf_cl_format_size [no],
-                                                     0, NULL, NULL, &cl_err);
-                      if (cl_err != CL_SUCCESS) CL_ERROR;
-
-                      /* color conversion has already been performed in the GPU */
-                      gegl_buffer_set (i->buffer[no], &i->roi[no][j], i->buffer[no]->format, data, GEGL_AUTO_ROWSTRIDE);
-
-                      cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex_buf[no][j], data,
-                                                             0, NULL, NULL);
-                      if (cl_err != CL_SUCCESS) CL_ERROR;
+                      gegl_buffer_cl_cache_new (i->buffer[no], &i->roi[no][j], i->tex_buf[no][j]);
+                      /* don't release this texture */
+                      i->tex_buf[no][j] = NULL;
                     }
                 }
             }
@@ -290,26 +282,31 @@ gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator, gboolean *err)
                   case GEGL_CL_COLOR_EQUAL:
 
                     {
-                    g_assert (i->tex_buf[no][j] == NULL);
-                    i->tex_buf[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
-                                                             CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
-                                                             i->size[no][j] * i->buf_cl_format_size [no],
-                                                             NULL, &cl_err);
-                    if (cl_err != CL_SUCCESS) CL_ERROR;
-
-                    /* pre-pinned memory */
-                    data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), i->tex_buf[no][j], CL_TRUE,
-                                                   CL_MAP_WRITE,
-                                                   0, i->size[no][j] * i->buf_cl_format_size [no],
-                                                   0, NULL, NULL, &cl_err);
-                    if (cl_err != CL_SUCCESS) CL_ERROR;
-
-                    /* color conversion will be performed in the GPU later */
-                    gegl_buffer_get (i->buffer[no], 1.0, &i->roi[no][j], i->buffer[no]->format, data, GEGL_AUTO_ROWSTRIDE);
-
-                    cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex_buf[no][j], data,
-                                                           0, NULL, NULL);
-                    if (cl_err != CL_SUCCESS) CL_ERROR;
+                    i->tex_buf[no][j] = gegl_buffer_cl_cache_get (i->buffer[no], &i->roi[no][j]);
+
+                    if (i->tex_buf[no][j] == NULL)
+                      {
+                        g_assert (i->tex_buf[no][j] == NULL);
+                        i->tex_buf[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
+                                                                 CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
+                                                                 i->size[no][j] * i->buf_cl_format_size [no],
+                                                                 NULL, &cl_err);
+                        if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                        /* pre-pinned memory */
+                        data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), i->tex_buf[no][j], CL_TRUE,
+                                                       CL_MAP_WRITE,
+                                                       0, i->size[no][j] * i->buf_cl_format_size [no],
+                                                       0, NULL, NULL, &cl_err);
+                        if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                        /* color conversion will be performed in the GPU later */
+                        gegl_buffer_get (i->buffer[no], 1.0, &i->roi[no][j], i->buffer[no]->format, data, GEGL_AUTO_ROWSTRIDE);
+
+                        cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex_buf[no][j], data,
+                                                               0, NULL, NULL);
+                        if (cl_err != CL_SUCCESS) CL_ERROR;
+                      }
 
                     i->tex[no][j] = i->tex_buf[no][j];
 
@@ -319,12 +316,31 @@ gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator, gboolean *err)
                   case GEGL_CL_COLOR_CONVERT:
 
                     {
-                    g_assert (i->tex_buf[no][j] == NULL);
-                    i->tex_buf[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
-                                                             CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
-                                                             i->size[no][j] * i->buf_cl_format_size [no],
-                                                             NULL, &cl_err);
-                    if (cl_err != CL_SUCCESS) CL_ERROR;
+                    i->tex_buf[no][j] = gegl_buffer_cl_cache_get (i->buffer[no], &i->roi[no][j]);
+
+                    if (i->tex_buf[no][j] == NULL)
+                      {
+                        g_assert (i->tex_buf[no][j] == NULL);
+                        i->tex_buf[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
+                                                                 CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY,
+                                                                 i->size[no][j] * i->buf_cl_format_size [no],
+                                                                 NULL, &cl_err);
+                        if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                        /* pre-pinned memory */
+                        data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), i->tex_buf[no][j], CL_TRUE,
+                                                       CL_MAP_WRITE,
+                                                       0, i->size[no][j] * i->buf_cl_format_size [no],
+                                                       0, NULL, NULL, &cl_err);
+                        if (cl_err != CL_SUCCESS) CL_ERROR;
+
+                        /* color conversion will be performed in the GPU later */
+                        gegl_buffer_get (i->buffer[no], 1.0, &i->roi[no][j], i->buffer[no]->format, data, GEGL_AUTO_ROWSTRIDE);
+
+                        cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex_buf[no][j], data,
+                                                               0, NULL, NULL);
+                        if (cl_err != CL_SUCCESS) CL_ERROR;
+                      }
 
                     g_assert (i->tex_op[no][j] == NULL);
                     i->tex_op[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
@@ -333,20 +349,6 @@ gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator, gboolean *err)
                                                             NULL, &cl_err);
                     if (cl_err != CL_SUCCESS) CL_ERROR;
 
-                    /* pre-pinned memory */
-                    data = gegl_clEnqueueMapBuffer(gegl_cl_get_command_queue(), i->tex_buf[no][j], CL_TRUE,
-                                                   CL_MAP_WRITE,
-                                                   0, i->size[no][j] * i->buf_cl_format_size [no],
-                                                   0, NULL, NULL, &cl_err);
-                    if (cl_err != CL_SUCCESS) CL_ERROR;
-
-                    /* color conversion will be performed in the GPU later */
-                    gegl_buffer_get (i->buffer[no], 1.0, &i->roi[no][j], i->buffer[no]->format, data, GEGL_AUTO_ROWSTRIDE);
-
-                    cl_err = gegl_clEnqueueUnmapMemObject (gegl_cl_get_command_queue(), i->tex_buf[no][j], data,
-                                                           0, NULL, NULL);
-                    if (cl_err != CL_SUCCESS) CL_ERROR;
-
                     /* color conversion in the GPU (input) */
                     g_assert (i->tex_buf[no][j] && i->tex_op[no][j]);
                     cl_err = gegl_cl_color_conv (i->tex_buf[no][j], i->tex_op[no][j], i->size[no][j],
@@ -390,7 +392,7 @@ gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator, gboolean *err)
                   {
                   g_assert (i->tex_buf[no][j] == NULL);
                   i->tex_buf[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
-                                                           CL_MEM_ALLOC_HOST_PTR | CL_MEM_WRITE_ONLY,
+                                                           CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, /* cache */
                                                            i->size[no][j] * i->buf_cl_format_size [no],
                                                            NULL, &cl_err);
                   if (cl_err != CL_SUCCESS) CL_ERROR;
@@ -405,7 +407,7 @@ gegl_buffer_cl_iterator_next (GeglBufferClIterator *iterator, gboolean *err)
                   {
                   g_assert (i->tex_buf[no][j] == NULL);
                   i->tex_buf[no][j] = gegl_clCreateBuffer (gegl_cl_get_context (),
-                                                           CL_MEM_ALLOC_HOST_PTR | CL_MEM_WRITE_ONLY,
+                                                           CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, /* cache */
                                                            i->size[no][j] * i->buf_cl_format_size [no],
                                                            NULL, &cl_err);
                   if (cl_err != CL_SUCCESS) CL_ERROR;
diff --git a/gegl/buffer/gegl-buffer.c b/gegl/buffer/gegl-buffer.c
index c09fef6..17a22fa 100644
--- a/gegl/buffer/gegl-buffer.c
+++ b/gegl/buffer/gegl-buffer.c
@@ -372,6 +372,9 @@ gegl_buffer_dispose (GObject *object)
 
   gegl_buffer_sample_cleanup (buffer);
 
+  if (cl_state.is_accelerated)
+    gegl_buffer_cl_cache_invalidate (GEGL_BUFFER (object), NULL);
+
   if (handler->source &&
       GEGL_IS_TILE_STORAGE (handler->source))
     {
diff --git a/gegl/gegl-config.c b/gegl/gegl-config.c
index 9232e93..90385bf 100644
--- a/gegl/gegl-config.c
+++ b/gegl/gegl-config.c
@@ -24,6 +24,8 @@
 #include "gegl-types-internal.h"
 #include "gegl-config.h"
 
+#include "opencl/gegl-cl.h"
+
 G_DEFINE_TYPE (GeglConfig, gegl_config, G_TYPE_OBJECT)
 
 static GObjectClass * parent_class = NULL;
diff --git a/gegl/opencl/gegl-cl-init.c b/gegl/opencl/gegl-cl-init.c
index 7a0ea89..da665b5 100644
--- a/gegl/opencl/gegl-cl-init.c
+++ b/gegl/opencl/gegl-cl-init.c
@@ -184,6 +184,12 @@ gegl_cl_init (GError **error)
       CL_LOAD_FUNCTION (clEnqueueWriteBuffer)
       CL_LOAD_FUNCTION (clEnqueueReadBuffer)
       CL_LOAD_FUNCTION (clEnqueueCopyBuffer)
+      CL_LOAD_FUNCTION (clEnqueueCopyBuffer)
+      CL_LOAD_FUNCTION (clEnqueueCopyBuffer)
+      CL_LOAD_FUNCTION (clEnqueueCopyBuffer)
+      CL_LOAD_FUNCTION (clEnqueueReadBufferRect)
+      CL_LOAD_FUNCTION (clEnqueueWriteBufferRect)
+      CL_LOAD_FUNCTION (clEnqueueCopyBufferRect)
       CL_LOAD_FUNCTION (clCreateImage2D)
       CL_LOAD_FUNCTION (clEnqueueWriteImage)
       CL_LOAD_FUNCTION (clEnqueueReadImage)
diff --git a/gegl/opencl/gegl-cl-init.h b/gegl/opencl/gegl-cl-init.h
index b69de92..583e76a 100644
--- a/gegl/opencl/gegl-cl-init.h
+++ b/gegl/opencl/gegl-cl-init.h
@@ -76,6 +76,9 @@ t_clCreateBuffer            gegl_clCreateBuffer            = NULL;
 t_clEnqueueWriteBuffer      gegl_clEnqueueWriteBuffer      = NULL;
 t_clEnqueueReadBuffer       gegl_clEnqueueReadBuffer       = NULL;
 t_clEnqueueCopyBuffer       gegl_clEnqueueCopyBuffer       = NULL;
+t_clEnqueueReadBufferRect   gegl_clEnqueueReadBufferRect   = NULL;
+t_clEnqueueWriteBufferRect  gegl_clEnqueueWriteBufferRect  = NULL;
+t_clEnqueueCopyBufferRect   gegl_clEnqueueCopyBufferRect   = NULL;
 t_clCreateImage2D           gegl_clCreateImage2D           = NULL;
 t_clEnqueueWriteImage       gegl_clEnqueueWriteImage       = NULL;
 t_clEnqueueReadImage        gegl_clEnqueueReadImage        = NULL;
@@ -118,6 +121,9 @@ extern t_clGetKernelWorkGroupInfo  gegl_clGetKernelWorkGroupInfo;
 extern t_clCreateBuffer            gegl_clCreateBuffer;
 extern t_clEnqueueWriteBuffer      gegl_clEnqueueWriteBuffer;
 extern t_clEnqueueReadBuffer       gegl_clEnqueueReadBuffer;
+extern t_clEnqueueReadBufferRect   gegl_clEnqueueReadBufferRect;
+extern t_clEnqueueWriteBufferRect  gegl_clEnqueueWriteBufferRect;
+extern t_clEnqueueCopyBufferRect   gegl_clEnqueueCopyBufferRect;
 extern t_clCreateImage2D           gegl_clCreateImage2D;
 extern t_clEnqueueWriteImage       gegl_clEnqueueWriteImage;
 extern t_clEnqueueReadImage        gegl_clEnqueueReadImage;
diff --git a/gegl/opencl/gegl-cl-types.h b/gegl/opencl/gegl-cl-types.h
index 4e94b76..e51fc9a 100644
--- a/gegl/opencl/gegl-cl-types.h
+++ b/gegl/opencl/gegl-cl-types.h
@@ -44,7 +44,9 @@ typedef CL_API_ENTRY cl_mem            (CL_API_CALL *t_clCreateBuffer
 typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueWriteBuffer     ) (cl_command_queue, cl_mem, cl_bool, size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *);
 typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueReadBuffer      ) (cl_command_queue, cl_mem, cl_bool, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *);
 typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueCopyBuffer      ) (cl_command_queue, cl_mem, cl_mem,  size_t, size_t, size_t, cl_uint, const cl_event *, cl_event *);
-
+typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueReadBufferRect  ) (cl_command_queue, cl_mem, cl_bool, const size_t [3], const size_t [3], const size_t [3], size_t, size_t, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *);
+typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueWriteBufferRect ) (cl_command_queue, cl_mem, cl_bool, const size_t [3], const size_t [3], const size_t [3], size_t, size_t, size_t, size_t, void *, cl_uint, const cl_event *, cl_event *);
+typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueCopyBufferRect  ) (cl_command_queue, cl_mem, cl_mem, const size_t [3], const size_t [3], const size_t [3], size_t, size_t, size_t, size_t, cl_uint, const cl_event *, cl_event *);
 typedef CL_API_ENTRY cl_mem            (CL_API_CALL *t_clCreateImage2D          ) (cl_context, cl_mem_flags, const cl_image_format *, size_t, size_t, size_t, void *, cl_int *);
 typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueReadImage       ) (cl_command_queue, cl_mem, cl_bool, const size_t [3], const size_t [3], size_t, size_t, void *, cl_uint, const cl_event *, cl_event *);
 typedef CL_API_ENTRY cl_int            (CL_API_CALL *t_clEnqueueWriteImage      ) (cl_command_queue, cl_mem, cl_bool, const size_t [3], const size_t [3], size_t, size_t, const void *, cl_uint, const cl_event *, cl_event *);



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