Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
test_pipe_cache_policy.c
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
31
32#include <stdarg.h>
33#include <stddef.h>
34// cmocka.h declares `extern jmp_buf global_expect_assert_env' at file scope without including
35// <setjmp.h> itself. Same suppression as test_metadata_notify.c, and for the same reason.
36#include <setjmp.h> // NOLINT(misc-include-cleaner)
37#include <stdint.h>
38#include <cmocka.h>
39
47
50{
51 (void)state;
54
55 gboolean upstream = FALSE;
56 const gboolean own = dt_dev_pipe_cache_policy_decide(&in, FALSE, &upstream);
57
58 // It requires nothing of its OWN output -- nobody downstream asked for it ...
60 // ... but the node before it must publish to host, because this one reads on the CPU.
62}
63
75
94{
95 (void)state;
97
98 gboolean upstream = TRUE;
99 const gboolean own = dt_dev_pipe_cache_policy_decide(&in, TRUE, &upstream);
100
101 // The consumer's requirement still reaches THIS node's output: that consumer reads it.
103 // ... and stops there. The node before this one publishes to this node, which is on GPU.
105}
106
113{
114 (void)state;
115 dt_dev_pipe_cache_policy_inputs_t in = { 0 }; // supports_opencl = FALSE
116
117 gboolean upstream = FALSE;
120}
121
139
142{
143 (void)state;
144 const size_t offsets[] = {
147 offsetof(dt_dev_pipe_cache_policy_inputs_t, global_hist_input_on),
149 };
150
151 for(size_t i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++)
152 {
154 *(gboolean *)((char *)&in + offsets[i]) = TRUE;
155
156 gboolean upstream = FALSE;
159 }
160}
161
164{
165 (void)state;
166 const size_t offsets[] = {
168 offsetof(dt_dev_pipe_cache_policy_inputs_t, user_requested_cache),
170 offsetof(dt_dev_pipe_cache_policy_inputs_t, global_hist_output_on),
171 };
172
173 for(size_t i = 0; i < sizeof(offsets) / sizeof(offsets[0]); i++)
174 {
176 *(gboolean *)((char *)&in + offsets[i]) = TRUE;
177
178 gboolean upstream = FALSE;
180 // None of these four says anything about what the node BEFORE this one must do.
182 }
183}
184
194
206static void _walk(const dt_dev_pipe_cache_policy_inputs_t *nodes, gboolean *out, const int count,
207 const gboolean display_reads_the_last_output)
208{
210 for(int i = count - 1; i >= 0; i--)
212}
213
219{
220 (void)state;
222 for(int i = 0; i < 4; i++) nodes[i] = _gpu_node_with_no_needs();
223
224 gboolean cached[4] = { FALSE };
225 _walk(nodes, cached, 4, TRUE);
226
227 assert_true(cached[3]); // the displayed output
228 assert_false(cached[2]); // ... and nothing else. Relayed, these were all TRUE.
231}
232
239{
240 (void)state;
242 for(int i = 0; i < 4; i++) nodes[i] = _gpu_node_with_no_needs();
243 nodes[2].supports_opencl = FALSE; // CPU-only: reads its input from RAM
244
245 gboolean cached[4] = { FALSE };
246 _walk(nodes, cached, 4, TRUE);
247
248 assert_true(cached[3]); // displayed
249 /* The CPU node's OWN flag is FALSE, and that is correct rather than an oversight: the flag
250 * asks for a device->host COPY of a module's output, and a module that ran on the CPU has
251 * already written its output in host memory. There is nothing to copy. (Asserting TRUE here
252 * is what this test caught on its first run.) */
254 assert_true(cached[1]); // its PRODUCER must publish -- this is the one that matters
255 assert_false(cached[0]); // and the requirement stops there
256}
257
260{
261 (void)state;
263 for(int i = 0; i < 3; i++) nodes[i] = _gpu_node_with_no_needs();
264
265 gboolean cached[3] = { FALSE };
266 _walk(nodes, cached, 3, FALSE);
267
268 for(int i = 0; i < 3; i++) assert_false(cached[i]);
269}
270
289
290// clang-format off
291// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
292// vim: shiftwidth=2 expandtab tabstop=2 cindent
293// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
294// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
const dt_colormatrix_t dt_aligned_pixel_t out
Whether one pipeline node must keep a host-RAM copy of its output.
static gboolean dt_dev_pipe_cache_policy_decide(const dt_dev_pipe_cache_policy_inputs_t *in, const gboolean inherited_requirement, gboolean *upstream_requirement)
Decide one node's host-cache requirement, walking the pipe from the end backwards.
const float uint32_t state[4]
Everything the decision depends on, named.
static void _gpu_node_requires_nothing_on_its_own(void **state)
static void _each_own_output_reason_raises_own(void **state)
static void _a_cpu_node_publishes_its_producer_and_no_further(void **state)
static void _only_the_displayed_output_is_cached_in_a_gpu_chain(void **state)
static void _each_own_input_reason_raises_upstream(void **state)
static void _a_cpu_node_still_makes_its_producer_publish(void **state)
int main(void)
static dt_dev_pipe_cache_policy_inputs_t _gpu_node_with_no_needs(void)
static void _a_pure_gpu_chain_nobody_reads_caches_nothing(void **state)
static void _a_gpu_node_does_not_relay_its_consumers_requirement(void **state)
static void _null_upstream_pointer_is_allowed(void **state)
static void _cpu_only_node_needs_its_input_on_host(void **state)
static void _a_gpu_node_nothing_reads_from_ram_caches_nothing(void **state)
static void _walk(const dt_dev_pipe_cache_policy_inputs_t *nodes, gboolean *out, const int count, const gboolean display_reads_the_last_output)
Walk a chain of nodes the way _seal_opencl_cache_policy() does, last to first.