Blender V4.3
render/intern/compositor.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 <cstring>
6#include <string>
7
9#include "BLI_threads.h"
10#include "BLI_vector.hh"
11
12#include "MEM_guardedalloc.h"
13
14#include "DNA_ID.h"
15
16#include "BKE_cryptomatte.hh"
17#include "BKE_global.hh"
18#include "BKE_image.hh"
19#include "BKE_node.hh"
20#include "BKE_scene.hh"
21
22#include "DRW_engine.hh"
23#include "DRW_render.hh"
24
25#include "IMB_imbuf.hh"
26
28
29#include "COM_context.hh"
30#include "COM_domain.hh"
31#include "COM_evaluator.hh"
32#include "COM_render_context.hh"
33
34#include "RE_compositor.hh"
35#include "RE_pipeline.h"
36
37#include "WM_api.hh"
38
39#include "GPU_context.hh"
40
41#include "render_types.h"
42
43namespace blender::render {
44
52 private:
61
62 public:
63 virtual ~TexturePool()
64 {
65 for (Vector<GPUTexture *> &available_textures : available_textures_.values()) {
66 for (GPUTexture *texture : available_textures) {
68 }
69 }
70
71 for (Vector<GPUTexture *> &textures_in_use : textures_in_use_.values()) {
72 for (GPUTexture *texture : textures_in_use) {
74 }
75 }
76 }
77
79 {
81 Vector<GPUTexture *> &available_textures = available_textures_.lookup_or_add_default(key);
82 GPUTexture *texture = nullptr;
83 if (available_textures.is_empty()) {
84 texture = GPU_texture_create_2d("compositor_texture_pool",
85 size.x,
86 size.y,
87 1,
88 format,
90 nullptr);
91 }
92 else {
93 texture = available_textures.pop_last();
94 }
95
96 textures_in_use_.lookup_or_add_default(key).append(texture);
97 return texture;
98 }
99
103 {
104 /* Free all textures in the available textures vectors. The fact that they still exist in those
105 * vectors after evaluation means they were not acquired during the evaluation, and are thus
106 * consequently no longer used. */
107 for (Vector<GPUTexture *> &available_textures : available_textures_.values()) {
108 for (GPUTexture *texture : available_textures) {
110 }
111 }
112
113 /* Move all textures in-use to be available textures for the next evaluation. */
114 available_textures_ = textures_in_use_;
115 textures_in_use_.clear();
116 }
117};
118
149
150/* Render Context Data */
151
153 private:
154 /* Input data. */
155 ContextInputData input_data_;
156
157 /* Output combined result. */
158 realtime_compositor::Result output_result_;
159
160 /* Viewer output result. */
161 realtime_compositor::Result viewer_output_result_;
162
163 /* Cached textures that the compositor took ownership of. */
164 Vector<GPUTexture *> textures_;
165
166 public:
169 input_data_(input_data),
170 output_result_(this->create_result(realtime_compositor::ResultType::Color)),
171 viewer_output_result_(this->create_result(realtime_compositor::ResultType::Color))
172 {
173 }
174
175 virtual ~Context()
176 {
177 output_result_.release();
178 viewer_output_result_.release();
179 for (GPUTexture *texture : textures_) {
181 }
182 }
183
184 void update_input_data(const ContextInputData &input_data)
185 {
186 input_data_ = input_data;
187 }
188
189 const Scene &get_scene() const override
190 {
191 return *input_data_.scene;
192 }
193
194 const bNodeTree &get_node_tree() const override
195 {
196 return *input_data_.node_tree;
197 }
198
199 bool use_gpu() const override
200 {
202 }
203
204 bool use_file_output() const override
205 {
206 return this->render_context() != nullptr;
207 }
208
209 bool should_compute_node_previews() const override
210 {
211 return this->render_context() == nullptr;
212 }
213
214 bool use_composite_output() const override
215 {
216 return true;
217 }
218
219 const RenderData &get_render_data() const override
220 {
221 return *(input_data_.render_data);
222 }
223
224 int2 get_render_size() const override
225 {
226 int width, height;
227 BKE_render_resolution(input_data_.render_data, true, &width, &height);
228 return int2(width, height);
229 }
230
232 {
233 const int2 render_size = get_render_size();
234 const rcti render_region = rcti{0, render_size.x, 0, render_size.y};
235
236 return render_region;
237 }
238
240 {
241 const int2 render_size = get_render_size();
242 if (output_result_.is_allocated()) {
243 /* If the allocated result have the same size as the render size, return it as is. */
244 if (render_size == output_result_.domain().size) {
245 return output_result_;
246 }
247 else {
248 /* Otherwise, the size changed, so release its data and reset it, then we reallocate it on
249 * the new render size below. */
250 output_result_.release();
251 output_result_.reset();
252 }
253 }
254
255 output_result_.allocate_texture(render_size, false);
256 return output_result_;
257 }
258
261 const bool is_data,
262 realtime_compositor::ResultPrecision precision) override
263 {
264 viewer_output_result_.set_transformation(domain.transformation);
265 viewer_output_result_.meta_data.is_non_color_data = is_data;
266
267 if (viewer_output_result_.is_allocated()) {
268 /* If the allocated result have the same size and precision as requested, return it as is. */
269 if (domain.size == viewer_output_result_.domain().size &&
270 precision == viewer_output_result_.precision())
271 {
272 return viewer_output_result_;
273 }
274 else {
275 /* Otherwise, the size or precision changed, so release its data and reset it, then we
276 * reallocate it on the new domain below. */
277 viewer_output_result_.release();
278 viewer_output_result_.reset();
279 }
280 }
281
282 viewer_output_result_.set_precision(precision);
283 viewer_output_result_.allocate_texture(domain, false);
284 return viewer_output_result_;
285 }
286
287 GPUTexture *get_input_texture(const Scene *scene,
288 int view_layer_id,
289 const char *pass_name) override
290 {
291 if (!scene) {
292 return nullptr;
293 }
294
295 Render *re = RE_GetSceneRender(scene);
296 RenderResult *rr = nullptr;
297 GPUTexture *input_texture = nullptr;
298
299 if (re) {
300 rr = RE_AcquireResultRead(re);
301 }
302
303 if (rr) {
304 ViewLayer *view_layer = (ViewLayer *)BLI_findlink(&scene->view_layers, view_layer_id);
305 if (view_layer) {
306 RenderLayer *rl = RE_GetRenderLayer(rr, view_layer->name);
307 if (rl) {
308 RenderPass *rpass = RE_pass_find_by_name(rl, pass_name, get_view_name().data());
309
310 if (rpass && rpass->ibuf && rpass->ibuf->float_buffer.data) {
311 input_texture = RE_pass_ensure_gpu_texture_cache(re, rpass);
312
313 if (input_texture) {
314 /* Don't assume render keeps texture around, add our own reference. */
315 GPU_texture_ref(input_texture);
316 textures_.append(input_texture);
317 }
318 }
319 }
320 }
321 }
322
323 if (re) {
325 re = nullptr;
326 }
327
328 return input_texture;
329 }
330
331 StringRef get_view_name() const override
332 {
333 return input_data_.view_name;
334 }
335
337 {
338 switch (input_data_.scene->r.compositor_precision) {
340 /* Auto uses full precision for final renders and half procession otherwise. */
341 if (this->render_context()) {
343 }
344 else {
346 }
349 }
350
353 }
354
355 void set_info_message(StringRef /*message*/) const override
356 {
357 /* TODO: ignored for now. Currently only used to communicate incomplete node support
358 * which is already shown on the node itself.
359 *
360 * Perhaps this overall info message could be replaced by a boolean indicating
361 * incomplete support, and leave more specific message to individual nodes? */
362 }
363
365 {
366 DrawEngineType *owner = (DrawEngineType *)this;
367 DrawData *draw_data = DRW_drawdata_ensure(id, owner, sizeof(DrawData), nullptr, nullptr);
368 IDRecalcFlag recalc_flag = IDRecalcFlag(draw_data->recalc);
369 draw_data->recalc = IDRecalcFlag(0);
370 return recalc_flag;
371 }
372
374 int view_layer_id,
375 const char *pass_name,
376 realtime_compositor::MetaData &meta_data) const override
377 {
378 ViewLayer *view_layer = static_cast<ViewLayer *>(
379 BLI_findlink(&scene->view_layers, view_layer_id));
380 if (!view_layer) {
381 return;
382 }
383
385 if (!render) {
386 return;
387 }
388
389 RenderResult *render_result = RE_AcquireResultRead(render);
390 if (!render_result || !render_result->stamp_data) {
392 return;
393 }
394
395 /* We assume the given pass is a Cryptomatte pass and retrieve its layer name. If it wasn't a
396 * Cryptomatte pass, the checks below will fail anyways. */
397 const std::string combined_pass_name = std::string(view_layer->name) + "." + pass_name;
399 combined_pass_name);
400
401 struct StampCallbackData {
402 std::string cryptomatte_layer_name;
404 };
405
406 /* Go over the stamp data and add any Cryptomatte related meta data. */
407 StampCallbackData callback_data = {cryptomatte_layer_name, &meta_data};
409 &callback_data,
410 render_result->stamp_data,
411 [](void *user_data, const char *key, char *value, int /*value_length*/) {
412 StampCallbackData *data = static_cast<StampCallbackData *>(user_data);
413
414 const std::string manifest_key = bke::cryptomatte::BKE_cryptomatte_meta_data_key(
415 data->cryptomatte_layer_name, "manifest");
416 if (key == manifest_key) {
417 data->meta_data->cryptomatte.manifest = value;
418 }
419
421 data->cryptomatte_layer_name, "hash");
422 if (key == hash_key) {
423 data->meta_data->cryptomatte.hash = value;
424 }
425
426 const std::string conversion_key = bke::cryptomatte::BKE_cryptomatte_meta_data_key(
427 data->cryptomatte_layer_name, "conversion");
428 if (key == conversion_key) {
429 data->meta_data->cryptomatte.conversion = value;
430 }
431 },
432 false);
433
434 RenderLayer *render_layer = RE_GetRenderLayer(render_result, view_layer->name);
435 if (!render_layer) {
437 return;
438 }
439
440 RenderPass *render_pass = RE_pass_find_by_name(
441 render_layer, pass_name, this->get_view_name().data());
442 if (!render_pass) {
444 return;
445 }
446
447 if (StringRef(render_pass->chan_id) == "XYZW") {
448 meta_data.is_4d_vector = true;
449 }
450
451 RE_ReleaseResult(render);
452 }
453
455 {
456 if (!output_result_.is_allocated()) {
457 return;
458 }
459
460 Render *re = RE_GetSceneRender(input_data_.scene);
462
463 if (rr) {
464 RenderView *rv = RE_RenderViewGetByName(rr, input_data_.view_name.c_str());
465 ImBuf *ibuf = RE_RenderViewEnsureImBuf(rr, rv);
466 rr->have_combined = true;
467
468 if (this->use_gpu()) {
470 float *output_buffer = static_cast<float *>(
471 GPU_texture_read(output_result_, GPU_DATA_FLOAT, 0));
472 IMB_assign_float_buffer(ibuf, output_buffer, IB_TAKE_OWNERSHIP);
473 }
474 else {
475 float *data = static_cast<float *>(
476 MEM_malloc_arrayN(rr->rectx * rr->recty, 4 * sizeof(float), __func__));
478 std::memcpy(
479 data, output_result_.float_texture(), rr->rectx * rr->recty * 4 * sizeof(float));
480 }
481 }
482
483 if (re) {
485 re = nullptr;
486 }
487
488 Image *image = BKE_image_ensure_viewer(G.main, IMA_TYPE_R_RESULT, "Render Result");
491 BKE_image_signal(G.main, image, nullptr, IMA_SIGNAL_FREE);
493 }
494
496 {
497 if (!viewer_output_result_.is_allocated()) {
498 return;
499 }
500
501 Image *image = BKE_image_ensure_viewer(G.main, IMA_TYPE_COMPOSITE, "Viewer Node");
502 const float2 translation = viewer_output_result_.domain().transformation.location();
503 image->runtime.backdrop_offset[0] = translation.x;
504 image->runtime.backdrop_offset[1] = translation.y;
505
506 if (viewer_output_result_.meta_data.is_non_color_data) {
507 image->flag &= ~IMA_VIEW_AS_RENDER;
508 }
509 else {
510 image->flag |= IMA_VIEW_AS_RENDER;
511 }
512
513 ImageUser image_user = {nullptr};
514 image_user.multi_index = BKE_scene_multiview_view_id_get(input_data_.render_data,
515 input_data_.view_name.c_str());
516
517 if (BKE_scene_multiview_is_render_view_first(input_data_.render_data,
518 input_data_.view_name.c_str()))
519 {
520 BKE_image_ensure_viewer_views(input_data_.render_data, image, &image_user);
521 }
522
524
525 void *lock;
526 ImBuf *image_buffer = BKE_image_acquire_ibuf(image, &image_user, &lock);
527
528 const int2 size = viewer_output_result_.domain().size;
529 if (image_buffer->x != size.x || image_buffer->y != size.y) {
530 imb_freerectImBuf(image_buffer);
531 imb_freerectfloatImBuf(image_buffer);
532 image_buffer->x = size.x;
533 image_buffer->y = size.y;
534 imb_addrectfloatImBuf(image_buffer, 4);
535 image_buffer->userflags |= IB_DISPLAY_BUFFER_INVALID;
536 }
537
538 BKE_image_release_ibuf(image, image_buffer, lock);
540
541 if (this->use_gpu()) {
543 float *output_buffer = static_cast<float *>(
544 GPU_texture_read(viewer_output_result_, GPU_DATA_FLOAT, 0));
545
546 std::memcpy(
547 image_buffer->float_buffer.data, output_buffer, size.x * size.y * 4 * sizeof(float));
548 MEM_freeN(output_buffer);
549 }
550 else {
551 std::memcpy(image_buffer->float_buffer.data,
552 viewer_output_result_.float_texture(),
553 size.x * size.y * 4 * sizeof(float));
554 }
555
557 if (input_data_.node_tree->runtime->update_draw) {
558 input_data_.node_tree->runtime->update_draw(input_data_.node_tree->runtime->udh);
559 }
560 }
561
563 {
564 return input_data_.render_context;
565 }
566
568 {
569 return input_data_.profiler;
570 }
571
572 void evaluate_operation_post() const override
573 {
574 /* If no render context exist, that means this is an interactive compositor evaluation due to
575 * the user editing the node tree. In that case, we wait until the operation finishes executing
576 * on the GPU before we continue to improve interactivity. The improvement comes from the fact
577 * that the user might be rapidly changing values, so we need to cancel previous evaluations to
578 * make editing faster, but we can't do that if all operations are submitted to the GPU all at
579 * once, and we can't cancel work that was already submitted to the GPU. This does have a
580 * performance penalty, but in practice, the improved interactivity is worth it according to
581 * user feedback. */
582 if (this->use_gpu() && !this->render_context()) {
583 GPU_finish();
584 }
585 }
586};
587
588/* Render Realtime Compositor */
589
591 private:
592 /* Render instance for GPU context to run compositor in. */
593 Render &render_;
594
595 std::unique_ptr<TexturePool> texture_pool_;
596 std::unique_ptr<Context> context_;
597
598 public:
600 {
601 texture_pool_ = std::make_unique<TexturePool>();
602 context_ = std::make_unique<Context>(input_data, *texture_pool_);
603 }
604
606 {
607 const bool use_gpu = context_->use_gpu();
608 if (use_gpu) {
609 /* Free resources with GPU context enabled. Cleanup may happen from the
610 * main thread, and we must use the main context there. */
611 if (BLI_thread_is_main()) {
613 }
614 else {
616 }
617 }
618
619 context_.reset();
620 texture_pool_.reset();
621
622 if (use_gpu) {
623 if (BLI_thread_is_main()) {
625 }
626 else {
628 }
629 }
630 }
631
632 /* Evaluate the compositor and output to the scene render result. */
633 void execute(const ContextInputData &input_data)
634 {
635 context_->update_input_data(input_data);
636
637 if (context_->use_gpu()) {
638 /* For main thread rendering in background mode, blocking rendering, or when we do not have a
639 * render system GPU context, use the DRW context directly, while for threaded rendering when
640 * we have a render system GPU context, use the render's system GPU context to avoid blocking
641 * with the global DST. */
642 void *re_system_gpu_context = RE_system_gpu_context_get(&render_);
643 if (BLI_thread_is_main() || re_system_gpu_context == nullptr) {
645 }
646 else {
647 void *re_system_gpu_context = RE_system_gpu_context_get(&render_);
648 WM_system_gpu_context_activate(re_system_gpu_context);
649
650 void *re_blender_gpu_context = RE_blender_gpu_context_ensure(&render_);
651
653 GPU_context_active_set(static_cast<GPUContext *>(re_blender_gpu_context));
654 }
655 }
656
657 /* Always recreate the evaluator, as this only runs on compositing node changes and
658 * there is no reason to cache this. Unlike the viewport where it helps for navigation. */
659 {
660 realtime_compositor::Evaluator evaluator(*context_);
661 evaluator.evaluate();
662 }
663
664 context_->output_to_render_result();
665 context_->viewer_output_to_viewer_image();
666 texture_pool_->free_unused_and_reset();
667
668 if (context_->use_gpu()) {
669 void *re_system_gpu_context = RE_system_gpu_context_get(&render_);
670 if (BLI_thread_is_main() || re_system_gpu_context == nullptr) {
672 }
673 else {
675 GPU_context_active_set(nullptr);
676 void *re_system_gpu_context = RE_system_gpu_context_get(&render_);
677 WM_system_gpu_context_release(re_system_gpu_context);
678 }
679 }
680 }
681};
682
683} // namespace blender::render
684
686 const RenderData &render_data,
687 const bNodeTree &node_tree,
688 const char *view_name,
691{
692 std::unique_lock lock(this->compositor_mutex);
693
695 scene, render_data, node_tree, view_name, render_context, profiler);
696
697 if (this->compositor == nullptr) {
698 this->compositor = new blender::render::RealtimeCompositor(*this, input_data);
699 }
700
701 this->compositor->execute(input_data);
702}
703
705{
706 std::unique_lock lock(this->compositor_mutex);
707
708 if (this->compositor != nullptr) {
709 delete this->compositor;
710 this->compositor = nullptr;
711 }
712}
713
715 const Scene &scene,
716 const RenderData &render_data,
717 const bNodeTree &node_tree,
718 const char *view_name,
721{
722 render.compositor_execute(scene, render_data, node_tree, view_name, render_context, profiler);
723}
724
726{
727 render.compositor_free();
728}
ImBuf * BKE_image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser)
Image * BKE_image_ensure_viewer(Main *bmain, int type, const char *name)
void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
#define IMA_SIGNAL_FREE
Definition BKE_image.hh:138
void BKE_stamp_info_callback(void *data, StampData *stamp_data, StampCallback callback, bool noskip)
void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
void BKE_image_partial_update_mark_full_update(Image *image)
Mark the whole image to be updated.
void BKE_render_resolution(const RenderData *r, const bool use_crop, int *r_width, int *r_height)
Definition scene.cc:2877
bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname)
Definition scene.cc:3002
int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
Definition scene.cc:3070
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
@ LOCK_DRAW_IMAGE
Definition BLI_threads.h:68
void BLI_thread_unlock(int type)
Definition threads.cc:333
void BLI_thread_lock(int type)
Definition threads.cc:328
int BLI_thread_is_main(void)
Definition threads.cc:179
ID and Library types, which are fundamental for SDNA.
IDRecalcFlag
Definition DNA_ID.h:1016
@ IMA_VIEW_AS_RENDER
@ IMA_TYPE_R_RESULT
@ IMA_TYPE_COMPOSITE
@ SCE_COMPOSITOR_PRECISION_FULL
@ SCE_COMPOSITOR_PRECISION_AUTO
@ SCE_COMPOSITOR_DEVICE_GPU
void DRW_gpu_context_disable()
void DRW_gpu_context_enable()
void DRW_render_context_disable(Render *render)
void DRW_render_context_enable(Render *render)
void GPU_render_end()
void GPU_render_begin()
void GPU_context_active_set(GPUContext *)
void GPU_memory_barrier(eGPUBarrier barrier)
Definition gpu_state.cc:374
void GPU_finish()
Definition gpu_state.cc:299
@ GPU_BARRIER_TEXTURE_UPDATE
Definition GPU_state.hh:39
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
void GPU_texture_ref(GPUTexture *texture)
void * GPU_texture_read(GPUTexture *texture, eGPUDataFormat data_format, int mip_level)
@ GPU_DATA_FLOAT
@ GPU_TEXTURE_USAGE_GENERAL
eGPUTextureFormat
void imb_freerectImBuf(ImBuf *ibuf)
void imb_freerectfloatImBuf(ImBuf *ibuf)
void IMB_assign_float_buffer(ImBuf *ibuf, float *buffer_data, ImBufOwnership ownership)
bool imb_addrectfloatImBuf(ImBuf *ibuf, const unsigned int channels, bool initialize_pixels=true)
@ IB_DISPLAY_BUFFER_INVALID
@ IB_TAKE_OWNERSHIP
Read Guarded memory(de)allocation.
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Color
uint32_t hash_key
volatile int lock
struct GPUContext GPUContext
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
bool is_empty() const
Result create_result(ResultType type, ResultPrecision precision)
void set_transformation(const float3x3 &transformation)
Definition result.cc:356
realtime_compositor::RenderContext * render_context
realtime_compositor::Profiler * profiler
ContextInputData(const Scene &scene, const RenderData &render_data, const bNodeTree &node_tree, const char *view_name, realtime_compositor::RenderContext *render_context, realtime_compositor::Profiler *profiler)
IDRecalcFlag query_id_recalc_flag(ID *id) const override
bool should_compute_node_previews() const override
const Scene & get_scene() const override
void set_info_message(StringRef) const override
StringRef get_view_name() const override
realtime_compositor::Result get_output_result() override
realtime_compositor::ResultPrecision get_precision() const override
void populate_meta_data_for_pass(const Scene *scene, int view_layer_id, const char *pass_name, realtime_compositor::MetaData &meta_data) const override
realtime_compositor::Result get_viewer_output_result(realtime_compositor::Domain domain, const bool is_data, realtime_compositor::ResultPrecision precision) override
realtime_compositor::Profiler * profiler() const override
void evaluate_operation_post() const override
Context(const ContextInputData &input_data, TexturePool &texture_pool)
void update_input_data(const ContextInputData &input_data)
bool use_file_output() const override
const RenderData & get_render_data() const override
bool use_composite_output() const override
rcti get_compositing_region() const override
const bNodeTree & get_node_tree() const override
GPUTexture * get_input_texture(const Scene *scene, int view_layer_id, const char *pass_name) override
realtime_compositor::RenderContext * render_context() const override
int2 get_render_size() const override
RealtimeCompositor(Render &render, const ContextInputData &input_data)
void execute(const ContextInputData &input_data)
GPUTexture * allocate_texture(int2 size, eGPUTextureFormat format) override
input_tx image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "preview_img") .compute_source("compositor_compute_preview.glsl") .do_static_compilation(true)
local_group_size(16, 16) .push_constant(Type texture
DrawData * DRW_drawdata_ensure(ID *id, DrawEngineType *engine_type, size_t size, DrawDataInitCb init_cb, DrawDataFreeCb free_cb)
format
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition mallocn.cc:45
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
StringRef BKE_cryptomatte_extract_layer_name(const StringRef render_pass_name)
std::string BKE_cryptomatte_meta_data_key(const StringRef layer_name, const StringRefNull key_name)
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
void RE_compositor_execute(Render &render, const Scene &scene, const RenderData &render_data, const bNodeTree &node_tree, const char *view_name, blender::realtime_compositor::RenderContext *render_context, blender::realtime_compositor::Profiler *profiler)
void RE_compositor_free(Render &render)
GPUTexture * RE_pass_ensure_gpu_texture_cache(Render *re, RenderPass *rpass)
RenderView * RE_RenderViewGetByName(RenderResult *rr, const char *viewname)
ImBuf * RE_RenderViewEnsureImBuf(const RenderResult *render_result, RenderView *render_view)
void * RE_blender_gpu_context_ensure(Render *re)
void * RE_system_gpu_context_get(Render *re)
RenderPass * RE_pass_find_by_name(RenderLayer *rl, const char *name, const char *viewname)
RenderResult * RE_AcquireResultWrite(Render *re)
RenderResult * RE_AcquireResultRead(Render *re)
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
void RE_ReleaseResult(Render *re)
Render * RE_GetSceneRender(const Scene *scene)
unsigned int recalc
Definition DNA_ID.h:50
Definition DNA_ID.h:413
ImBufFloatBuffer float_buffer
short multi_index
struct ImBuf * ibuf
Definition RE_pipeline.h:68
char chan_id[8]
Definition RE_pipeline.h:59
struct StampData * stamp_data
void compositor_free() override
blender::render::RealtimeCompositor * compositor
void compositor_execute(const Scene &scene, const RenderData &render_data, const bNodeTree &node_tree, const char *view_name, blender::realtime_compositor::RenderContext *render_context, blender::realtime_compositor::Profiler *profiler) override
Scene * scene
std::mutex compositor_mutex
ListBase view_layers
char name[64]
void WM_system_gpu_context_activate(void *context)
void WM_system_gpu_context_release(void *context)