Blender V4.5
symmetric_separable_blur_weights.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 <cstdint>
6#include <memory>
7
8#include "BLI_array.hh"
9#include "BLI_hash.hh"
10#include "BLI_index_range.hh"
11#include "BLI_math_base.hh"
12
13#include "RE_pipeline.h"
14
15#include "GPU_texture.hh"
16
17#include "COM_context.hh"
18#include "COM_result.hh"
20
21namespace blender::compositor {
22
23/* --------------------------------------------------------------------
24 * Symmetric Separable Blur Weights Key.
25 */
26
31
36
39{
40 return a.type == b.type && a.radius == b.radius;
41}
42
43/* --------------------------------------------------------------------
44 * Symmetric Separable Blur Weights.
45 */
46
48 int type,
49 float radius)
50 : result(context.create_result(ResultType::Float))
51{
52 /* The size of filter is double the radius plus 1, but since the filter is symmetric, we only
53 * compute half of it and no doubling happens. We add 1 to make sure the filter size is always
54 * odd and there is a center weight. */
55 const int size = math::ceil(radius) + 1;
56 weights_ = Array<float>(size);
57
58 float sum = 0.0f;
59
60 /* First, compute the center weight. */
61 const float center_weight = RE_filter_value(type, 0.0f);
62 weights_[0] = center_weight;
63 sum += center_weight;
64
65 /* Second, compute the other weights in the positive direction, making sure to add double the
66 * weight to the sum of weights because the filter is symmetric and we only loop over half of
67 * it. Skip the center weight already computed by dropping the front index. */
68 const float scale = radius > 0.0f ? 1.0f / radius : 0.0f;
69 for (const int i : weights_.index_range().drop_front(1)) {
70 const float weight = RE_filter_value(type, i * scale);
71 weights_[i] = weight;
72 sum += weight * 2.0f;
73 }
74
75 /* Finally, normalize the weights. */
76 for (const int i : weights_.index_range()) {
77 weights_[i] /= sum;
78 }
79
80 if (context.use_gpu()) {
81 this->result.allocate_texture(Domain(int2(size, 1)), false);
82 GPU_texture_update(this->result, GPU_DATA_FLOAT, weights_.data());
83
84 /* CPU-side data no longer needed, so free it. */
85 weights_ = Array<float>();
86 }
87 else {
88 this->result.wrap_external(weights_.data(), int2(size, 1));
89 }
90}
91
96
97/* --------------------------------------------------------------------
98 * Symmetric Separable Blur Weights Container.
99 */
100
102{
103 /* First, delete all resources that are no longer needed. */
104 map_.remove_if([](auto item) { return !item.value->needed; });
105
106 /* Second, reset the needed status of the remaining resources to false to ready them to track
107 * their needed status for the next evaluation. */
108 for (auto &value : map_.values()) {
109 value->needed = false;
110 }
111}
112
114{
115 const SymmetricSeparableBlurWeightsKey key(type, radius);
116
117 auto &weights = *map_.lookup_or_add_cb(key, [&]() {
118 return std::make_unique<SymmetricSeparableBlurWeights>(context, type, radius);
119 });
120
121 weights.needed = true;
122 return weights.result;
123}
124
125} // namespace blender::compositor
@ GPU_DATA_FLOAT
void GPU_texture_update(GPUTexture *texture, eGPUDataFormat data_format, const void *data)
unsigned long long int uint64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static T sum(const btAlignedObjectArray< T > &items)
SymmetricSeparableBlurWeights(Context &context, int type, float radius)
float RE_filter_value(int type, float x)
bool operator==(const BokehKernelKey &a, const BokehKernelKey &b)
T ceil(const T &a)
uint64_t get_default_hash(const T &v, const Args &...args)
Definition BLI_hash.hh:233
VecBase< int32_t, 2 > int2
i
Definition text_draw.cc:230