[gegl/soc-2013-opecl-ops: 4/6] Added partial OpenCL support to contrast-curve
- From: Carlos Zubieta <czubieta src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gegl/soc-2013-opecl-ops: 4/6] Added partial OpenCL support to contrast-curve
- Date: Wed, 24 Jul 2013 00:24:40 +0000 (UTC)
commit c159ac65b889164f0b21b23d56dcc62538f8f927
Author: Carlos Zubieta <czubieta dev gmail com>
Date: Tue Jul 23 18:13:14 2013 -0500
Added partial OpenCL support to contrast-curve
opencl/contrast-curve.cl | 20 ++++++
opencl/contrast-curve.cl.h | 22 +++++++
operations/common/contrast-curve.c | 122 ++++++++++++++++++++++++++++++++++++
3 files changed, 164 insertions(+), 0 deletions(-)
---
diff --git a/opencl/contrast-curve.cl b/opencl/contrast-curve.cl
new file mode 100644
index 0000000..48d6982
--- /dev/null
+++ b/opencl/contrast-curve.cl
@@ -0,0 +1,20 @@
+__kernel void cl_contrast_curve(__global const float2 *in,
+ __global float2 *out,
+ __constant float *curve,
+ constant int num_sampling_points)
+{
+ int gid = get_global_id(0);
+ float2 in_v = in[gid];
+ int x = in_v.x * num_sampling_points;
+ float y;
+
+ if(x < 0)
+ y = curve[0];
+ else if (x < num_sampling_points)
+ y = curve[x];
+ else
+ y = curve[num_sampling_points - 1];
+
+ out[gid] = float2(y,in_v.y);
+}
+
diff --git a/opencl/contrast-curve.cl.h b/opencl/contrast-curve.cl.h
new file mode 100644
index 0000000..2ad559d
--- /dev/null
+++ b/opencl/contrast-curve.cl.h
@@ -0,0 +1,22 @@
+static const char* cl_contrast_curve_source =
+"__kernel void cl_contrast_curve(__global const float2 *in, \n"
+" __global float2 *out, \n"
+" __constant float *curve, \n"
+" constant int num_sampling_points) \n"
+"{ \n"
+" int gid = get_global_id(0); \n"
+" float2 in_v = in[gid]; \n"
+" int x = in_v.x * num_sampling_points; \n"
+" float y; \n"
+" \n"
+" if(x < 0) \n"
+" y = curve[0]; \n"
+" else if (x < num_sampling_points) \n"
+" y = curve[x]; \n"
+" else \n"
+" y = curve[num_sampling_points - 1]; \n"
+" \n"
+" out[gid] = float2(y,in_v.y); \n"
+"} \n"
+;
+
diff --git a/operations/common/contrast-curve.c b/operations/common/contrast-curve.c
index 9fbb2b9..c1f2e9c 100644
--- a/operations/common/contrast-curve.c
+++ b/operations/common/contrast-curve.c
@@ -41,6 +41,126 @@ static void prepare (GeglOperation *operation)
gegl_operation_set_format (operation, "output", format);
}
+#include "opencl/gegl-cl.h"
+#include "gegl/gegl-debug.h"
+
+#include "opencl/contrast-curve.cl.h"
+
+/* TODO : Replace gegl_curve_calc_values and gegl_curve_calc_value in cl_process
+ with something more suitable for the cl version*/
+
+static void
+copy_double_array_to_float_array (gdouble *in,
+ gfloat *out,
+ gint size)
+{
+ gint i;
+ for(i = 0; i < size; ++i)
+ out[i] = (gfloat)in[i];
+}
+
+static GeglClRunData * cl_data = NULL;
+
+static gboolean
+cl_process (GeglOperation *self,
+ cl_mem in_tex,
+ cl_mem out_tex,
+ size_t global_worksize,
+ const GeglRectangle *roi,
+ gint level)
+{
+ GeglChantO *o = GEGL_CHANT_PROPERTIES (self);
+ gint num_sampling_points;
+ gdouble *xs, *ys;
+ gfloat *ysf;
+ cl_mem cl_curve;
+ cl_ulong cl_max_constant_size;
+ cl_int cl_err = 0;
+
+ num_sampling_points = o->sampling_points;
+
+ if (num_sampling_points > 0)
+ {
+ xs = g_new(gdouble, num_sampling_points);
+ ys = g_new(gdouble, num_sampling_points);
+
+ gegl_curve_calc_values(o->curve, 0.0, 1.0, num_sampling_points, xs, ys);
+ g_free(xs);
+ /*We need to downscale the array to pass it to the GPU*/
+ ysf = g_new(gfloat, num_sampling_points);
+ copy_double_array_to_float_array(ys,ysf,num_sampling_points);
+ g_free(ys);
+
+ cl_err = gegl_clGetDeviceInfo(gegl_cl_get_device(),
+ CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
+ sizeof(cl_ulong),
+ &cl_max_constant_size,
+ NULL);
+ CL_CHECK;
+
+ GEGL_NOTE (GEGL_DEBUG_OPENCL, "Max Constant Mem Size: %lu bytes",
+ (unsigned long)cl_max_constant_size);
+
+ if(sizeof(cl_float)*num_sampling_points < cl_max_constant_size)
+ {
+ if (!cl_data)
+ {
+ const char *kernel_name[] = {"cl_contrast_curve",NULL};
+ cl_data = gegl_cl_compile_and_build (cl_contrast_curve_source,
+ kernel_name);
+ }
+ if (!cl_data)
+ return TRUE;
+
+ cl_curve = gegl_clCreateBuffer(gegl_cl_get_context(),
+ CL_MEM_USE_HOST_PTR | CL_MEM_READ_ONLY,
+ num_sampling_points * sizeof(cl_float),
+ ysf, &cl_err);
+ CL_CHECK;
+
+ {
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 0, sizeof(cl_mem),
+ (void*)&in_tex);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 1, sizeof(cl_mem),
+ (void*)&out_tex);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 2, sizeof(cl_mem),
+ (void*)&cl_curve);
+ CL_CHECK;
+ cl_err = gegl_clSetKernelArg(cl_data->kernel[0], 3, sizeof(gint),
+ (void*)&num_sampling_points);
+ CL_CHECK;
+
+ cl_err = gegl_clEnqueueNDRangeKernel(gegl_cl_get_command_queue (),
+ cl_data->kernel[0], 1,
+ NULL, &global_worksize, NULL,
+ 0, NULL, NULL);
+ CL_CHECK;
+ }
+ }
+ else
+ {
+ /*If the curve size doesn't fit constant memory is better to use CPU*/
+ GEGL_NOTE (GEGL_DEBUG_OPENCL,
+ "Not enough constant memory for the curve");
+ g_free(ysf);
+ return TRUE;
+ }
+
+ g_free(ysf);
+ return FALSE;
+error:
+ return TRUE;
+ }
+ else /*If the curve doesn't have a lookup table is better to use CPU*/
+ {
+ GEGL_NOTE (GEGL_DEBUG_OPENCL,
+ "Curve not suitable to be computed in the GPU");
+ return TRUE;
+ }
+}
+
static gboolean
process (GeglOperation *op,
void *in_buf,
@@ -116,7 +236,9 @@ gegl_chant_class_init (GeglChantClass *klass)
point_filter_class = GEGL_OPERATION_POINT_FILTER_CLASS (klass);
point_filter_class->process = process;
+ point_filter_class->cl_process = cl_process;
operation_class->prepare = prepare;
+ operation_class->opencl_support = TRUE;
gegl_operation_class_set_keys (operation_class,
"name" , "gegl:contrast-curve",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]