Blender V4.3
realize_on_domain.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 <limits>
6
8#include "BLI_math_matrix.hh"
11#include "BLI_utildefines.h"
12
13#include "GPU_capabilities.hh"
14#include "GPU_shader.hh"
15#include "GPU_texture.hh"
16
17#include "COM_context.hh"
18#include "COM_domain.hh"
19#include "COM_result.hh"
20#include "COM_utilities.hh"
21
23
25
26static const char *get_realization_shader(Result &input,
27 const RealizationOptions &realization_options)
28{
29 if (realization_options.interpolation == Interpolation::Bicubic) {
30 switch (input.type()) {
32 return "compositor_realize_on_domain_bicubic_color";
34 return "compositor_realize_on_domain_bicubic_vector";
36 return "compositor_realize_on_domain_bicubic_float";
40 /* Realization does not support internal image types. */
41 break;
42 }
43 }
44 else {
45 switch (input.type()) {
47 return "compositor_realize_on_domain_color";
49 return "compositor_realize_on_domain_vector";
51 return "compositor_realize_on_domain_float";
55 /* Realization does not support internal image types. */
56 break;
57 }
58 }
59
61 return nullptr;
62}
63
65 Result &input,
66 Result &output,
67 const Domain &domain,
68 const float3x3 &input_transformation,
69 const RealizationOptions &realization_options)
70{
71 const Domain input_domain = Domain(input.domain().size, input_transformation);
72 if (input_domain == domain) {
73 input.pass_through(output);
74 output.set_transformation(domain.transformation);
75 return;
76 }
77
78 GPUShader *shader = context.get_shader(get_realization_shader(input, realization_options));
79 GPU_shader_bind(shader);
80
81 /* Translation from lower-left corner to center of input space. */
82 float2 input_translate(-float2(input_domain.size) / 2.0f);
83
84 /* Bias translations in case of nearest interpolation to avoids the round-to-even behavior of
85 * some GPUs at pixel boundaries. */
86 if (realization_options.interpolation == Interpolation::Nearest) {
87 input_translate += std::numeric_limits<float>::epsilon() * 10e3f;
88 }
89
90 /* Transformation from input domain with 0,0 in lower-left to virtual compositing space. */
91 const float3x3 in_transformation = math::translate(input_transformation, input_translate);
92
93 /* Transformation from output domain with 0,0 in lower-left to virtual compositing space. */
94 const float3x3 out_transformation = math::translate(domain.transformation,
95 -float2(domain.size) / 2.0f);
96
97 /* Concatenate to get full transform from output space to input space */
98 const float3x3 inverse_transformation = math::invert(in_transformation) * out_transformation;
99
100 GPU_shader_uniform_mat3_as_mat4(shader, "inverse_transformation", inverse_transformation.ptr());
101
102 /* The texture sampler should use bilinear interpolation for both the bilinear and bicubic
103 * cases, as the logic used by the bicubic realization shader expects textures to use bilinear
104 * interpolation. */
105 const bool use_bilinear = ELEM(
107 GPU_texture_filter_mode(input, use_bilinear);
108
109 /* If the input wraps, set a repeating wrap mode for out-of-bound texture access. Otherwise,
110 * make out-of-bound texture access return zero by setting a clamp to border extend mode. */
112 realization_options.wrap_x ? GPU_SAMPLER_EXTEND_MODE_REPEAT :
115 realization_options.wrap_y ? GPU_SAMPLER_EXTEND_MODE_REPEAT :
117
118 input.bind_as_texture(shader, "input_tx");
119
120 output.allocate_texture(domain);
121 output.bind_as_image(shader, "domain_img");
122
123 compute_dispatch_threads_at_least(shader, domain.size);
124
125 input.unbind_as_texture();
126 output.unbind_as_image();
128}
129
130} // namespace blender::realtime_compositor
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define ELEM(...)
void GPU_shader_uniform_mat3_as_mat4(GPUShader *sh, const char *name, const float data[3][3])
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_unbind()
void GPU_texture_extend_mode_y(GPUTexture *texture, GPUSamplerExtendMode extend_mode)
void GPU_texture_extend_mode_x(GPUTexture *texture, GPUSamplerExtendMode extend_mode)
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_CLAMP_TO_BORDER
void GPU_texture_filter_mode(GPUTexture *texture, bool use_filter)
struct GPUShader GPUShader
CartesianBasis invert(const CartesianBasis &basis)
MatBase< T, NumCol, NumRow > translate(const MatBase< T, NumCol, NumRow > &mat, const VectorT &translation)
static const char * get_realization_shader(Result &input, const RealizationOptions &realization_options)
void compute_dispatch_threads_at_least(GPUShader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:131
void realize_on_domain(Context &context, Result &input, Result &output, const Domain &domain, const float3x3 &input_transformation, const RealizationOptions &realization_options)
VecBase< float, 2 > float2
const c_style_mat & ptr() const