Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
bilateralcl.c
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2012 johannes hanika.
4 Copyright (C) 2012-2014, 2016 Tobias Ellinghaus.
5 Copyright (C) 2012, 2014, 2016-2017 Ulrich Pegelow.
6 Copyright (C) 2016 Roman Lebedev.
7 Copyright (C) 2019 Marcus Rückert.
8 Copyright (C) 2020 Hubert Kowalski.
9 Copyright (C) 2020 Pascal Obry.
10 Copyright (C) 2020 Ralf Brown.
11 Copyright (C) 2022 Hanno Schwalm.
12 Copyright (C) 2022 Martin Bařinka.
13
14 darktable is free software: you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 darktable is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with darktable. If not, see <http://www.gnu.org/licenses/>.
26*/
27
28#include "system/macros.h"
29#include "system/mem_alloc.h"
30#include "common/logging.h"
31#ifdef HAVE_OPENCL
32
33#include "pixel/bilateral.h"
34#include "pixel/bilateralcl.h"
35#include "common/opencl.h" // for dt_opencl_set_kernel_arg, dt_opencl_cr...
36#include <glib.h> // for MAX
37#include <stdlib.h> // for free, malloc
38
39/* The kernels this subsystem compiles, owned HERE. They used to be handed to
40 * common/opencl.c, parked on the application-wide dt_opencl_t, and read back from it --
41 * a round trip through a god-struct that added nothing but an ordering. opencl.c still
42 * calls init/free, because the kernels must be built after the devices exist, but the
43 * pointer never leaves this file. */
45
47{
49
50 const int program = 10; // bilateral.cl, from programs.conf
51 b->kernel_zero = dt_opencl_create_kernel(program, "zero");
52 b->kernel_splat = dt_opencl_create_kernel(program, "splat");
53 b->kernel_blur_line = dt_opencl_create_kernel(program, "blur_line");
54 b->kernel_blur_line_z = dt_opencl_create_kernel(program, "blur_line_z");
55 b->kernel_slice = dt_opencl_create_kernel(program, "slice");
56 b->kernel_slice2 = dt_opencl_create_kernel(program, "slice_to_output");
58}
59
61{
62 if(IS_NULL_PTR(b)) return;
63 // free device mem
65 dt_opencl_release_mem_object(b->dev_grid_tmp);
66 dt_free(b);
67}
68
69
70// modules that want to use dt_bilateral_slice_to_output_cl() ought to take this one;
71// takes account of an additional temp buffer needed in the OpenCL code path
73 const int height,
74 const float sigma_s,
75 const float sigma_r)
76{
77 return dt_bilateral_memory_use(width, height, sigma_s, sigma_r) + sizeof(float) * 4 * width * height;
78}
79
80// modules that want to use dt_bilateral_slice_to_output_cl() ought to take this one;
81// takes account of an additional temp buffer needed in the OpenCL code path
83 const int height,
84 const float sigma_s,
85 const float sigma_r)
86{
87 return MAX(dt_bilateral_singlebuffer_size(width, height, sigma_s, sigma_r), sizeof(float) * 4 * width * height);
88}
89
90
92 const int width, // width of input image
93 const int height, // height of input image
94 const float sigma_s, // spatial sigma (blur pixel coords)
95 const float sigma_r) // range sigma (blur luma values)
96{
98 = (dt_opencl_local_buffer_t){ .xoffset = 0, .xfactor = 1, .yoffset = 0, .yfactor = 1,
99 .cellsize = 8 * sizeof(float) + sizeof(int), .overhead = 0,
100 .sizex = 1 << 6, .sizey = 1 << 6 };
101
103 {
105 "[opencl_bilateral] can not identify resource limits for device %d in bilateral grid\n", devid);
106 return NULL;
107 }
108
109 if(locopt.sizex * locopt.sizey < 16 * 16)
110 {
112 "[opencl_bilateral] device %d does not offer sufficient resources to run bilateral grid\n",
113 devid);
114 return NULL;
115 }
116
118 if(IS_NULL_PTR(b)) return NULL;
119
120 b->global = _bilateral_cl_global;
121 b->width = width;
122 b->height = height;
123 b->blocksizex = locopt.sizex;
124 b->blocksizey = locopt.sizey;
125 b->devid = devid;
126 b->dev_grid = NULL;
127 b->dev_grid_tmp = NULL;
130 b->size_x = b2.size_x;
131 b->size_y = b2.size_y;
132 b->size_z = b2.size_z;
133 b->sigma_s = b2.sigma_s;
134 b->sigma_r = b2.sigma_r;
135
136 // alloc grid buffer:
137 b->dev_grid
138 = dt_opencl_alloc_device_buffer(b->devid, sizeof(float) * b->size_x * b->size_y * b->size_z);
139 if(!b->dev_grid)
140 {
142 return NULL;
143 }
144
145 // alloc temporary grid buffer
146 b->dev_grid_tmp
147 = dt_opencl_alloc_device_buffer(b->devid, sizeof(float) * b->size_x * b->size_y * b->size_z);
148 if(!b->dev_grid_tmp)
149 {
151 return NULL;
152 }
153
154 // zero out grid
155 int wd = b->size_x, ht = b->size_y * b->size_z;
156 size_t sizes[] = { ROUNDUPDWD(wd, b->devid), ROUNDUPDHT(ht, b->devid), 1 };
157 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_zero, 0, sizeof(cl_mem), (void *)&b->dev_grid);
158 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_zero, 1, sizeof(int), (void *)&wd);
159 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_zero, 2, sizeof(int), (void *)&ht);
160 cl_int err = -666;
161 err = dt_opencl_enqueue_kernel_2d(b->devid, b->global->kernel_zero, sizes);
162 if(err != CL_SUCCESS)
163 {
165 return NULL;
166 }
167
168#if 0
169 fprintf(stderr, "[bilateral] created grid [%d %d %d]"
170 " with sigma (%f %f) (%f %f)\n", b->size_x, b->size_y, b->size_z,
171 b->sigma_s, sigma_s, b->sigma_r, sigma_r);
172#endif
173 return b;
174}
175
177{
178 cl_int err = -666;
179 size_t sizes[] = { ROUNDUP(b->width, b->blocksizex), ROUNDUP(b->height, b->blocksizey), 1 };
180 size_t local[] = { b->blocksizex, b->blocksizey, 1 };
181 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 0, sizeof(cl_mem), (void *)&in);
182 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 1, sizeof(cl_mem), (void *)&b->dev_grid);
183 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 2, sizeof(int), (void *)&b->width);
184 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 3, sizeof(int), (void *)&b->height);
185 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 4, sizeof(int), (void *)&b->size_x);
186 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 5, sizeof(int), (void *)&b->size_y);
187 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 6, sizeof(int), (void *)&b->size_z);
188 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 7, sizeof(float), (void *)&b->sigma_s);
189 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 8, sizeof(float), (void *)&b->sigma_r);
190 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 9, b->blocksizex * b->blocksizey * sizeof(int),
191 NULL);
192 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_splat, 10,
193 b->blocksizex * b->blocksizey * 8 * sizeof(float), NULL);
194 err = dt_opencl_enqueue_kernel_2d_with_local(b->devid, b->global->kernel_splat, sizes, local);
195 return err;
196}
197
199{
200 cl_int err = -666;
201 size_t sizes[3] = { 0, 0, 1 };
202
203 err = dt_opencl_enqueue_copy_buffer_to_buffer(b->devid, b->dev_grid, b->dev_grid_tmp, 0, 0,
204 b->size_x * b->size_y * b->size_z * sizeof(float));
205 if(err != CL_SUCCESS) return err;
206
207 sizes[0] = ROUNDUPDWD(b->size_z, b->devid);
208 sizes[1] = ROUNDUPDHT(b->size_y, b->devid);
209 int stride1, stride2, stride3;
210 stride1 = b->size_x * b->size_y;
211 stride2 = b->size_x;
212 stride3 = 1;
213 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 0, sizeof(cl_mem), (void *)&b->dev_grid_tmp);
214 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 1, sizeof(cl_mem), (void *)&b->dev_grid);
215 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 2, sizeof(int), (void *)&stride1);
216 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 3, sizeof(int), (void *)&stride2);
217 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 4, sizeof(int), (void *)&stride3);
218 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 5, sizeof(int), (void *)&b->size_z);
219 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 6, sizeof(int), (void *)&b->size_y);
220 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 7, sizeof(int), (void *)&b->size_x);
221 err = dt_opencl_enqueue_kernel_2d(b->devid, b->global->kernel_blur_line, sizes);
222 if(err != CL_SUCCESS) return err;
223
224 stride1 = b->size_x * b->size_y;
225 stride2 = 1;
226 stride3 = b->size_x;
227 sizes[0] = ROUNDUPDWD(b->size_z, b->devid);
228 sizes[1] = ROUNDUPDHT(b->size_x, b->devid);
229 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 0, sizeof(cl_mem), (void *)&b->dev_grid);
230 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 1, sizeof(cl_mem), (void *)&b->dev_grid_tmp);
231 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 2, sizeof(int), (void *)&stride1);
232 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 3, sizeof(int), (void *)&stride2);
233 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 4, sizeof(int), (void *)&stride3);
234 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 5, sizeof(int), (void *)&b->size_z);
235 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 6, sizeof(int), (void *)&b->size_x);
236 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line, 7, sizeof(int), (void *)&b->size_y);
237 err = dt_opencl_enqueue_kernel_2d(b->devid, b->global->kernel_blur_line, sizes);
238 if(err != CL_SUCCESS) return err;
239
240 stride1 = 1;
241 stride2 = b->size_x;
242 stride3 = b->size_x * b->size_y;
243 sizes[0] = ROUNDUPDWD(b->size_x, b->devid);
244 sizes[1] = ROUNDUPDHT(b->size_y, b->devid);
245 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 0, sizeof(cl_mem),
246 (void *)&b->dev_grid_tmp);
247 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 1, sizeof(cl_mem), (void *)&b->dev_grid);
248 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 2, sizeof(int), (void *)&stride1);
249 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 3, sizeof(int), (void *)&stride2);
250 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 4, sizeof(int), (void *)&stride3);
251 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 5, sizeof(int), (void *)&b->size_x);
252 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 6, sizeof(int), (void *)&b->size_y);
253 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_blur_line_z, 7, sizeof(int), (void *)&b->size_z);
254 err = dt_opencl_enqueue_kernel_2d(b->devid, b->global->kernel_blur_line_z, sizes);
255 return err;
256}
257
258cl_int dt_bilateral_slice_to_output_cl(dt_bilateral_cl_t *b, cl_mem in, cl_mem out, const float detail)
259{
260 cl_int err = -666;
261 cl_mem tmp = NULL;
262
263 tmp = dt_opencl_alloc_device(b->devid, b->width, b->height, sizeof(float) * 4);
264 if(IS_NULL_PTR(tmp)) goto error;
265
266 size_t origin[] = { 0, 0, 0 };
267 size_t region[] = { b->width, b->height, 1 };
268 err = dt_opencl_enqueue_copy_image(b->devid, out, tmp, origin, origin, region);
269 if(err != CL_SUCCESS) goto error;
270
271 size_t sizes[] = { ROUNDUPDWD(b->width, b->devid), ROUNDUPDHT(b->height, b->devid), 1 };
272 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 0, sizeof(cl_mem), (void *)&in);
273 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 1, sizeof(cl_mem), (void *)&tmp);
274 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 2, sizeof(cl_mem), (void *)&out);
275 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 3, sizeof(cl_mem), (void *)&b->dev_grid);
276 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 4, sizeof(int), (void *)&b->width);
277 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 5, sizeof(int), (void *)&b->height);
278 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 6, sizeof(int), (void *)&b->size_x);
279 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 7, sizeof(int), (void *)&b->size_y);
280 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 8, sizeof(int), (void *)&b->size_z);
281 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 9, sizeof(float), (void *)&b->sigma_s);
282 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 10, sizeof(float), (void *)&b->sigma_r);
283 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice2, 11, sizeof(float), (void *)&detail);
284 err = dt_opencl_enqueue_kernel_2d(b->devid, b->global->kernel_slice2, sizes);
285
287 return err;
288
289error:
291 return err;
292}
293
294cl_int dt_bilateral_slice_cl(dt_bilateral_cl_t *b, cl_mem in, cl_mem out, const float detail)
295{
296 cl_int err = -666;
297 size_t sizes[] = { ROUNDUPDWD(b->width, b->devid), ROUNDUPDHT(b->height, b->devid), 1 };
298 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 0, sizeof(cl_mem), (void *)&in);
299 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 1, sizeof(cl_mem), (void *)&out);
300 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 2, sizeof(cl_mem), (void *)&b->dev_grid);
301 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 3, sizeof(int), (void *)&b->width);
302 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 4, sizeof(int), (void *)&b->height);
303 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 5, sizeof(int), (void *)&b->size_x);
304 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 6, sizeof(int), (void *)&b->size_y);
305 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 7, sizeof(int), (void *)&b->size_z);
306 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 8, sizeof(float), (void *)&b->sigma_s);
307 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 9, sizeof(float), (void *)&b->sigma_r);
308 dt_opencl_set_kernel_arg(b->devid, b->global->kernel_slice, 10, sizeof(float), (void *)&detail);
309 err = dt_opencl_enqueue_kernel_2d(b->devid, b->global->kernel_slice, sizes);
310 return err;
311}
312
314{
317 if(IS_NULL_PTR(b)) return;
318 // destroy kernels
319 dt_opencl_free_kernel(b->kernel_zero);
320 dt_opencl_free_kernel(b->kernel_splat);
321 dt_opencl_free_kernel(b->kernel_blur_line);
322 dt_opencl_free_kernel(b->kernel_blur_line_z);
323 dt_opencl_free_kernel(b->kernel_slice);
324 dt_opencl_free_kernel(b->kernel_slice2);
325 dt_free(b);
326}
327
328#endif
329
330// clang-format off
331// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
332// vim: shiftwidth=2 expandtab tabstop=2 cindent
333// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
334// clang-format on
335
static void error(char *msg)
Definition ashift_lsd.c:202
void dt_bilateral_grid_size(dt_bilateral_t *b, const int width, const int height, const float L_range, float sigma_s, const float sigma_r)
Definition bilateral.c:51
size_t dt_bilateral_memory_use(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateral.c:80
size_t dt_bilateral_singlebuffer_size(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateral.c:108
float sigma_s
Definition bilateral.h:3
float sigma_r
Definition bilateral.h:3
size_t dt_bilateral_memory_use2(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateralcl.c:72
void dt_bilateral_init_cl_global(void)
Definition bilateralcl.c:46
static dt_bilateral_cl_global_t * _bilateral_cl_global
Definition bilateralcl.c:44
void dt_bilateral_free_cl(dt_bilateral_cl_t *b)
Definition bilateralcl.c:60
size_t dt_bilateral_singlebuffer_size2(const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateralcl.c:82
cl_int dt_bilateral_slice_cl(dt_bilateral_cl_t *b, cl_mem in, cl_mem out, const float detail)
cl_int dt_bilateral_slice_to_output_cl(dt_bilateral_cl_t *b, cl_mem in, cl_mem out, const float detail)
dt_bilateral_cl_t * dt_bilateral_init_cl(const int devid, const int width, const int height, const float sigma_s, const float sigma_r)
Definition bilateralcl.c:91
cl_int dt_bilateral_blur_cl(dt_bilateral_cl_t *b)
void dt_bilateral_free_cl_global(void)
cl_int dt_bilateral_splat_cl(dt_bilateral_cl_t *b, cl_mem in)
const dt_colormatrix_t dt_aligned_pixel_t out
@ DT_DEBUG_OPENCL
Definition logging.h:57
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
uint32_t width
Definition mipmap_cache.c:0
uint32_t height
Definition mipmap_cache.c:1
int dt_opencl_local_buffer_opt(const int devid, const int kernel, dt_opencl_local_buffer_t *factors)
Definition opencl.c:3713
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
Definition opencl.c:2554
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
Definition opencl.c:2970
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
Definition opencl.c:2894
int dt_opencl_create_kernel(const int prog, const char *name)
Definition opencl.c:2448
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
Definition opencl.c:2679
void dt_opencl_free_kernel(const int kernel)
Definition opencl.c:2491
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
Definition opencl.c:2545
int dt_opencl_enqueue_kernel_2d_with_local(const int dev, const int kernel, const size_t *sizes, const size_t *local)
Definition opencl.c:2560
int dt_opencl_enqueue_copy_buffer_to_buffer(const int devid, cl_mem src_buffer, cl_mem dst_buffer, size_t srcoffset, size_t dstoffset, size_t size)
Definition opencl.c:2714
void dt_opencl_release_mem_object(cl_mem mem)
Definition opencl.c:2805
#define ROUNDUP(a, n)
Definition opencl.h:82
#define ROUNDUPDHT(a, b)
Definition opencl.h:86
#define ROUNDUPDWD(a, b)
Definition opencl.h:85
size_t size_y
Definition bilateral.h:34
size_t size_z
Definition bilateral.h:34
size_t size_x
Definition bilateral.h:34
#define MAX(a, b)
Definition thinplate.c:29