Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
pixelpipe_cache_alloc.h
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18#ifndef DT_CACHES_PIXELPIPE_CACHE_ALLOC_H
19#define DT_CACHES_PIXELPIPE_CACHE_ALLOC_H
20
21/* Convenience allocators over the pixelpipe cache, bound to the application-wide
22 * cache singleton (and, for the perthread variants, to the application's OpenMP
23 * thread count).
24 *
25 * They moved here from darktable.h: they are pipeline-cache API glue, not
26 * orchestrator material. The binding is resolved inside caches/pixelpipe_cache.c
27 * and dt_get_num_openmp_threads() accessors — declared by the libs, implemented by
28 * the orchestrator (darktable.c) — so including this helper does NOT drag
29 * darktable.h (and with it the whole application) into the translation unit. */
30
31/* Kept SEPARATE from pixelpipe_cache.h on purpose. 94 translation units -- most of src/iop
32 * and src/pixel -- want the allocators below and nothing else; pixelpipe_cache.h is the
33 * cache's full API and pulls more than twice the transitive headers. Merging the two would
34 * hand 90 files a supply line they never asked for. */
35
36#include "system/macros.h"
37#include "system/mem_alloc.h"
38#include "system/openmp.h"
39
40#ifdef __cplusplus
41extern "C" {
42#endif
43
44/* Deliberately does NOT include caches/pixelpipe_cache.h. This header is the
45 * ALLOCATOR INTERFACE; the cache implementation is a develop/ concern. Pulling the full
46 * cache header in dragged develop/ into 96 files -- 11 in common/ and 16 in pixel/ --
47 * purely to allocate a buffer, i.e. an upward dependency for something the caller never
48 * touches. The three entry points below take the cache as an opaque pointer, so a tag
49 * declaration is enough; the *_perthread_impl helpers are static inline right here. */
50/* These two take NO cache handle. There is one pixelpipe cache, it is a file-static inside
51 * caches/pixelpipe_cache.c, and these resolve it there.
52 *
53 * They used to take `struct dt_dev_pixelpipe_cache_t *`, which meant the macros below had to
54 * call dt_pixelpipe_cache_get_global() to fill it -- so the accessor had to be DECLARED here,
55 * in a header 94 translation units include, handing every one of them the cache pointer
56 * whether it wanted it or not. An argument nobody chooses is not a parameter, it is a leak.
57 * The accessor still exists for the cache's own API in pixelpipe_cache.h; it is simply not
58 * part of allocating. */
59void *dt_pixelpipe_cache_alloc_align_cache_impl(size_t size, int id, const char *name);
60
61void dt_pixelpipe_cache_free_align_cache(void **mem, const char *message);
62
63#define dt_pixelpipe_cache_alloc_align_cache(size, id) \
64 dt_pixelpipe_cache_alloc_align_cache_impl((size), (id), __FILE__ ":" DT_STRINGIFY(__LINE__))
65
66#ifndef dt_pixelpipe_cache_alloc_align
67#define dt_pixelpipe_cache_alloc_align(size, pipe) \
68 dt_pixelpipe_cache_alloc_align_cache((size), (pipe)->type)
69#endif
70
71#ifndef dt_pixelpipe_cache_alloc_align_float
72#define dt_pixelpipe_cache_alloc_align_float(pixels, pipe) \
73 ((float *)dt_pixelpipe_cache_alloc_align((size_t)(pixels) * sizeof(float), (pipe)))
74#endif
75
76#ifndef dt_pixelpipe_cache_alloc_align_float_cache
77#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id) \
78 ((float *)dt_pixelpipe_cache_alloc_align_cache((size_t)(pixels) * sizeof(float), (id)))
79#endif
80
81#ifndef dt_pixelpipe_cache_alloc_align_int
82#define dt_pixelpipe_cache_alloc_align_int(count, pipe) \
83 ((int *)dt_pixelpipe_cache_alloc_align((size_t)(count) * sizeof(int), (pipe)))
84#endif
85
86/* Cache-id forms. The `pipe` forms below are sugar for these: a caller that has only
87 * the pipeline TYPE (an int) rather than the pipeline itself -- e.g. a maths solver that
88 * must not depend on develop/ -- uses these directly. */
89#ifndef dt_pixelpipe_cache_alloc_align_int_cache
90#define dt_pixelpipe_cache_alloc_align_int_cache(count, id) \
91 ((int *)dt_pixelpipe_cache_alloc_align_cache((size_t)(count) * sizeof(int), (id)))
92#endif
93
94#ifndef dt_pixelpipe_cache_alloc_align_double_cache
95#define dt_pixelpipe_cache_alloc_align_double_cache(count, id) \
96 ((double *)dt_pixelpipe_cache_alloc_align_cache((size_t)(count) * sizeof(double), (id)))
97#endif
98
99#ifndef dt_pixelpipe_cache_alloc_align_double
100#define dt_pixelpipe_cache_alloc_align_double(count, pipe) \
101 ((double *)dt_pixelpipe_cache_alloc_align((size_t)(count) * sizeof(double), (pipe)))
102#endif
103
104#define dt_pixelpipe_cache_free_align(mem) \
105 dt_pixelpipe_cache_free_align_cache((void **)&(mem), __FILE__ ":" DT_STRINGIFY(__LINE__));
106
107// Allocate a buffer for 'n' objects each of size 'objsize' bytes for each of the program's threads.
108// Ensures that there is no false sharing among threads by aligning and rounding up the allocation to
109// a multiple of the cache line size. Returns a pointer to the allocated pool and the adjusted number
110// of objects in each thread's buffer. Use dt_get_perthread or dt_get_bythread (see below) to access
111// a specific thread's buffer.
112static inline void *dt_pixelpipe_cache_alloc_perthread_impl(const size_t n, const size_t objsize, size_t* padded_size, const char *message)
113{
114 const size_t alloc_size = n * objsize;
119 if(IS_NULL_PTR(buf)) return NULL;
121}
122
123#ifndef dt_pixelpipe_cache_alloc_perthread
124#define dt_pixelpipe_cache_alloc_perthread(n, objsize, padded_size) \
125 ((void *)dt_pixelpipe_cache_alloc_perthread_impl((n), (objsize), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
126#endif
127
128static inline void *dt_pixelpipe_cache_calloc_perthread_impl(const size_t n, const size_t objsize, size_t* padded_size, const char *message)
129{
130 void *const buf = (float*)dt_pixelpipe_cache_alloc_perthread_impl(n, objsize, padded_size, message);
131 if(IS_NULL_PTR(buf)) return NULL;
133 return buf;
134}
135
136#ifndef dt_pixelpipe_cache_calloc_perthread
137#define dt_pixelpipe_cache_calloc_perthread(n, objsize, padded_size) \
138 ((void *)dt_pixelpipe_cache_calloc_perthread_impl((n), (objsize), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
139#endif
140
141// Same as dt_pixelpipe_cache_alloc_perthread, but the object is a float.
142static inline float *dt_pixelpipe_cache_alloc_perthread_float_impl(const size_t n, size_t* padded_size, const char *message)
143{
144 return (float*)dt_pixelpipe_cache_alloc_perthread_impl(n, sizeof(float), padded_size, message);
145}
146
147#ifndef dt_pixelpipe_cache_alloc_perthread_float
148#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size) \
149 ((float *)dt_pixelpipe_cache_alloc_perthread_float_impl((n), (padded_size), __FILE__ ":" DT_STRINGIFY(__LINE__)))
150#endif
151
152// Given the buffer and object count returned by dt_pixelpipe_cache_alloc_perthread, return the current thread's private buffer.
153#define dt_get_perthread(buf, padsize) DT_IS_ALIGNED((buf) + ((padsize) * dt_get_thread_num()))
154// Given the buffer and object count returned by dt_pixelpipe_cache_alloc_perthread and a thread count in 0..dt_get_num_openmp_threads()-1,
155// return a pointer to the indicated thread's private buffer.
156#define dt_get_bythread(buf, padsize, tnum) DT_IS_ALIGNED((buf) + ((padsize) * (tnum)))
157
158#ifdef __cplusplus
159}
160#endif
161
162#endif // DT_CACHES_PIXELPIPE_CACHE_ALLOC_H
163
164// clang-format off
165// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
166// vim: shiftwidth=2 expandtab tabstop=2 cindent
167// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
168// clang-format on
int dt_get_num_openmp_threads(void)
Definition darktable.c:518
#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:65
#define DT_CACHELINE_BYTES
Definition mem_alloc.h:52
size_t size
Definition mipmap_cache.c:3
const char * name
Definition pdf.h:90
void * dt_pixelpipe_cache_alloc_align_cache_impl(size_t size, int id, const char *name)
Allocate aligned memory tracked by the pixelpipe cache. This allows LRU cache entries to be evicted i...
static void * dt_pixelpipe_cache_alloc_perthread_impl(const size_t n, const size_t objsize, size_t *padded_size, const char *message)
static float * dt_pixelpipe_cache_alloc_perthread_float_impl(const size_t n, size_t *padded_size, const char *message)
void dt_pixelpipe_cache_free_align_cache(void **mem, const char *message)
Free aligned memory allocated with dt_pixelpipe_cache_alloc_align_cache.
static void * dt_pixelpipe_cache_calloc_perthread_impl(const size_t n, const size_t objsize, size_t *padded_size, const char *message)