Blender V5.0
node_composite_group_input.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_string_ref.hh"
6
7#include "GPU_shader.hh"
8
9#include "BLT_translation.hh"
10
11#include "UI_resources.hh"
12
13#include "DNA_space_types.h"
14
15#include "BKE_context.hh"
16
17#include "NOD_composite.hh"
19
20#include "COM_node_operation.hh"
21#include "COM_utilities.hh"
22
24
25using namespace blender::compositor;
26
28 public:
30
31 void execute() override
32 {
33 for (const bNodeSocket *output : this->node()->output_sockets()) {
35 continue;
36 }
37
38 Result &result = this->get_result(output->identifier);
39 if (!result.should_compute()) {
40 continue;
41 }
42
43 const Result pass = this->context().get_input(output->name);
44 this->execute_pass(pass, result);
45 }
46 }
47
48 void execute_pass(const Result &pass, Result &result)
49 {
50 if (!pass.is_allocated()) {
51 /* Pass not rendered yet, or not supported by viewport. */
52 result.allocate_invalid();
53 return;
54 }
55
56 if (!this->context().is_valid_compositing_region()) {
57 result.allocate_invalid();
58 return;
59 }
60
61 result.set_type(pass.type());
62 result.set_precision(pass.precision());
63
64 if (this->context().use_gpu()) {
65 this->execute_pass_gpu(pass, result);
66 }
67 else {
68 this->execute_pass_cpu(pass, result);
69 }
70 result.set_transformation(pass.domain().transformation);
71 }
72
74 {
75 gpu::Shader *shader = this->context().get_shader(this->get_shader_name(pass),
76 result.precision());
77 GPU_shader_bind(shader);
78
79 /* The compositing space might be limited to a subset of the pass texture, so only read that
80 * compositing region into an appropriately sized result. */
81 const int2 lower_bound = this->context().get_compositing_region().min;
82 GPU_shader_uniform_2iv(shader, "lower_bound", lower_bound);
83
84 pass.bind_as_texture(shader, "input_tx");
85
86 result.allocate_texture(Domain(this->context().get_compositing_region_size()));
87 result.bind_as_image(shader, "output_img");
88
89 compute_dispatch_threads_at_least(shader, result.domain().size);
90
92 pass.unbind_as_texture();
93 result.unbind_as_image();
94 }
95
96 const char *get_shader_name(const Result &pass)
97 {
98 switch (pass.type()) {
100 return "compositor_read_input_float";
104 return "compositor_read_input_float4";
105 case ResultType::Int:
106 case ResultType::Int2:
108 case ResultType::Bool:
109 case ResultType::Menu:
110 /* Not supported. */
111 break;
113 /* Single only types do not support GPU code path. */
116 break;
117 }
118
120 return nullptr;
121 }
122
124 {
125 /* The compositing space might be limited to a subset of the pass texture, so only read that
126 * compositing region into an appropriately sized result. */
127 const int2 lower_bound = this->context().get_compositing_region().min;
128
131 pass.domain().size;
132 result.allocate_texture(size);
133
134 parallel_for(size, [&](const int2 texel) {
135 result.store_pixel_generic_type(texel, pass.load_pixel_generic_type(texel + lower_bound));
136 });
137 }
138};
139
140} // namespace blender::nodes::node_composite_group_input_cc
141
142namespace blender::nodes {
143
149
151{
152 if (parameters.tree.type != NTREE_COMPOSIT) {
153 return;
154 }
155
156 SpaceNode *space_node = CTX_wm_space_node(&parameters.C);
157 if (space_node->edittree != space_node->nodetree) {
158 return;
159 }
160
162 return;
163 }
164
165 Span<const bNodeSocket *> group_inputs = parameters.node.output_sockets().drop_back(1);
166 bool added_warning_for_unsupported_inputs = false;
167 for (const bNodeSocket *input : group_inputs) {
168 if (StringRef(input->name) == "Image") {
169 if (input->type != SOCK_RGBA) {
171 row.text = IFACE_("Wrong Image Input Type");
172 row.icon = ICON_ERROR;
173 row.tooltip = TIP_("Node group's main Image input should be of type Color");
174 parameters.rows.append(std::move(row));
175 }
176 }
177 else if (StringRef(input->name) == "Mask") {
178 if (input->type != SOCK_RGBA) {
180 row.text = IFACE_("Wrong Mask Input Type");
181 row.icon = ICON_ERROR;
182 row.tooltip = TIP_("Node group's Mask input should be of type Color");
183 parameters.rows.append(std::move(row));
184 }
185 }
186 else {
187 if (added_warning_for_unsupported_inputs) {
188 continue;
189 }
191 row.text = IFACE_("Unsupported Inputs");
192 row.icon = ICON_WARNING_LARGE;
193 row.tooltip = TIP_(
194 "Only a main Image and Mask inputs are supported, the rest are unsupported and will "
195 "return zero");
196 parameters.rows.append(std::move(row));
197 added_warning_for_unsupported_inputs = true;
198 }
199 }
200}
201
202} // namespace blender::nodes
SpaceNode * CTX_wm_space_node(const bContext *C)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define TIP_(msgid)
#define IFACE_(msgid)
@ NTREE_COMPOSIT
@ SOCK_RGBA
@ SNODE_COMPOSITOR_SEQUENCER
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_unbind()
void GPU_shader_uniform_2iv(blender::gpu::Shader *sh, const char *name, const int data[2])
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void append(const T &value)
virtual bool use_context_bounds_for_input_output() const
virtual Result get_input(StringRef name)=0
virtual Bounds< int2 > get_compositing_region() const =0
gpu::Shader * get_shader(const char *info_name, ResultPrecision precision)
NodeOperation(Context &context, DNode node)
Result & get_result(StringRef identifier)
Definition operation.cc:39
void unbind_as_texture() const
Definition result.cc:511
bool is_allocated() const
Definition result.cc:763
static bool is_single_value_only_type(ResultType type)
Definition result.cc:44
static ResultType type(blender::gpu::TextureFormat format)
Definition result.cc:261
void bind_as_texture(gpu::Shader *shader, const char *texture_name) const
Definition result.cc:487
const Domain & domain() const
static ResultPrecision precision(blender::gpu::TextureFormat format)
Definition result.cc:233
float4 load_pixel_generic_type(const int2 &texel) const
#define input
#define output
void compute_dispatch_threads_at_least(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:196
void parallel_for(const int2 range, const Function &function)
bool is_socket_available(const bNodeSocket *socket)
Definition utilities.cc:27
void get_compositor_group_input_extra_info(blender::nodes::NodeExtraInfoParams &parameters)
compositor::NodeOperation * get_group_input_compositor_operation(compositor::Context &context, DNode node)
VecBase< int32_t, 2 > int2
char node_tree_sub_type
struct bNodeTree * edittree
struct bNodeTree * nodetree
Vector< NodeExtraInfoRow > & rows