Blender V5.0
parallel_reduction.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <cmath>
6#include <limits>
7
8#include "BLI_index_range.hh"
9#include "BLI_math_base.hh"
10#include "BLI_math_vector.hh"
12#include "BLI_task.hh"
13
14#include "MEM_guardedalloc.h"
15
16#include "GPU_compute.hh"
17#include "GPU_shader.hh"
18#include "GPU_state.hh"
19#include "GPU_texture.hh"
20#include "GPU_texture_pool.hh"
21
22#include "COM_context.hh"
23#include "COM_result.hh"
24
26
27namespace blender::compositor {
28
29/* Reduces the given texture into a single value and returns it. The return value should be freed
30 * by a call to MEM_freeN. The return value is either a pointer to a float, or a pointer to an
31 * array of floats that represents a vector. This depends on the given format, which should be
32 * compatible with the reduction shader.
33 *
34 * The given reduction shader should be bound when calling the function and the shader is expected
35 * to be derived from the compositor_parallel_reduction.glsl shader, see that file for more
36 * information. Also see the compositor_parallel_reduction_info.hh file for example shader
37 * definitions. */
39 gpu::Shader *shader,
41{
42 GPU_shader_uniform_1b(shader, "is_initial_reduction", true);
43
44 blender::gpu::Texture *texture_to_reduce = texture;
46
47 /* Dispatch the reduction shader until the texture reduces to a single pixel. */
48 while (size_to_reduce != int2(1)) {
49 const int2 reduced_size = math::divide_ceil(size_to_reduce, int2(16));
51 reduced_size.x, reduced_size.y, format, GPU_TEXTURE_USAGE_GENERAL);
52
54 const int texture_image_unit = GPU_shader_get_sampler_binding(shader, "input_tx");
55 GPU_texture_bind(texture_to_reduce, texture_image_unit);
56
57 const int image_unit = GPU_shader_get_sampler_binding(shader, "output_img");
58 GPU_texture_image_bind(reduced_texture, image_unit);
59
60 GPU_compute_dispatch(shader, reduced_size.x, reduced_size.y, 1);
61
62 GPU_texture_image_unbind(reduced_texture);
63 GPU_texture_unbind(texture_to_reduce);
64
65 /* Release the input texture only if it is not the source texture, since the source texture is
66 * not acquired or owned by the function. */
67 if (texture_to_reduce != texture) {
68 gpu::TexturePool::get().release_texture(texture_to_reduce);
69 }
70
71 texture_to_reduce = reduced_texture;
72 size_to_reduce = reduced_size;
73
74 GPU_shader_uniform_1b(shader, "is_initial_reduction", false);
75 }
76
78 float *pixel = static_cast<float *>(GPU_texture_read(texture_to_reduce, GPU_DATA_FLOAT, 0));
79
80 /* Release the final texture only if it is not the source texture, since the source texture is
81 * not acquired or owned by the function. */
82 if (texture_to_reduce != texture) {
83 gpu::TexturePool::get().release_texture(texture_to_reduce);
84 }
85
86 return pixel;
87}
88
89/* Reduces the given function in parallel over the given 2D range, the reduction function should
90 * have the given identity value. The given function gets as arguments the texel coordinates of the
91 * element of the range as well as a reference to the value where the result should be accumulated,
92 * while the reduction function gets a reference to two values and returns their reduction. */
93template<typename Value, typename Function, typename Reduction>
94static Value parallel_reduce(const int2 range,
95 const Value &identity,
96 const Function &function,
97 const Reduction &reduction)
98{
100 IndexRange(range.y),
101 64,
102 identity,
103 [&](const IndexRange sub_y_range, const Value &initial_value) {
104 Value result = initial_value;
105 for (const int64_t y : sub_y_range) {
106 for (const int64_t x : IndexRange(range.x)) {
107 function(int2(x, y), result);
108 }
109 }
110 return result;
111 },
112 reduction);
113}
114
115/* --------------------------------------------------------------------
116 * Sum Reductions.
117 */
118
119static float sum_red_gpu(Context &context, const Result &result)
120{
121 gpu::Shader *shader = context.get_shader("compositor_sum_red", ResultPrecision::Full);
122 GPU_shader_bind(shader);
123
124 float *reduced_value = parallel_reduction_dispatch(
126 const float sum = *reduced_value;
127 MEM_freeN(reduced_value);
129
130 return sum;
131}
132
133static float sum_red_cpu(const Result &result)
134{
135 return float(parallel_reduce(
136 result.domain().size,
137 0.0,
138 [&](const int2 texel, double &accumulated_value) {
139 accumulated_value += result.load_pixel<float4>(texel).x;
140 },
141 [&](const double &a, const double &b) { return a + b; }));
142}
143
144float sum_red(Context &context, const Result &result)
145{
146 if (context.use_gpu()) {
147 return sum_red_gpu(context, result);
148 }
149
150 return sum_red_cpu(result);
151}
152
153static float sum_green_gpu(Context &context, const Result &result)
154{
155 gpu::Shader *shader = context.get_shader("compositor_sum_green", ResultPrecision::Full);
156 GPU_shader_bind(shader);
157
158 float *reduced_value = parallel_reduction_dispatch(
160 const float sum = *reduced_value;
161 MEM_freeN(reduced_value);
163
164 return sum;
165}
166
167static float sum_green_cpu(const Result &result)
168{
169 return float(parallel_reduce(
170 result.domain().size,
171 0.0,
172 [&](const int2 texel, double &accumulated_value) {
173 accumulated_value += result.load_pixel<float4>(texel).y;
174 },
175 [&](const double &a, const double &b) { return a + b; }));
176}
177
178float sum_green(Context &context, const Result &result)
179{
180 if (context.use_gpu()) {
181 return sum_green_gpu(context, result);
182 }
183
184 return sum_green_cpu(result);
185}
186
187static float sum_blue_gpu(Context &context, const Result &result)
188{
189 gpu::Shader *shader = context.get_shader("compositor_sum_blue", ResultPrecision::Full);
190 GPU_shader_bind(shader);
191
192 float *reduced_value = parallel_reduction_dispatch(
194 const float sum = *reduced_value;
195 MEM_freeN(reduced_value);
197
198 return sum;
199}
200
201static float sum_blue_cpu(const Result &result)
202{
203 return float(parallel_reduce(
204 result.domain().size,
205 0.0,
206 [&](const int2 texel, double &accumulated_value) {
207 accumulated_value += result.load_pixel<float4>(texel).z;
208 },
209 [&](const double &a, const double &b) { return a + b; }));
210}
211
212float sum_blue(Context &context, const Result &result)
213{
214 if (context.use_gpu()) {
215 return sum_blue_gpu(context, result);
216 }
217
218 return sum_blue_cpu(result);
219}
220
221static float sum_luminance_gpu(Context &context,
222 const Result &result,
223 const float3 &luminance_coefficients)
224{
225 gpu::Shader *shader = context.get_shader("compositor_sum_luminance", ResultPrecision::Full);
226 GPU_shader_bind(shader);
227
228 GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
229
230 float *reduced_value = parallel_reduction_dispatch(
232 const float sum = *reduced_value;
233 MEM_freeN(reduced_value);
235
236 return sum;
237}
238
239static float sum_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
240{
241 return float(parallel_reduce(
242 result.domain().size,
243 0.0,
244 [&](const int2 texel, double &accumulated_value) {
245 accumulated_value += math::dot(result.load_pixel<float4>(texel).xyz(),
246 luminance_coefficients);
247 },
248 [&](const double &a, const double &b) { return a + b; }));
249}
250
251float sum_luminance(Context &context, const Result &result, const float3 &luminance_coefficients)
252{
253 if (context.use_gpu()) {
254 return sum_luminance_gpu(context, result, luminance_coefficients);
255 }
256
257 return sum_luminance_cpu(result, luminance_coefficients);
258}
259
260static float sum_log_luminance_gpu(Context &context,
261 const Result &result,
262 const float3 &luminance_coefficients)
263{
264 gpu::Shader *shader = context.get_shader("compositor_sum_log_luminance", ResultPrecision::Full);
265 GPU_shader_bind(shader);
266
267 GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
268
269 float *reduced_value = parallel_reduction_dispatch(
271 const float sum = *reduced_value;
272 MEM_freeN(reduced_value);
274
275 return sum;
276}
277
278static float sum_log_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
279{
280 return float(parallel_reduce(
281 result.domain().size,
282 0.0,
283 [&](const int2 texel, double &accumulated_value) {
284 const float luminance = math::dot(result.load_pixel<float4>(texel).xyz(),
285 luminance_coefficients);
286 accumulated_value += std::log(math::max(luminance, 1e-5f));
287 },
288 [&](const double &a, const double &b) { return a + b; }));
289}
290
292 const Result &result,
293 const float3 &luminance_coefficients)
294{
295 if (context.use_gpu()) {
296 return sum_log_luminance_gpu(context, result, luminance_coefficients);
297 }
298
299 return sum_log_luminance_cpu(result, luminance_coefficients);
300}
301
302static float4 sum_color_gpu(Context &context, const Result &result)
303{
304 gpu::Shader *shader = context.get_shader("compositor_sum_color", ResultPrecision::Full);
305 GPU_shader_bind(shader);
306
307 float *reduced_value = parallel_reduction_dispatch(
309 const float4 sum = float4(reduced_value);
310 MEM_freeN(reduced_value);
312
313 return sum;
314}
315
317{
318 return float4(parallel_reduce(
319 result.domain().size,
320 double4(0.0),
321 [&](const int2 texel, double4 &accumulated_value) {
322 accumulated_value += double4(result.load_pixel<float4>(texel));
323 },
324 [&](const double4 &a, const double4 &b) { return a + b; }));
325}
326
328{
329 if (context.use_gpu()) {
330 return sum_color_gpu(context, result);
331 }
332
333 return sum_color_cpu(result);
334}
335
336/* --------------------------------------------------------------------
337 * Sum Of Squared Difference Reductions.
338 */
339
341 const Result &result,
342 const float subtrahend)
343{
344 gpu::Shader *shader = context.get_shader("compositor_sum_red_squared_difference",
346 GPU_shader_bind(shader);
347
348 GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
349
350 float *reduced_value = parallel_reduction_dispatch(
352 const float sum = *reduced_value;
353 MEM_freeN(reduced_value);
355
356 return sum;
357}
358
359static float sum_red_squared_difference_cpu(const Result &result, const float subtrahend)
360{
361 return float(parallel_reduce(
362 result.domain().size,
363 0.0,
364 [&](const int2 texel, double &accumulated_value) {
365 accumulated_value += math::square(result.load_pixel<float4>(texel).x - subtrahend);
366 },
367 [&](const double &a, const double &b) { return a + b; }));
368}
369
370float sum_red_squared_difference(Context &context, const Result &result, const float subtrahend)
371{
372 if (context.use_gpu()) {
373 return sum_red_squared_difference_gpu(context, result, subtrahend);
374 }
375
376 return sum_red_squared_difference_cpu(result, subtrahend);
377}
378
380 const Result &result,
381 const float subtrahend)
382{
383 gpu::Shader *shader = context.get_shader("compositor_sum_green_squared_difference",
385 GPU_shader_bind(shader);
386
387 GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
388
389 float *reduced_value = parallel_reduction_dispatch(
391 const float sum = *reduced_value;
392 MEM_freeN(reduced_value);
394
395 return sum;
396}
397
398static float sum_green_squared_difference_cpu(const Result &result, const float subtrahend)
399{
400 return float(parallel_reduce(
401 result.domain().size,
402 0.0,
403 [&](const int2 texel, double &accumulated_value) {
404 accumulated_value += math::square(result.load_pixel<float4>(texel).y - subtrahend);
405 },
406 [&](const double &a, const double &b) { return a + b; }));
407}
408
409float sum_green_squared_difference(Context &context, const Result &result, const float subtrahend)
410{
411 if (context.use_gpu()) {
412 return sum_green_squared_difference_gpu(context, result, subtrahend);
413 }
414
415 return sum_green_squared_difference_cpu(result, subtrahend);
416}
417
419 const Result &result,
420 const float subtrahend)
421{
422 gpu::Shader *shader = context.get_shader("compositor_sum_blue_squared_difference",
424 GPU_shader_bind(shader);
425
426 GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
427
428 float *reduced_value = parallel_reduction_dispatch(
430 const float sum = *reduced_value;
431 MEM_freeN(reduced_value);
433
434 return sum;
435}
436
437static float sum_blue_squared_difference_cpu(const Result &result, const float subtrahend)
438{
439 return float(parallel_reduce(
440 result.domain().size,
441 0.0,
442 [&](const int2 texel, double &accumulated_value) {
443 accumulated_value += math::square(result.load_pixel<float4>(texel).z - subtrahend);
444 },
445 [&](const double &a, const double &b) { return a + b; }));
446}
447
448float sum_blue_squared_difference(Context &context, const Result &result, const float subtrahend)
449{
450 if (context.use_gpu()) {
451 return sum_blue_squared_difference_gpu(context, result, subtrahend);
452 }
453
454 return sum_blue_squared_difference_cpu(result, subtrahend);
455}
456
458 const Result &result,
459 const float3 &luminance_coefficients,
460 const float subtrahend)
461{
462 gpu::Shader *shader = context.get_shader("compositor_sum_luminance_squared_difference",
464 GPU_shader_bind(shader);
465
466 GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
467 GPU_shader_uniform_1f(shader, "subtrahend", subtrahend);
468
469 float *reduced_value = parallel_reduction_dispatch(
471 const float sum = *reduced_value;
472 MEM_freeN(reduced_value);
474
475 return sum;
476}
477
479 const float3 &luminance_coefficients,
480 const float subtrahend)
481{
482 return float(parallel_reduce(
483 result.domain().size,
484 0.0,
485 [&](const int2 texel, double &accumulated_value) {
486 const float luminance = math::dot(result.load_pixel<float4>(texel).xyz(),
487 luminance_coefficients);
488 accumulated_value += math::square(luminance - subtrahend);
489 },
490 [&](const double &a, const double &b) { return a + b; }));
491}
492
494 const Result &result,
495 const float3 &luminance_coefficients,
496 const float subtrahend)
497{
498 if (context.use_gpu()) {
500 context, result, luminance_coefficients, subtrahend);
501 }
502
503 return sum_luminance_squared_difference_cpu(result, luminance_coefficients, subtrahend);
504}
505
506/* --------------------------------------------------------------------
507 * Maximum Reductions.
508 */
509
510static float maximum_luminance_gpu(Context &context,
511 const Result &result,
512 const float3 &luminance_coefficients)
513{
514 gpu::Shader *shader = context.get_shader("compositor_maximum_luminance", ResultPrecision::Full);
515 GPU_shader_bind(shader);
516
517 GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
518
519 float *reduced_value = parallel_reduction_dispatch(
521 const float maximum = *reduced_value;
522 MEM_freeN(reduced_value);
524
525 return maximum;
526}
527
528static float maximum_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
529{
530 return float(parallel_reduce(
531 result.domain().size,
532 std::numeric_limits<float>::lowest(),
533 [&](const int2 texel, float &accumulated_value) {
534 const float luminance = math::dot(result.load_pixel<float4>(texel).xyz(),
535 luminance_coefficients);
536 accumulated_value = math::max(accumulated_value, luminance);
537 },
538 [&](const float &a, const float &b) { return math::max(a, b); }));
539}
540
542 const Result &result,
543 const float3 &luminance_coefficients)
544{
545 if (context.use_gpu()) {
546 return maximum_luminance_gpu(context, result, luminance_coefficients);
547 }
548
549 return maximum_luminance_cpu(result, luminance_coefficients);
550}
551
552static float maximum_float_gpu(Context &context, const Result &result)
553{
554 gpu::Shader *shader = context.get_shader("compositor_maximum_float", ResultPrecision::Full);
555 GPU_shader_bind(shader);
556
557 float *reduced_value = parallel_reduction_dispatch(
559 const float maximum = *reduced_value;
560 MEM_freeN(reduced_value);
562
563 return maximum;
564}
565
566static float maximum_float_cpu(const Result &result)
567{
568 return float(parallel_reduce(
569 result.domain().size,
570 std::numeric_limits<float>::lowest(),
571 [&](const int2 texel, float &accumulated_value) {
572 accumulated_value = math::max(accumulated_value, result.load_pixel<float>(texel));
573 },
574 [&](const float &a, const float &b) { return math::max(a, b); }));
575}
576
577float maximum_float(Context &context, const Result &result)
578{
579 if (context.use_gpu()) {
580 return maximum_float_gpu(context, result);
581 }
582
584}
585
587{
588 gpu::Shader *shader = context.get_shader("compositor_maximum_float2", ResultPrecision::Full);
589 GPU_shader_bind(shader);
590
591 float *reduced_value = parallel_reduction_dispatch(
593 const float2 maximum = reduced_value;
594 MEM_freeN(reduced_value);
596
597 return maximum;
598}
599
601{
602 return parallel_reduce(
603 result.domain().size,
604 float2(std::numeric_limits<float>::lowest()),
605 [&](const int2 texel, float2 &accumulated_value) {
606 accumulated_value = math::max(accumulated_value, result.load_pixel<float2>(texel));
607 },
608 [&](const float2 &a, const float2 &b) { return math::max(a, b); });
609}
610
612{
613 if (context.use_gpu()) {
614 return maximum_float2_gpu(context, result);
615 }
616
618}
619
621 const Result &result,
622 const float lower_bound,
623 const float upper_bound)
624{
625 gpu::Shader *shader = context.get_shader("compositor_maximum_float_in_range",
627 GPU_shader_bind(shader);
628
629 GPU_shader_uniform_1f(shader, "lower_bound", lower_bound);
630 GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
631
632 float *reduced_value = parallel_reduction_dispatch(
634 const float maximum = *reduced_value;
635 MEM_freeN(reduced_value);
637
638 return maximum;
639}
640
642 const float lower_bound,
643 const float upper_bound)
644{
645 return float(parallel_reduce(
646 result.domain().size,
647 lower_bound,
648 [&](const int2 texel, float &accumulated_value) {
649 const float value = result.load_pixel<float>(texel);
650 if ((value <= upper_bound) && (value >= lower_bound)) {
651 accumulated_value = math::max(accumulated_value, value);
652 }
653 },
654 [&](const float &a, const float &b) { return math::max(a, b); }));
655}
656
658 const Result &result,
659 const float lower_bound,
660 const float upper_bound)
661{
662 if (context.use_gpu()) {
663 return maximum_float_in_range_gpu(context, result, lower_bound, upper_bound);
664 }
665
666 return maximum_float_in_range_cpu(result, lower_bound, upper_bound);
667}
668
669/* --------------------------------------------------------------------
670 * Minimum Reductions.
671 */
672
673static float minimum_luminance_gpu(Context &context,
674 const Result &result,
675 const float3 &luminance_coefficients)
676{
677 gpu::Shader *shader = context.get_shader("compositor_minimum_luminance", ResultPrecision::Full);
678 GPU_shader_bind(shader);
679
680 GPU_shader_uniform_3fv(shader, "luminance_coefficients", luminance_coefficients);
681
682 float *reduced_value = parallel_reduction_dispatch(
684 const float minimum = *reduced_value;
685 MEM_freeN(reduced_value);
687
688 return minimum;
689}
690
691static float minimum_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
692{
693 return float(parallel_reduce(
694 result.domain().size,
695 std::numeric_limits<float>::max(),
696 [&](const int2 texel, float &accumulated_value) {
697 const float luminance = math::dot(result.load_pixel<float4>(texel).xyz(),
698 luminance_coefficients);
699 accumulated_value = math::min(accumulated_value, luminance);
700 },
701 [&](const float &a, const float &b) { return math::min(a, b); }));
702}
703
705 const Result &result,
706 const float3 &luminance_coefficients)
707{
708 if (context.use_gpu()) {
709 return minimum_luminance_gpu(context, result, luminance_coefficients);
710 }
711
712 return minimum_luminance_cpu(result, luminance_coefficients);
713}
714
715static float minimum_float_gpu(Context &context, const Result &result)
716{
717 gpu::Shader *shader = context.get_shader("compositor_minimum_float", ResultPrecision::Full);
718 GPU_shader_bind(shader);
719
720 float *reduced_value = parallel_reduction_dispatch(
722 const float minimum = *reduced_value;
723 MEM_freeN(reduced_value);
725
726 return minimum;
727}
728
729static float minimum_float_cpu(const Result &result)
730{
731 return float(parallel_reduce(
732 result.domain().size,
733 std::numeric_limits<float>::max(),
734 [&](const int2 texel, float &accumulated_value) {
735 accumulated_value = math::min(accumulated_value, result.load_pixel<float>(texel));
736 },
737 [&](const float &a, const float &b) { return math::min(a, b); }));
738}
739
740float minimum_float(Context &context, const Result &result)
741{
742 if (context.use_gpu()) {
743 return minimum_float_gpu(context, result);
744 }
745
747}
748
750 const Result &result,
751 const float lower_bound,
752 const float upper_bound)
753{
754 gpu::Shader *shader = context.get_shader("compositor_minimum_float_in_range",
756 GPU_shader_bind(shader);
757
758 GPU_shader_uniform_1f(shader, "lower_bound", lower_bound);
759 GPU_shader_uniform_1f(shader, "upper_bound", upper_bound);
760
761 float *reduced_value = parallel_reduction_dispatch(
763 const float minimum = *reduced_value;
764 MEM_freeN(reduced_value);
766
767 return minimum;
768}
769
771 const float lower_bound,
772 const float upper_bound)
773{
774 return parallel_reduce(
775 result.domain().size,
776 upper_bound,
777 [&](const int2 texel, float &accumulated_value) {
778 const float value = result.load_pixel<float>(texel);
779 if ((value <= upper_bound) && (value >= lower_bound)) {
780 accumulated_value = math::min(accumulated_value, value);
781 }
782 },
783 [&](const float &a, const float &b) { return math::min(a, b); });
784}
785
787 const Result &result,
788 const float lower_bound,
789 const float upper_bound)
790{
791 if (context.use_gpu()) {
792 return minimum_float_in_range_gpu(context, result, lower_bound, upper_bound);
793 }
794
795 return minimum_float_in_range_cpu(result, lower_bound, upper_bound);
796}
797
798} // namespace blender::compositor
void GPU_compute_dispatch(blender::gpu::Shader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1b(blender::gpu::Shader *sh, const char *name, bool value)
void GPU_shader_uniform_1f(blender::gpu::Shader *sh, const char *name, float value)
int GPU_shader_get_sampler_binding(blender::gpu::Shader *shader, const char *name)
void GPU_shader_uniform_3fv(blender::gpu::Shader *sh, const char *name, const float data[3])
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_unbind()
@ GPU_BARRIER_TEXTURE_FETCH
Definition GPU_state.hh:37
@ GPU_BARRIER_TEXTURE_UPDATE
Definition GPU_state.hh:39
void GPU_memory_barrier(GPUBarrier barrier)
Definition gpu_state.cc:326
int GPU_texture_height(const blender::gpu::Texture *texture)
void GPU_texture_unbind(blender::gpu::Texture *texture)
int GPU_texture_width(const blender::gpu::Texture *texture)
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_GENERAL
void * GPU_texture_read(blender::gpu::Texture *texture, eGPUDataFormat data_format, int mip_level)
void GPU_texture_image_bind(blender::gpu::Texture *texture, int unit)
void GPU_texture_image_unbind(blender::gpu::Texture *texture)
void GPU_texture_bind(blender::gpu::Texture *texture, int unit)
Read Guarded memory(de)allocation.
static T sum(const btAlignedObjectArray< T > &items)
static blender::gpu::TextureFormat gpu_texture_format(ResultType type, ResultPrecision precision)
Definition result.cc:65
blender::gpu::Texture * acquire_texture(int width, int height, blender::gpu::TextureFormat format, eGPUTextureUsage usage)
static TexturePool & get()
void release_texture(blender::gpu::Texture *tmp_tex)
nullptr float
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
VecBase< float, 4 > float4
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
float sum_red(Context &context, const Result &result)
float4 sum_color(Context &context, const Result &result)
static float2 maximum_float2_gpu(Context &context, const Result &result)
float maximum_luminance(Context &context, const Result &result, const float3 &luminance_coefficients)
static float sum_blue_squared_difference_gpu(Context &context, const Result &result, const float subtrahend)
static float * parallel_reduction_dispatch(blender::gpu::Texture *texture, gpu::Shader *shader, blender::gpu::TextureFormat format)
static float sum_blue_cpu(const Result &result)
float sum_red_squared_difference(Context &context, const Result &result, const float subtrahend)
static Value parallel_reduce(const int2 range, const Value &identity, const Function &function, const Reduction &reduction)
static float minimum_float_in_range_gpu(Context &context, const Result &result, const float lower_bound, const float upper_bound)
float sum_luminance(Context &context, const Result &result, const float3 &luminance_coefficients)
static float sum_red_gpu(Context &context, const Result &result)
static float sum_log_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
static float sum_luminance_gpu(Context &context, const Result &result, const float3 &luminance_coefficients)
static float sum_luminance_squared_difference_cpu(const Result &result, const float3 &luminance_coefficients, const float subtrahend)
float sum_blue_squared_difference(Context &context, const Result &result, const float subtrahend)
float sum_luminance_squared_difference(Context &context, const Result &result, const float3 &luminance_coefficients, const float subtrahend)
float minimum_float_in_range(Context &context, const Result &result, const float lower_bound, const float upper_bound)
float maximum_float_in_range(Context &context, const Result &result, const float lower_bound, const float upper_bound)
static float maximum_float_cpu(const Result &result)
static float4 sum_color_gpu(Context &context, const Result &result)
static float sum_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
float sum_green_squared_difference(Context &context, const Result &result, const float subtrahend)
float minimum_float(Context &context, const Result &result)
static float minimum_float_cpu(const Result &result)
float sum_green(Context &context, const Result &result)
float minimum_luminance(Context &context, const Result &result, const float3 &luminance_coefficients)
float sum_blue(Context &context, const Result &result)
static float sum_blue_gpu(Context &context, const Result &result)
static float sum_green_gpu(Context &context, const Result &result)
static float maximum_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
static float minimum_float_in_range_cpu(const Result &result, const float lower_bound, const float upper_bound)
float2 maximum_float2(Context &context, const Result &result)
static float2 maximum_float2_cpu(const Result &result)
static float sum_green_squared_difference_gpu(Context &context, const Result &result, const float subtrahend)
static float minimum_float_gpu(Context &context, const Result &result)
static float sum_red_squared_difference_cpu(const Result &result, const float subtrahend)
float maximum_float(Context &context, const Result &result)
static float minimum_luminance_cpu(const Result &result, const float3 &luminance_coefficients)
static float sum_green_squared_difference_cpu(const Result &result, const float subtrahend)
static float maximum_float_in_range_gpu(Context &context, const Result &result, const float lower_bound, const float upper_bound)
static float4 sum_color_cpu(const Result &result)
static float maximum_float_in_range_cpu(const Result &result, const float lower_bound, const float upper_bound)
float sum_log_luminance(Context &context, const Result &result, const float3 &luminance_coefficients)
static float sum_luminance_squared_difference_gpu(Context &context, const Result &result, const float3 &luminance_coefficients, const float subtrahend)
static float sum_blue_squared_difference_cpu(const Result &result, const float subtrahend)
static float maximum_luminance_gpu(Context &context, const Result &result, const float3 &luminance_coefficients)
static float sum_green_cpu(const Result &result)
static float sum_log_luminance_gpu(Context &context, const Result &result, const float3 &luminance_coefficients)
static float sum_red_cpu(const Result &result)
static float minimum_luminance_gpu(Context &context, const Result &result, const float3 &luminance_coefficients)
static float maximum_float_gpu(Context &context, const Result &result)
static float sum_red_squared_difference_gpu(Context &context, const Result &result, const float subtrahend)
VecBase< T, Size > divide_ceil(const VecBase< T, Size > &a, const VecBase< T, Size > &b)
T min(const T &a, const T &b)
T max(const T &a, const T &b)
Value parallel_reduce(IndexRange range, int64_t grain_size, const Value &identity, const Function &function, const Reduction &reduction)
Definition BLI_task.hh:151
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
VecBase< float, 3 > float3
VecBase< double, 4 > double4
static Value parallel_reduce(const int range, const Value &identity, const Function &function, const Reduction &reduction)
Definition tracking.cc:2514