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) {
67 GPU_texture_free(texture);
68 }
69 }
70
71 for (Vector<GPUTexture *> &textures_in_use : textures_in_use_.values()) {
72 for (GPUTexture *texture : textures_in_use) {
73 GPU_texture_free(texture);
74 }
75 }
76 }
77
78 GPUTexture *allocate_texture(int2 size, eGPUTextureFormat format) override
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) {
109 GPU_texture_free(texture);
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:
168 : realtime_compositor::Context(texture_pool),
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_) {
180 GPU_texture_free(texture);
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
384 Render *render = RE_GetSceneRender(scene);
385 if (!render) {
386 return;
387 }
388
389 RenderResult *render_result = RE_AcquireResultRead(render);
390 if (!render_result || !render_result->stamp_data) {
391 RE_ReleaseResult(render);
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) {
436 RE_ReleaseResult(render);
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) {
443 RE_ReleaseResult(render);
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};
515 input_data_.view_name.c_str());
516
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:
599 RealtimeCompositor(Render &render, const ContextInputData &input_data) : render_(render)
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)
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
@ LOCK_DRAW_IMAGE
Definition BLI_threads.h:68
ID and Library types, which are fundamental for SDNA.
IDRecalcFlag
Definition DNA_ID.h:1016
@ IMA_TYPE_R_RESULT
@ IMA_TYPE_COMPOSITE
@ IMA_VIEW_AS_RENDER
@ 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_TAKE_OWNERSHIP
@ IB_DISPLAY_BUFFER_INVALID
Read Guarded memory(de)allocation.
uint32_t hash_key
volatile int lock
struct GPUContext GPUContext
void clear()
Definition BLI_map.hh:989
Value & lookup_or_add_default(const Key &key)
Definition BLI_map.hh:601
ValueIterator values() const
Definition BLI_map.hh:846
void append(const T &value)
bool is_empty() const
Result create_result(ResultType type, ResultPrecision precision)
static ResultPrecision precision(eGPUTextureFormat format)
Definition result.cc:125
const Domain & domain() const
Definition result.cc:712
void set_precision(ResultPrecision precision)
Definition result.cc:677
void set_transformation(const float3x3 &transformation)
Definition result.cc:356
void allocate_texture(Domain domain, bool from_pool=true)
Definition result.cc:204
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
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
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
std::mutex compositor_mutex
struct RenderData r
char name[64]
bNodeTreeRuntimeHandle * runtime
void WM_system_gpu_context_activate(void *context)
void WM_system_gpu_context_release(void *context)