ufo-padding-2d-task.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /**
  2. * SECTION:ufo-filter-task
  3. * @Short_description: Process arbitrary Filter kernels
  4. * @Title: filter
  5. *
  6. * This module is used to load an arbitrary #UfoPadding2DTask:kernel from
  7. * #UfoPadding2DTask:filename and execute it on each input. The kernel must have
  8. * only two global float array parameters, the first represents the input, the
  9. * second one the output. #UfoPadding2DTask:num-dims must be changed, if the kernel
  10. * accesses either one or three dimensional index spaces.
  11. */
  12. #ifdef __APPLE__
  13. #include <OpenCL/cl.h>
  14. #else
  15. #include <CL/cl.h>
  16. #endif
  17. #include <ufo-gpu-task-iface.h>
  18. #include "ufo-padding-2d-task.h"
  19. typedef enum {
  20. PADDING_ZERO = 0,
  21. PADDING_CONST,
  22. PADDING_GAVG,
  23. PADDING_BREP
  24. } PaddingMode;
  25. struct _UfoPadding2DTaskPrivate {
  26. guint in_width;
  27. guint in_height;
  28. guint out_width;
  29. guint out_height;
  30. // extent adds
  31. guint xl;
  32. guint xr;
  33. guint yt;
  34. guint yb;
  35. size_t global_work_size_small[2];
  36. size_t global_work_size_large[2];
  37. PaddingMode mode;
  38. // padding constant
  39. float pconst;
  40. cl_kernel kernel_iconst;
  41. cl_kernel kernel_cpyimg;
  42. cl_kernel kernel_brep;
  43. };
  44. static void ufo_task_interface_init (UfoTaskIface *iface);
  45. static void ufo_gpu_task_interface_init (UfoGpuTaskIface *iface);
  46. G_DEFINE_TYPE_WITH_CODE (UfoPadding2DTask, ufo_padding_2d_task, UFO_TYPE_TASK_NODE,
  47. G_IMPLEMENT_INTERFACE (UFO_TYPE_TASK,
  48. ufo_task_interface_init)
  49. G_IMPLEMENT_INTERFACE (UFO_TYPE_GPU_TASK,
  50. ufo_gpu_task_interface_init))
  51. #define UFO_PADDING_2D_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_PADDING_2D_TASK, UfoPadding2DTaskPrivate))
  52. enum {
  53. PROP_0,
  54. PROP_XL,
  55. PROP_XR,
  56. PROP_YT,
  57. PROP_YB,
  58. PROP_MODE,
  59. PROP_PCONST,
  60. N_PROPERTIES
  61. };
  62. static GParamSpec *properties[N_PROPERTIES] = { NULL, };
  63. UfoNode *
  64. ufo_padding_2d_task_new (void)
  65. {
  66. return UFO_NODE (g_object_new (UFO_TYPE_PADDING_2D_TASK, NULL));
  67. }
  68. static gboolean
  69. ufo_padding_2d_task_process (UfoGpuTask *task,
  70. UfoBuffer **inputs,
  71. UfoBuffer *output,
  72. UfoRequisition *requisition,
  73. UfoGpuNode *node)
  74. {
  75. UfoPadding2DTaskPrivate *priv;
  76. cl_command_queue cmd_queue;
  77. cl_mem in_mem;
  78. cl_mem out_mem;
  79. priv = UFO_PADDING_2D_TASK (task)->priv;
  80. const PaddingMode mode = priv->mode;
  81. const guint pxl = priv->xl;
  82. const guint pyt = priv->yt;
  83. float pval = priv->pconst;
  84. const guint ixs = priv->in_width;
  85. const guint iys = priv->in_height;
  86. const guint oxs = priv->out_width;
  87. if (mode == PADDING_GAVG) {
  88. gfloat *indata = ufo_buffer_get_host_array (inputs[0], NULL);
  89. gfloat sum = 0;
  90. guint psz = ixs * iys;
  91. for (guint i =0; i < psz; i++)
  92. sum += indata[i];
  93. pval = sum / (gfloat) psz;
  94. }
  95. cmd_queue = ufo_gpu_node_get_cmd_queue (node);
  96. in_mem = ufo_buffer_get_device_array (inputs[0], cmd_queue);
  97. out_mem = ufo_buffer_get_device_array (output, cmd_queue);
  98. if ((mode == PADDING_ZERO) || (mode == PADDING_CONST) || (mode == PADDING_GAVG)) {
  99. cl_kernel k_iconst = priv->kernel_iconst;
  100. cl_kernel k_cpyimg = priv->kernel_cpyimg;
  101. /// fill with constant
  102. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_iconst, 0, sizeof(cl_mem), (void *) &out_mem));
  103. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_iconst, 1, sizeof(int), &oxs));
  104. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_iconst, 2, sizeof(float), &pval));
  105. UFO_RESOURCES_CHECK_CLERR(clEnqueueNDRangeKernel(cmd_queue, k_iconst,
  106. 2, NULL, priv->global_work_size_large, NULL,
  107. 0, NULL, NULL));
  108. /// copy old image
  109. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_cpyimg, 0, sizeof(cl_mem), (void *) &in_mem));
  110. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_cpyimg, 1, sizeof(cl_mem), (void *) &out_mem));
  111. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_cpyimg, 2, sizeof(int), &ixs));
  112. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_cpyimg, 3, sizeof(int), &oxs));
  113. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_cpyimg, 4, sizeof(int), &pxl));
  114. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_cpyimg, 5, sizeof(int), &pyt));
  115. UFO_RESOURCES_CHECK_CLERR(clEnqueueNDRangeKernel(cmd_queue, k_cpyimg,
  116. 2, NULL, priv->global_work_size_small, NULL,
  117. 0, NULL, NULL));
  118. }
  119. if (mode == PADDING_BREP) {
  120. cl_kernel k_brep = priv->kernel_brep;
  121. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 0, sizeof(cl_mem), (void *) &in_mem));
  122. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 1, sizeof(cl_mem), (void *) &out_mem));
  123. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 2, sizeof(int), &ixs));
  124. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 3, sizeof(int), &iys));
  125. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 4, sizeof(int), &oxs));
  126. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 5, sizeof(int), &pxl));
  127. UFO_RESOURCES_CHECK_CLERR(clSetKernelArg( k_brep, 6, sizeof(int), &pyt));
  128. UFO_RESOURCES_CHECK_CLERR(clEnqueueNDRangeKernel(cmd_queue, k_brep,
  129. 2, NULL, priv->global_work_size_large, NULL,
  130. 0, NULL, NULL));
  131. }
  132. return TRUE;
  133. }
  134. static void
  135. ufo_padding_2d_task_setup (UfoTask *task,
  136. UfoResources *resources,
  137. GError **error)
  138. {
  139. UfoPadding2DTaskPrivate *priv;
  140. priv = UFO_PADDING_2D_TASK_GET_PRIVATE (task);
  141. priv->kernel_iconst = ufo_resources_get_kernel (resources, "padding_2d.cl", "padding_2d_init_const", error);
  142. priv->kernel_cpyimg = ufo_resources_get_kernel (resources, "padding_2d.cl", "padding_2d_copy_in", error);
  143. priv->kernel_brep = ufo_resources_get_kernel (resources, "padding_2d.cl", "padding_2d_brep", error);
  144. }
  145. static void
  146. ufo_padding_2d_task_get_requisition (UfoTask *task,
  147. UfoBuffer **inputs,
  148. UfoRequisition *requisition)
  149. {
  150. UfoPadding2DTaskPrivate *priv;
  151. UfoRequisition in_req;
  152. priv = UFO_PADDING_2D_TASK_GET_PRIVATE (task);
  153. ufo_buffer_get_requisition (inputs[0], &in_req);
  154. priv->in_width = in_req.dims[0];
  155. priv->in_height = in_req.dims[1];
  156. requisition->n_dims = 2;
  157. requisition->dims[0] = priv->out_width = priv->xl + priv->in_width + priv->xr;
  158. requisition->dims[1] = priv->out_height = priv->yt + priv->in_height + priv->yb;
  159. priv->global_work_size_small[0] = (size_t) priv->in_width;
  160. priv->global_work_size_small[1] = (size_t) priv->in_height;
  161. priv->global_work_size_large[0] = requisition->dims[0];
  162. priv->global_work_size_large[1] = requisition->dims[1];
  163. }
  164. static void
  165. ufo_padding_2d_task_get_structure (UfoTask *task,
  166. guint *n_inputs,
  167. UfoInputParam **in_params,
  168. UfoTaskMode *mode)
  169. {
  170. UfoPadding2DTaskPrivate *priv;
  171. priv = UFO_PADDING_2D_TASK_GET_PRIVATE (task);
  172. *mode = UFO_TASK_MODE_SINGLE;
  173. *n_inputs = 1;
  174. *in_params = g_new0 (UfoInputParam, 1);
  175. (*in_params)[0].n_dims = 2;
  176. (*in_params)[0].n_expected = -1;
  177. }
  178. static UfoNode *
  179. ufo_padding_2d_task_copy_real (UfoNode *node,
  180. GError **error)
  181. {
  182. UfoPadding2DTask *orig;
  183. UfoPadding2DTask *copy;
  184. orig = UFO_PADDING_2D_TASK (node);
  185. copy = UFO_PADDING_2D_TASK (ufo_padding_2d_task_new ());
  186. copy->priv->xl = orig->priv->xl;
  187. copy->priv->xr = orig->priv->xr;
  188. copy->priv->yb = orig->priv->yb;
  189. copy->priv->yt = orig->priv->yt;
  190. copy->priv->mode = orig->priv->mode;
  191. copy->priv->pconst = orig->priv->pconst;
  192. return UFO_NODE (copy);
  193. }
  194. static gboolean
  195. ufo_padding_2d_task_equal_real (UfoNode *n1,
  196. UfoNode *n2)
  197. {
  198. g_return_val_if_fail (UFO_IS_PADDING_2D_TASK (n1) && UFO_IS_PADDING_2D_TASK (n2), FALSE);
  199. return TRUE;
  200. }
  201. static void
  202. ufo_padding_2d_task_finalize (GObject *object)
  203. {
  204. UfoPadding2DTaskPrivate *priv;
  205. priv = UFO_PADDING_2D_TASK_GET_PRIVATE (object);
  206. G_OBJECT_CLASS (ufo_padding_2d_task_parent_class)->finalize (object);
  207. }
  208. static void
  209. ufo_task_interface_init (UfoTaskIface *iface)
  210. {
  211. iface->setup = ufo_padding_2d_task_setup;
  212. iface->get_requisition = ufo_padding_2d_task_get_requisition;
  213. iface->get_structure = ufo_padding_2d_task_get_structure;
  214. }
  215. static void
  216. ufo_gpu_task_interface_init (UfoGpuTaskIface *iface)
  217. {
  218. iface->process = ufo_padding_2d_task_process;
  219. }
  220. static void
  221. ufo_padding_2d_task_set_property (GObject *object,
  222. guint property_id,
  223. const GValue *value,
  224. GParamSpec *pspec)
  225. {
  226. UfoPadding2DTaskPrivate *priv = UFO_PADDING_2D_TASK_GET_PRIVATE (object);
  227. switch (property_id) {
  228. case PROP_XL:
  229. priv->xl = g_value_get_uint(value);
  230. break;
  231. case PROP_XR:
  232. priv->xr = g_value_get_uint(value);
  233. break;
  234. case PROP_YT:
  235. priv->yt = g_value_get_uint(value);
  236. break;
  237. case PROP_YB:
  238. priv->yb = g_value_get_uint(value);
  239. break;
  240. case PROP_MODE:
  241. if (!g_strcmp0(g_value_get_string(value), "zero"))
  242. priv->mode = PADDING_ZERO;
  243. else if (!g_strcmp0(g_value_get_string(value), "const"))
  244. priv->mode = PADDING_CONST;
  245. else if (!g_strcmp0(g_value_get_string(value), "gavg"))
  246. priv->mode = PADDING_GAVG;
  247. else if (!g_strcmp0(g_value_get_string(value), "brep"))
  248. priv->mode = PADDING_BREP;
  249. else
  250. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  251. break;
  252. case PROP_PCONST:
  253. priv->pconst = (float) g_value_get_double(value);
  254. break;
  255. default:
  256. G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
  257. break;
  258. }
  259. }
  260. static void
  261. ufo_padding_2d_task_get_property (GObject *object,
  262. guint property_id,
  263. GValue *value,
  264. GParamSpec *pspec)
  265. {
  266. UfoPadding2DTaskPrivate *priv = UFO_PADDING_2D_TASK_GET_PRIVATE (object);
  267. switch (property_id) {
  268. case PROP_XL:
  269. g_value_set_uint(value, priv->xl);
  270. break;
  271. case PROP_XR:
  272. g_value_set_uint(value, priv->xr);
  273. break;
  274. case PROP_YT:
  275. g_value_set_uint(value, priv->yt);
  276. break;
  277. case PROP_YB:
  278. g_value_set_uint(value, priv->yb);
  279. break;
  280. case PROP_MODE:
  281. switch (priv->mode) {
  282. case PADDING_ZERO:
  283. g_value_set_string(value, "zero");
  284. break;
  285. case PADDING_CONST:
  286. g_value_set_string(value, "const");
  287. break;
  288. case PADDING_GAVG:
  289. g_value_set_string(value, "gavg");
  290. break;
  291. case PADDING_BREP:
  292. g_value_set_string(value, "brep");
  293. break;
  294. default:
  295. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  296. break;
  297. }
  298. break;
  299. case PROP_PCONST:
  300. g_value_set_double(value, priv->pconst);
  301. break;
  302. default:
  303. G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
  304. break;
  305. }
  306. }
  307. static void
  308. ufo_padding_2d_task_class_init (UfoPadding2DTaskClass *klass)
  309. {
  310. GObjectClass *oclass;
  311. UfoNodeClass *node_class;
  312. oclass = G_OBJECT_CLASS (klass);
  313. node_class = UFO_NODE_CLASS (klass);
  314. oclass->finalize = ufo_padding_2d_task_finalize;
  315. oclass->set_property = ufo_padding_2d_task_set_property;
  316. oclass->get_property = ufo_padding_2d_task_get_property;
  317. properties[PROP_XL] =
  318. g_param_spec_uint("xl",
  319. "Number of additional pixel on the left hand image side",
  320. "Number of additional pixel on the left hand image side",
  321. 0, 16384, 1,
  322. G_PARAM_READWRITE);
  323. properties[PROP_XR] =
  324. g_param_spec_uint("xr",
  325. "Number of additional pixel on the right hand image side",
  326. "Number of additional pixel on the right hand image side",
  327. 0, 16384, 1,
  328. G_PARAM_READWRITE);
  329. properties[PROP_YT] =
  330. g_param_spec_uint("yt",
  331. "Number of additional pixel on the top image side",
  332. "Number of additional pixel on the top image side",
  333. 0, 16384, 1,
  334. G_PARAM_READWRITE);
  335. properties[PROP_YB] =
  336. g_param_spec_uint("yb",
  337. "Number of additional pixel on the bottom image side",
  338. "Number of additional pixel on the bottom image side",
  339. 0, 16384, 1,
  340. G_PARAM_READWRITE);
  341. properties[PROP_MODE] =
  342. g_param_spec_string("mode",
  343. "Padding mode can be 'zero', 'const', 'gavg' or 'brep' ",
  344. "Padding mode can be 'zero', 'const', 'gavg' or 'brep' ",
  345. "zero",
  346. G_PARAM_READWRITE);
  347. properties[PROP_PCONST] =
  348. g_param_spec_double("pconst",
  349. "Padding constant",
  350. "Padding constant",
  351. -320000.0,
  352. 320000.0,
  353. 0.0,
  354. G_PARAM_READWRITE);
  355. for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++)
  356. g_object_class_install_property (oclass, i, properties[i]);
  357. node_class->copy = ufo_padding_2d_task_copy_real;
  358. node_class->equal = ufo_padding_2d_task_equal_real;
  359. g_type_class_add_private(klass, sizeof(UfoPadding2DTaskPrivate));
  360. }
  361. static void
  362. ufo_padding_2d_task_init (UfoPadding2DTask *self)
  363. {
  364. UfoPadding2DTaskPrivate *priv;
  365. self->priv = priv = UFO_PADDING_2D_TASK_GET_PRIVATE (self);
  366. priv->xl = 1;
  367. priv->xr = 1;
  368. priv->yt = 1;
  369. priv->yb = 1;
  370. priv->mode = PADDING_ZERO;
  371. priv->pconst = 0.0;
  372. priv->kernel_iconst = NULL;
  373. priv->kernel_cpyimg = NULL;
  374. priv->kernel_brep = NULL;
  375. }