Blender V5.0
compute_preview.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BLI_index_range.hh"
6#include "BLI_math_color.h"
8#include "BLI_task.hh"
9
10#include "DNA_node_types.h"
11
13#include "IMB_imbuf.hh"
14
15#include "GPU_shader.hh"
16#include "GPU_state.hh"
17#include "GPU_texture.hh"
18
19#include "BKE_node.hh"
20
21#include "COM_context.hh"
22#include "COM_result.hh"
23#include "COM_utilities.hh"
24
26
27namespace blender::compositor {
28
29static void compute_preview_cpu(Context &context,
30 const Result &input_result,
31 bke::bNodePreview *preview)
32{
33 const int2 input_size = input_result.domain().size;
34 const int2 preview_size = int2(preview->ibuf->x, preview->ibuf->y);
35
37 &context.get_scene().view_settings, &context.get_scene().display_settings);
38
39 threading::parallel_for(IndexRange(preview_size.y), 1, [&](const IndexRange sub_y_range) {
40 for (const int64_t y : sub_y_range) {
41 for (const int64_t x : IndexRange(preview_size.x)) {
42 const int2 coordinates = int2((float2(x, y) / float2(preview_size)) * float2(input_size));
43 float4 color = input_result.load_pixel_generic_type(coordinates);
44 if (input_result.type() == ResultType::Float) {
45 color = float4(float3(color.x), 1.0f);
46 }
47 IMB_colormanagement_processor_apply_v4(color_processor, color);
48
49 const int64_t index = (y * preview_size.x + x) * 4;
50 rgba_float_to_uchar(preview->ibuf->byte_buffer.data + index, color);
51 }
52 }
53 });
54
56}
57
58static void compute_preview_gpu(Context &context,
59 const Result &input_result,
60 bke::bNodePreview *preview)
61{
62 const int2 preview_size = int2(preview->ibuf->x, preview->ibuf->y);
63
64 gpu::Shader *shader = context.get_shader("compositor_compute_preview");
65 GPU_shader_bind(shader);
66
67 if (input_result.type() == ResultType::Float) {
68 GPU_texture_swizzle_set(input_result, "rrr1");
69 }
70
71 input_result.bind_as_texture(shader, "input_tx");
72
73 Result preview_result = context.create_result(ResultType::Color);
74 preview_result.allocate_texture(Domain(preview_size));
75 preview_result.bind_as_image(shader, "preview_img");
76
77 compute_dispatch_threads_at_least(shader, preview_size);
78
79 input_result.unbind_as_texture();
80 preview_result.unbind_as_image();
82
83 /* Restore original swizzle mask set above. */
84 if (input_result.type() == ResultType::Float) {
85 GPU_texture_swizzle_set(input_result, "rgba");
86 }
87
89 float *preview_pixels = static_cast<float *>(
90 GPU_texture_read(preview_result, GPU_DATA_FLOAT, 0));
91 preview_result.release();
92
94 &context.get_scene().view_settings, &context.get_scene().display_settings);
95
96 threading::parallel_for(IndexRange(preview_size.y), 1, [&](const IndexRange sub_y_range) {
97 for (const int64_t y : sub_y_range) {
98 for (const int64_t x : IndexRange(preview_size.x)) {
99 const int64_t index = (y * preview_size.x + x) * 4;
100 IMB_colormanagement_processor_apply_v4(color_processor, preview_pixels + index);
101 rgba_float_to_uchar(preview->ibuf->byte_buffer.data + index, preview_pixels + index);
102 }
103 }
104 });
105
106 MEM_freeN(preview_pixels);
107 IMB_colormanagement_processor_free(color_processor);
108}
109
110/* Given the size of a result, compute a lower resolution size for a preview. The greater dimension
111 * will be assigned an arbitrarily chosen size of 128, while the other dimension will get the size
112 * that maintains the same aspect ratio. */
114{
115 const int greater_dimension_size = 128;
116 if (size.x > size.y) {
117 return int2(greater_dimension_size, int(greater_dimension_size * (float(size.y) / size.x)));
118 }
119 return int2(int(greater_dimension_size * (float(size.x) / size.y)), greater_dimension_size);
120}
121
122void compute_preview(Context &context, const DNode &node, const Result &input_result)
123{
124 /* Initialize node tree previews if not already initialized. */
125 bNodeTree *root_tree = const_cast<bNodeTree *>(
126 &node.context()->derived_tree().root_context().btree());
127
128 const int2 preview_size = compute_preview_size(input_result.domain().size);
129
131 root_tree->runtime->previews, node.instance_key(), preview_size.x, preview_size.y, true);
132
133 if (context.use_gpu()) {
134 compute_preview_gpu(context, input_result, preview);
135 }
136 else {
137 compute_preview_cpu(context, input_result, preview);
138 }
139}
140
141} // namespace blender::compositor
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_unbind()
@ GPU_BARRIER_TEXTURE_FETCH
Definition GPU_state.hh:37
void GPU_memory_barrier(GPUBarrier barrier)
Definition gpu_state.cc:326
void GPU_texture_swizzle_set(blender::gpu::Texture *texture, const char swizzle[4])
@ GPU_DATA_FLOAT
void * GPU_texture_read(blender::gpu::Texture *texture, eGPUDataFormat data_format, int mip_level)
ColormanageProcessor * IMB_colormanagement_display_processor_new(const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, const ColorManagedDisplaySpace display_space=DISPLAY_SPACE_DRAW, const bool inverse=false)
void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
void allocate_texture(const Domain domain, const bool from_pool=true, const std::optional< ResultStorageType > storage_type=std::nullopt)
Definition result.cc:389
void unbind_as_texture() const
Definition result.cc:511
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
void unbind_as_image() const
Definition result.cc:517
void bind_as_image(gpu::Shader *shader, const char *image_name, bool read=false) const
Definition result.cc:498
VecBase< int, 2 > int2
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
bNodePreview * node_preview_verify(Map< bNodeInstanceKey, bNodePreview > &previews, bNodeInstanceKey key, int xsize, int ysize, bool create)
Definition node.cc:4132
static void compute_preview_cpu(Context &context, const Result &input_result, bke::bNodePreview *preview)
void compute_dispatch_threads_at_least(gpu::Shader *shader, int2 threads_range, int2 local_size=int2(16))
Definition utilities.cc:196
static void compute_preview_gpu(Context &context, const Result &input_result, bke::bNodePreview *preview)
static int2 compute_preview_size(int2 size)
void compute_preview(Context &context, const nodes::DNode &node, const Result &input_result)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
VecBase< int32_t, 2 > int2
bNodeTreeRuntimeHandle * runtime