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

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