Blender V4.3
morphological_distance_feather.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 "BLI_math_base.hh"
7
8#include "GPU_shader.hh"
9#include "GPU_texture.hh"
10
11#include "COM_algorithm_morphological_distance_feather.hh" /* Own include. */
12#include "COM_context.hh"
14#include "COM_result.hh"
15#include "COM_utilities.hh"
16
18
19static const char *get_shader_name(int distance)
20{
21 if (distance > 0) {
22 return "compositor_morphological_distance_feather_dilate";
23 }
24 return "compositor_morphological_distance_feather_erode";
25}
26
27static Result horizontal_pass(Context &context, Result &input, int distance, int falloff_type)
28{
29 GPUShader *shader = context.get_shader(get_shader_name(distance));
30 GPU_shader_bind(shader);
31
32 input.bind_as_texture(shader, "input_tx");
33
35 context.cache_manager().morphological_distance_feather_weights.get(
36 context, falloff_type, math::abs(distance));
37 weights.bind_weights_as_texture(shader, "weights_tx");
38 weights.bind_distance_falloffs_as_texture(shader, "falloffs_tx");
39
40 /* We allocate an output image of a transposed size, that is, with a height equivalent to the
41 * width of the input and vice versa. This is done as a performance optimization. The shader
42 * will process the image horizontally and write it to the intermediate output transposed. Then
43 * the vertical pass will execute the same horizontal pass shader, but since its input is
44 * transposed, it will effectively do a vertical pass and write to the output transposed,
45 * effectively undoing the transposition in the horizontal pass. This is done to improve
46 * spatial cache locality in the shader and to avoid having two separate shaders for each of
47 * the passes. */
48 const Domain domain = input.domain();
49 const int2 transposed_domain = int2(domain.size.y, domain.size.x);
50
51 Result output = context.create_result(ResultType::Float);
52 output.allocate_texture(transposed_domain);
53 output.bind_as_image(shader, "output_img");
54
55 compute_dispatch_threads_at_least(shader, domain.size);
56
58 input.unbind_as_texture();
61 output.unbind_as_image();
62
63 return output;
64}
65
66static void vertical_pass(Context &context,
67 Result &original_input,
68 Result &horizontal_pass_result,
69 Result &output,
70 int distance,
71 int falloff_type)
72{
73 GPUShader *shader = context.get_shader(get_shader_name(distance));
74 GPU_shader_bind(shader);
75
76 horizontal_pass_result.bind_as_texture(shader, "input_tx");
77
79 context.cache_manager().morphological_distance_feather_weights.get(
80 context, falloff_type, math::abs(distance));
81 weights.bind_weights_as_texture(shader, "weights_tx");
82 weights.bind_distance_falloffs_as_texture(shader, "falloffs_tx");
83
84 const Domain domain = original_input.domain();
85 output.allocate_texture(domain);
86 output.bind_as_image(shader, "output_img");
87
88 /* Notice that the domain is transposed, see the note on the horizontal pass function for more
89 * information on the reasoning behind this. */
90 compute_dispatch_threads_at_least(shader, int2(domain.size.y, domain.size.x));
91
93 horizontal_pass_result.unbind_as_texture();
96 output.unbind_as_image();
97}
98
100 Context &context, Result &input, Result &output, int distance, int falloff_type)
101{
102 Result horizontal_pass_result = horizontal_pass(context, input, distance, falloff_type);
103 vertical_pass(context, input, horizontal_pass_result, output, distance, falloff_type);
104 horizontal_pass_result.release();
105}
106
107} // namespace blender::realtime_compositor
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_unbind()
struct GPUShader GPUShader
#define output
void bind_distance_falloffs_as_texture(GPUShader *shader, const char *texture_name) const
void bind_weights_as_texture(GPUShader *shader, const char *texture_name) const
const Domain & domain() const
Definition result.cc:712
void allocate_texture(Domain domain, bool from_pool=true)
Definition result.cc:204
void bind_as_texture(GPUShader *shader, const char *texture_name) const
Definition result.cc:253
T abs(const T &a)
static const char * get_shader_name(int distance)
static void vertical_pass(Context &context, Result &original_input, Result &horizontal_pass_result, Result &output, int distance, int falloff_type)
static Result horizontal_pass(Context &context, Result &input, int distance, int falloff_type)
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:131
void morphological_distance_feather(Context &context, Result &input, Result &output, int distance, int falloff_type=PROP_SMOOTH)
VecBase< int32_t, 2 > int2