Blender V4.3
conversion_operation.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
6
7#include "GPU_shader.hh"
8
9#include "COM_context.hh"
12#include "COM_result.hh"
13#include "COM_utilities.hh"
14
16
17/* --------------------------------------------------------------------
18 * Conversion Operation
19 */
20
22{
23 Result &result = get_result();
24 const Result &input = get_input();
25
26 if (input.is_single_value()) {
27 result.allocate_single_value();
28 this->execute_single(input, result);
29 return;
30 }
31
32 result.allocate_texture(input.domain());
33 if (context().use_gpu()) {
35 GPU_shader_bind(shader);
36
37 input.bind_as_texture(shader, "input_tx");
38 result.bind_as_image(shader, "output_img");
39
40 compute_dispatch_threads_at_least(shader, input.domain().size);
41
42 input.unbind_as_texture();
43 result.unbind_as_image();
45 }
46 else {
47 this->execute_cpu(input, result);
48 }
49}
50
52 const Result &input_result,
53 const InputDescriptor &input_descriptor)
54{
55 ResultType result_type = input_result.type();
56 ResultType expected_type = input_descriptor.type;
57
58 /* If the result type differs from the expected type, return an instance of an appropriate
59 * conversion operation. Otherwise, return a null pointer. */
60
61 if (result_type == ResultType::Float && expected_type == ResultType::Vector) {
62 return new ConvertFloatToVectorOperation(context);
63 }
64
65 if (result_type == ResultType::Float && expected_type == ResultType::Color) {
66 return new ConvertFloatToColorOperation(context);
67 }
68
69 if (result_type == ResultType::Color && expected_type == ResultType::Float) {
70 return new ConvertColorToFloatOperation(context);
71 }
72
73 if (result_type == ResultType::Color && expected_type == ResultType::Vector) {
74 return new ConvertColorToVectorOperation(context);
75 }
76
77 if (result_type == ResultType::Vector && expected_type == ResultType::Float) {
78 return new ConvertVectorToFloatOperation(context);
79 }
80
81 if (result_type == ResultType::Vector && expected_type == ResultType::Color) {
82 return new ConvertVectorToColorOperation(context);
83 }
84
85 return nullptr;
86}
87
88/* --------------------------------------------------------------------
89 * Convert Float to Vector Operation
90 */
91
93 : ConversionOperation(context)
94{
95 InputDescriptor input_descriptor;
96 input_descriptor.type = ResultType::Float;
97 declare_input_descriptor(input_descriptor);
98 populate_result(context.create_result(ResultType::Vector));
99}
100
102{
103 output.set_vector_value(float4(float3(input.get_float_value()), 1.0f));
104}
105
107{
108 parallel_for(input.domain().size, [&](const int2 texel) {
109 output.store_pixel(texel, float4(float3(input.load_pixel(texel).x), 1.0f));
110 });
111}
112
114{
115 return context().get_shader("compositor_convert_float_to_vector");
116}
117
118/* --------------------------------------------------------------------
119 * Convert Float to Color Operation
120 */
121
123 : ConversionOperation(context)
124{
125 InputDescriptor input_descriptor;
126 input_descriptor.type = ResultType::Float;
127 declare_input_descriptor(input_descriptor);
128 populate_result(context.create_result(ResultType::Color));
129}
130
132{
133 output.set_color_value(float4(float3(input.get_float_value()), 1.0f));
134}
135
137{
138 parallel_for(input.domain().size, [&](const int2 texel) {
139 output.store_pixel(texel, float4(float3(input.load_pixel(texel).x), 1.0f));
140 });
141}
142
144{
145 return context().get_shader("compositor_convert_float_to_color");
146}
147
148/* --------------------------------------------------------------------
149 * Convert Color to Float Operation
150 */
151
153 : ConversionOperation(context)
154{
155 InputDescriptor input_descriptor;
156 input_descriptor.type = ResultType::Color;
157 declare_input_descriptor(input_descriptor);
158 populate_result(context.create_result(ResultType::Float));
159}
160
162{
163 float4 color = input.get_color_value();
164 output.set_float_value((color.x + color.y + color.z) / 3.0f);
165}
166
168{
169 parallel_for(input.domain().size, [&](const int2 texel) {
170 const float4 color = input.load_pixel(texel);
171 output.store_pixel(texel, float4((color.x + color.y + color.z) / 3.0f));
172 });
173}
174
176{
177 return context().get_shader("compositor_convert_color_to_float");
178}
179
180/* --------------------------------------------------------------------
181 * Convert Color to Vector Operation
182 */
183
185 : ConversionOperation(context)
186{
187 InputDescriptor input_descriptor;
188 input_descriptor.type = ResultType::Color;
189 declare_input_descriptor(input_descriptor);
190 populate_result(context.create_result(ResultType::Vector));
191}
192
194{
195 float4 color = input.get_color_value();
196 output.set_vector_value(color);
197}
198
200{
201 parallel_for(input.domain().size,
202 [&](const int2 texel) { output.store_pixel(texel, input.load_pixel(texel)); });
203}
204
206{
207 return context().get_shader("compositor_convert_color_to_vector");
208}
209
210/* --------------------------------------------------------------------
211 * Convert Vector to Float Operation
212 */
213
215 : ConversionOperation(context)
216{
217 InputDescriptor input_descriptor;
218 input_descriptor.type = ResultType::Vector;
219 declare_input_descriptor(input_descriptor);
220 populate_result(context.create_result(ResultType::Float));
221}
222
224{
225 float4 vector = input.get_vector_value();
226 output.set_float_value((vector[0] + vector[1] + vector[2]) / 3.0f);
227}
228
230{
231 parallel_for(input.domain().size, [&](const int2 texel) {
232 const float4 vector = input.load_pixel(texel);
233 output.store_pixel(texel, float4((vector.x + vector.y + vector.z) / 3.0f));
234 });
235}
236
238{
239 return context().get_shader("compositor_convert_vector_to_float");
240}
241
242/* --------------------------------------------------------------------
243 * Convert Vector to Color Operation
244 */
245
247 : ConversionOperation(context)
248{
249 InputDescriptor input_descriptor;
250 input_descriptor.type = ResultType::Vector;
251 declare_input_descriptor(input_descriptor);
252 populate_result(context.create_result(ResultType::Color));
253}
254
256{
257 output.set_color_value(float4(float3(input.get_vector_value()), 1.0f));
258}
259
261{
262 parallel_for(input.domain().size, [&](const int2 texel) {
263 output.store_pixel(texel, float4(input.load_pixel(texel).xyz(), 1.0f));
264 });
265}
266
268{
269 return context().get_shader("compositor_convert_vector_to_color");
270}
271
272} // namespace blender::realtime_compositor
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_unbind()
struct GPUShader GPUShader
GPUShader * get_shader(const char *info_name, ResultPrecision precision)
virtual void execute_cpu(const Result &input, Result &output)=0
virtual GPUShader * get_conversion_shader() const =0
virtual void execute_single(const Result &input, Result &output)=0
static SimpleOperation * construct_if_needed(Context &context, const Result &input_result, const InputDescriptor &input_descriptor)
void execute_cpu(const Result &input, Result &output) override
void execute_single(const Result &input, Result &output) override
void execute_cpu(const Result &input, Result &output) override
void execute_single(const Result &input, Result &output) override
void execute_single(const Result &input, Result &output) override
void execute_cpu(const Result &input, Result &output) override
void execute_cpu(const Result &input, Result &output) override
void execute_single(const Result &input, Result &output) override
void execute_single(const Result &input, Result &output) override
void execute_cpu(const Result &input, Result &output) override
void execute_cpu(const Result &input, Result &output) override
void execute_single(const Result &input, Result &output) override
static ResultType type(eGPUTextureFormat format)
Definition result.cc:148
void declare_input_descriptor(InputDescriptor descriptor)
void parallel_for(const int2 range, FunctionRef< void(int2)> function)
Definition utilities.cc:252
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:131
VecBase< float, 4 > float4
VecBase< float, 3 > float3