LensSerious 0.1
Lens-correction mathematics as data, not as a library of callbacks
Loading...
Searching...
No Matches
lensserious.cl
Go to the documentation of this file.
1/*
2 LensSerious — lens correction evaluated inside the kernel that consumes it.
3
4 Copyright (C) 2026 Aurélien PIERRE. License: LGPL-3.0-or-later.
5
6 Lensfun can only produce its displacement map through single-threaded CPU callbacks
7 (measured 278 ms per 24 Mpx frame), after which a GPU pipeline uploads six floats per
8 pixel -- 576 MB for that same frame -- purely so a resampler can read them back. Here
9 the correction crosses as an ls_eval_t of scalars and each work-item evaluates its own
10 coordinates in a handful of FMAs.
11
12 THE MATH IS NOT IN THIS FILE. It is in include/lensserious_eval.h, which the CPU
13 library includes too, so there is one source text and no second copy to drift. What
14 lives here is the OpenCL-only part: the address-space plumbing and the entry points.
15
16 A consuming kernel should not call ls_map_pixel_buffer() below -- writing a map to
17 memory is the cost this library exists to remove. It should include this file and call
18 ls_eval_map()/ls_eval_vignette_factor() directly at the point it needs a source
19 coordinate. The kernels here exist so a host can verify the device against the CPU.
20*/
21
22#include "lensserious_eval.h"
23
29kernel void ls_subpixel_geometry(global float *res,
30 const int width, const int height,
31 const float xu, const float yu,
32 const ls_eval_t p)
33{
34 const int col = get_global_id(0);
35 const int row = get_global_id(1);
36 if(col >= width || row >= height) return;
37
38 float out[6];
39 ls_eval_map(&p, xu + (float)col, yu + (float)row, out);
40
41 global float *dst = res + ((size_t)row * width + col) * 6;
42 for(int k = 0; k < 6; k++) dst[k] = out[k];
43}
44
46kernel void ls_vignette_map(global float *res,
47 const int width, const int height,
48 const float xu, const float yu,
49 const ls_eval_t p)
50{
51 const int col = get_global_id(0);
52 const int row = get_global_id(1);
53 if(col >= width || row >= height) return;
54
55 res[(size_t)row * width + col] =
56 ls_eval_vignette_factor(&p, xu + (float)col, yu + (float)row);
57}
kernel void ls_vignette_map(global float *res, const int width, const int height, const float xu, const float yu, const ls_eval_t p)
kernel void ls_subpixel_geometry(global float *res, const int width, const int height, const float xu, const float yu, const ls_eval_t p)
The closed forms, written once, compiled as C99 and as OpenCL C.
static void ls_eval_map(const ls_eval_t *p, float xu, float yu, float *out)
The map for ONE output pixel: six floats, source coordinates for R, G, B.
static float ls_eval_vignette_factor(const ls_eval_t *p, float xu, float yu)
The vignetting multiplier for ONE output pixel. Multiply the pixel by it.
One lens resolved at one shooting configuration, as a flat block of scalars.