diff options
-rw-r--r-- | opencl/dot.cl | 72 | ||||
-rw-r--r-- | opencl/dot.cl.h | 73 | ||||
-rw-r--r-- | operations/common/dot.c | 147 |
3 files changed, 290 insertions, 2 deletions
diff --git a/opencl/dot.cl b/opencl/dot.cl new file mode 100644 index 00000000..b1bd9057 --- /dev/null +++ b/opencl/dot.cl @@ -0,0 +1,72 @@ +/* This file is an image processing operation for GEGL + * + * GEGL is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * GEGL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with GEGL; if not, see <http://www.gnu.org/licenses/>. + * + * Copyright 2013 Carlos Zubieta <czubieta.dev@gmail.com> + */ + +__kernel void cl_calc_block_colors (__global const float4 *in, + __global float4 *block_colors, + int cx0, + int cy0, + int size, + float weight, + int roi_x, + int roi_y, + int line_width) +{ + int cx = cx0 + get_global_id(0); + int cy = cy0 + get_global_id(1); + int px = (cx * size) - roi_x + size; + int py = (cy * size) - roi_y + size; + float4 mean = (float4)(0.0f); + float4 tmp; + int i, j; + + for( j = py; j < py+size; ++j) + { + for (i = px; i < px+size; ++i) + { + mean += in[j * line_width + i]; + } + } + block_colors[(cx-cx0) + get_global_size(0) * (cy-cy0)] = mean*weight; +} + +__kernel void cl_dot (__global const float4 *block_colors, + __global float4 *out, + int cx0, + int cy0, + int size, + float radius2, + int roi_x, + int roi_y, + int block_count_x) +{ + int gidx = get_global_id(0); + int gidy = get_global_id(1); + int x = gidx + roi_x; + int y = gidy + roi_y; + int cy = y/size; + int cx = x/size; + float cellx = convert_float(x - cx * size) - convert_float(size) / 2.0; + float celly = convert_float(y - cy * size) - convert_float(size) / 2.0; + float4 tmp = (float4)(0.0); + + if((cellx * cellx + celly * celly) <= radius2) + tmp = block_colors[(cx-cx0) + block_count_x * (cy-cy0)]; + + out[gidx + get_global_size(0) * gidy] = tmp; +} + diff --git a/opencl/dot.cl.h b/opencl/dot.cl.h new file mode 100644 index 00000000..c75b7f11 --- /dev/null +++ b/opencl/dot.cl.h @@ -0,0 +1,73 @@ +static const char* dot_cl_source = +"/* This file is an image processing operation for GEGL \n" +" * \n" +" * GEGL is free software; you can redistribute it and/or \n" +" * modify it under the terms of the GNU Lesser General Public \n" +" * License as published by the Free Software Foundation; either \n" +" * version 3 of the License, or (at your option) any later version. \n" +" * \n" +" * GEGL is distributed in the hope that it will be useful, \n" +" * but WITHOUT ANY WARRANTY; without even the implied warranty of \n" +" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU \n" +" * Lesser General Public License for more details. \n" +" * \n" +" * You should have received a copy of the GNU Lesser General Public \n" +" * License along with GEGL; if not, see <http://www.gnu.org/licenses/>. \n" +" * \n" +" * Copyright 2013 Carlos Zubieta <czubieta.dev@gmail.com> \n" +" */ \n" +" \n" +"__kernel void cl_calc_block_colors (__global const float4 *in, \n" +" __global float4 *block_colors, \n" +" int cx0, \n" +" int cy0, \n" +" int size, \n" +" float weight, \n" +" int roi_x, \n" +" int roi_y, \n" +" int line_width) \n" +"{ \n" +" int cx = cx0 + get_global_id(0); \n" +" int cy = cy0 + get_global_id(1); \n" +" int px = (cx * size) - roi_x + size; \n" +" int py = (cy * size) - roi_y + size; \n" +" float4 mean = (float4)(0.0f); \n" +" float4 tmp; \n" +" int i, j; \n" +" \n" +" for( j = py; j < py+size; ++j) \n" +" { \n" +" for (i = px; i < px+size; ++i) \n" +" { \n" +" mean += in[j * line_width + i]; \n" +" } \n" +" } \n" +" block_colors[(cx-cx0) + get_global_size(0) * (cy-cy0)] = mean*weight; \n" +"} \n" +" \n" +"__kernel void cl_dot (__global const float4 *block_colors, \n" +" __global float4 *out, \n" +" int cx0, \n" +" int cy0, \n" +" int size, \n" +" float radius2, \n" +" int roi_x, \n" +" int roi_y, \n" +" int block_count_x) \n" +"{ \n" +" int gidx = get_global_id(0); \n" +" int gidy = get_global_id(1); \n" +" int x = gidx + roi_x; \n" +" int y = gidy + roi_y; \n" +" int cy = y/size; \n" +" int cx = x/size; \n" +" float cellx = convert_float(x - cx * size) - convert_float(size) / 2.0; \n" +" float celly = convert_float(y - cy * size) - convert_float(size) / 2.0; \n" +" float4 tmp = (float4)(0.0); \n" +" \n" +" if((cellx * cellx + celly * celly) <= radius2) \n" +" tmp = block_colors[(cx-cx0) + block_count_x * (cy-cy0)]; \n" +" \n" +" out[gidx + get_global_size(0) * gidy] = tmp; \n" +"} \n" +; diff --git a/operations/common/dot.c b/operations/common/dot.c index 35312733..8a15e409 100644 --- a/operations/common/dot.c +++ b/operations/common/dot.c @@ -62,6 +62,142 @@ prepare (GeglOperation *operation) babl_format ("RGBA float")); } +#include "opencl/gegl-cl.h" +#include "buffer/gegl-buffer-cl-iterator.h" +#include "opencl/dot.cl.h" +#include <stdio.h> + +GEGL_CL_STATIC + +static gboolean +cl_dot (cl_mem in, + cl_mem out, + const GeglRectangle *roi, + gint size, + gfloat ratio) +{ + cl_int cl_err = 0; + cl_mem block_colors = NULL; + + GEGL_CL_BUILD(dot, "cl_calc_block_colors", "cl_dot") + + { + cl_int cl_size = size; + cl_float radius2 = (cl_float)(size*ratio*size*ratio)/4.0; + cl_float weight = 1.0 / (cl_float)(size*size); + cl_int roi_x = roi->x; + cl_int roi_y = roi->y; + cl_int line_width = roi->width + 2*size; + cl_int cx0 = CELL_X(roi->x, size); + cl_int cy0 = CELL_Y(roi->y, size); + cl_int block_count_x = CELL_X(roi->x + roi->width - 1, size) - cx0 + 1; + cl_int block_count_y = CELL_Y(roi->y + roi->height - 1, size) - cy0 + 1; + size_t glbl_s[2] = {block_count_x, block_count_y}; + + block_colors = gegl_clCreateBuffer(gegl_cl_get_context(), + CL_MEM_READ_WRITE, + glbl_s[0] * glbl_s[1] * sizeof(cl_float4), + NULL, &cl_err); + CL_CHECK; + + GEGL_CL_ARG_START(cl_data->kernel[0]) + GEGL_CL_ARG(cl_mem, in) + GEGL_CL_ARG(cl_mem, block_colors) + GEGL_CL_ARG(cl_int, cx0) + GEGL_CL_ARG(cl_int, cy0) + GEGL_CL_ARG(cl_int, cl_size) + GEGL_CL_ARG(cl_float, weight) + GEGL_CL_ARG(cl_int, roi_x) + GEGL_CL_ARG(cl_int, roi_y) + GEGL_CL_ARG(cl_int, line_width) + GEGL_CL_ARG_END + + /* calculate the average color of all the blocks */ + cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (), + cl_data->kernel[0], 2, + NULL, glbl_s, NULL, + 0, NULL, NULL); + CL_CHECK; + + glbl_s[0] = roi->width; + glbl_s[1] = roi->height; + + GEGL_CL_ARG_START(cl_data->kernel[1]) + GEGL_CL_ARG(cl_mem, block_colors) + GEGL_CL_ARG(cl_mem, out) + GEGL_CL_ARG(cl_int, cx0) + GEGL_CL_ARG(cl_int, cy0) + GEGL_CL_ARG(cl_int, cl_size) + GEGL_CL_ARG(cl_float, radius2) + GEGL_CL_ARG(cl_int, roi_x) + GEGL_CL_ARG(cl_int, roi_y) + GEGL_CL_ARG(cl_int, block_count_x) + GEGL_CL_ARG_END + + /* set each pixel to the average color of the block it belongs to */ + cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (), + cl_data->kernel[1], 2, + NULL, glbl_s, NULL, + 0, NULL, NULL); + CL_CHECK; + + cl_err = gegl_clFinish(gegl_cl_get_command_queue ()); + CL_CHECK; + + GEGL_CL_RELEASE(block_colors) + } + + return FALSE; + +error: + if(block_colors) + GEGL_CL_RELEASE(block_colors) + return TRUE; +} + +static gboolean +cl_process (GeglOperation *operation, + GeglBuffer *input, + GeglBuffer *output, + const GeglRectangle *result) +{ + const Babl *in_format = gegl_operation_get_format (operation, "input"); + const Babl *out_format = gegl_operation_get_format (operation, "output"); + + gint err; + + GeglOperationAreaFilter *op_area = GEGL_OPERATION_AREA_FILTER (operation); + GeglChantO *o = GEGL_CHANT_PROPERTIES (operation); + + GeglBufferClIterator *i = gegl_buffer_cl_iterator_new (output, + result, + out_format, + GEGL_CL_BUFFER_WRITE); + + gint read = gegl_buffer_cl_iterator_add_2 (i, + input, + result, + in_format, + GEGL_CL_BUFFER_READ, + op_area->left, + op_area->right, + op_area->top, + op_area->bottom, + GEGL_ABYSS_NONE); + + GEGL_CL_BUFFER_ITERATE_START(i, err) + { + err = cl_dot(i->tex[read], + i->tex[0], + &i->roi[0], + o->size, + o->ratio); + } + GEGL_CL_BUFFER_ITERATE_END(err) + + return TRUE; +} + static void calc_block_colors (gfloat* block_colors, const gfloat* input, @@ -156,6 +292,10 @@ process (GeglOperation *operation, GeglOperationAreaFilter *op_area; gfloat* buf; + if (gegl_cl_is_accelerated ()) + if (cl_process (operation, input, output, roi)) + return TRUE; + op_area = GEGL_OPERATION_AREA_FILTER (operation); src_rect = *roi; src_rect.x -= op_area->left; @@ -165,10 +305,12 @@ process (GeglOperation *operation, buf = g_new0 (gfloat, src_rect.width * src_rect.height * 4); - gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RGBA float"), buf, GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); + gegl_buffer_get (input, &src_rect, 1.0, babl_format ("RGBA float"), buf, + GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE); dot(buf, roi, o); - gegl_buffer_set (output, roi, 0, babl_format ("RGBA float"), buf, GEGL_AUTO_ROWSTRIDE); + gegl_buffer_set (output, roi, 0, babl_format ("RGBA float"), buf, + GEGL_AUTO_ROWSTRIDE); g_free (buf); @@ -187,6 +329,7 @@ gegl_chant_class_init (GeglChantClass *klass) filter_class->process = process; operation_class->prepare = prepare; + operation_class->opencl_support = TRUE; gegl_operation_class_set_keys (operation_class, "name", "gegl:dot", |