Blender V4.3
intern/engine.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2006 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstddef>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_ghash.h"
16#include "BLI_listbase.h"
17#include "BLI_math_bits.h"
18#include "BLI_string.h"
19#include "BLI_utildefines.h"
20
21#include "DNA_object_types.h"
22
23#include "BKE_camera.h"
24#include "BKE_global.hh"
25#include "BKE_node.hh"
26#include "BKE_report.hh"
27#include "BKE_scene.hh"
28
29#include "DEG_depsgraph.hh"
32
33#include "GPU_context.hh"
34
35#ifdef WITH_PYTHON
36# include "BPY_extern.hh"
37#endif
38
39#include "IMB_imbuf_types.hh"
40
41#include "RE_bake.h"
42#include "RE_engine.h"
43#include "RE_pipeline.h"
44
45#include "DRW_engine.hh"
46
47#include "WM_api.hh"
48
49#include "pipeline.hh"
50#include "render_result.h"
51#include "render_types.h"
52
53/* Render Engine Types */
54
55ListBase R_engines = {nullptr, nullptr};
56
61
63{
64 RenderEngineType *type, *next;
65
67
68 for (type = static_cast<RenderEngineType *>(R_engines.first); type; type = next) {
69 next = type->next;
70
71 BLI_remlink(&R_engines, type);
72
73 if (!(type->flag & RE_INTERNAL)) {
74 if (type->rna_ext.free) {
75 type->rna_ext.free(type->rna_ext.data);
76 }
77
78 MEM_freeN(type);
79 }
80 }
81}
82
84{
85 if (render_type->draw_engine) {
86 DRW_engine_register(render_type->draw_engine);
87 }
88 BLI_addtail(&R_engines, render_type);
89}
90
92{
93 RenderEngineType *type = static_cast<RenderEngineType *>(
95 if (!type) {
96 type = static_cast<RenderEngineType *>(
97 BLI_findstring(&R_engines, "BLENDER_EEVEE_NEXT", offsetof(RenderEngineType, idname)));
98 }
99
100 return type;
101}
102
104{
105 return (re->engine && re->engine->type && re->engine->type->render);
106}
107
109{
110 if ((render_type->flag & RE_USE_ALEMBIC_PROCEDURAL) == 0) {
111 return false;
112 }
113
115 return false;
116 }
117
118 return true;
119}
120
121/* Create, Free */
122
124{
125 RenderEngine *engine = MEM_cnew<RenderEngine>("RenderEngine");
126 engine->type = type;
127
130
131 return engine;
132}
133
135{
136 if (engine->depsgraph) {
137 /* Need GPU context since this might free GPU buffers. */
138 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
139 if (use_gpu_context) {
140 /* This function can be called on the main thread before RenderEngine is destroyed.
141 * In this case, just bind the main draw context to gather the deleted GPU buffers.
142 * Binding the same GPU context as the render engine is not needed (see #129019). */
143 if (BLI_thread_is_main()) {
145 }
146 else {
148 }
149 }
150
151 DEG_graph_free(engine->depsgraph);
152 engine->depsgraph = nullptr;
153
154 if (use_gpu_context) {
155 if (BLI_thread_is_main()) {
157 }
158 else {
160 }
161 }
162 }
163}
164
166{
167#ifdef WITH_PYTHON
168 if (engine->py_instance) {
170 }
171#endif
172
173 engine_depsgraph_free(engine);
174
177
178 MEM_freeN(engine);
179}
180
181/* Bake Render Results */
182
184 RenderEngine *engine, int x, int y, int w, int h, const char *layername)
185{
186 BakeImage *image = &engine->bake.targets->images[engine->bake.image_id];
187 const BakePixel *pixels = engine->bake.pixels + image->offset;
188 const size_t channels_num = engine->bake.targets->channels_num;
189
190 /* Remember layer name for to match images in render_frame_finish. */
191 if (image->render_layer_name[0] == '\0') {
192 STRNCPY(image->render_layer_name, layername);
193 }
194
195 /* Create render result with specified size. */
196 RenderResult *rr = MEM_cnew<RenderResult>(__func__);
197
198 rr->rectx = w;
199 rr->recty = h;
200 rr->tilerect.xmin = x;
201 rr->tilerect.ymin = y;
202 rr->tilerect.xmax = x + w;
203 rr->tilerect.ymax = y + h;
204
205 /* Add single baking render layer. */
206 RenderLayer *rl = MEM_cnew<RenderLayer>("bake render layer");
207 STRNCPY(rl->name, layername);
208 rl->rectx = w;
209 rl->recty = h;
210 BLI_addtail(&rr->layers, rl);
211
212 /* Add render passes. */
213 render_layer_add_pass(rr, rl, channels_num, RE_PASSNAME_COMBINED, "", "RGBA", true);
214
215 RenderPass *primitive_pass = render_layer_add_pass(rr, rl, 3, "BakePrimitive", "", "RGB", true);
216 RenderPass *differential_pass = render_layer_add_pass(
217 rr, rl, 4, "BakeDifferential", "", "RGBA", true);
218
219 /* Per-pixel seeds are only needed for baking to vertex colors, see
220 * bake_targets_populate_pixels_color_attributes for more details. */
221 RenderPass *seed_pass = (image->image == nullptr) ?
222 render_layer_add_pass(rr, rl, 1, "BakeSeed", "", "X", true) :
223 nullptr;
224
225 /* Fill render passes from bake pixel array, to be read by the render engine. */
226 for (int ty = 0; ty < h; ty++) {
227 size_t offset = ty * w;
228 float *primitive = primitive_pass->ibuf->float_buffer.data + 3 * offset;
229 float *seed = (seed_pass != nullptr) ? (seed_pass->ibuf->float_buffer.data + offset) : nullptr;
230 float *differential = differential_pass->ibuf->float_buffer.data + 4 * offset;
231
232 size_t bake_offset = (y + ty) * image->width + x;
233 const BakePixel *bake_pixel = pixels + bake_offset;
234
235 for (int tx = 0; tx < w; tx++) {
236 if (bake_pixel->object_id != engine->bake.object_id) {
237 primitive[0] = int_as_float(-1);
238 primitive[1] = int_as_float(-1);
239 primitive[2] = int_as_float(-1);
240 }
241 else {
242 primitive[0] = bake_pixel->uv[0];
243 primitive[1] = bake_pixel->uv[1];
244 primitive[2] = int_as_float(bake_pixel->primitive_id);
245
246 differential[0] = bake_pixel->du_dx;
247 differential[1] = bake_pixel->du_dy;
248 differential[2] = bake_pixel->dv_dx;
249 differential[3] = bake_pixel->dv_dy;
250 }
251
252 if (seed_pass != nullptr) {
253 *seed = int_as_float(bake_pixel->seed);
254 seed += 1;
255 }
256
257 primitive += 3;
258 differential += 4;
259 bake_pixel++;
260 }
261 }
262
263 return rr;
264}
265
267{
268 RenderLayer *rl = static_cast<RenderLayer *>(rr->layers.first);
270 if (!rpass) {
271 return;
272 }
273
274 /* Find bake image corresponding to layer. */
275 int image_id = 0;
276 for (; image_id < engine->bake.targets->images_num; image_id++) {
277 if (STREQ(engine->bake.targets->images[image_id].render_layer_name, rl->name)) {
278 break;
279 }
280 }
281 if (image_id == engine->bake.targets->images_num) {
282 return;
283 }
284
285 const BakeImage *image = &engine->bake.targets->images[image_id];
286 const BakePixel *pixels = engine->bake.pixels + image->offset;
287 const size_t channels_num = engine->bake.targets->channels_num;
288 const size_t channels_size = channels_num * sizeof(float);
289 float *result = engine->bake.result + image->offset * channels_num;
290
291 /* Copy from tile render result to full image bake result. Just the pixels for the
292 * object currently being baked, to preserve other objects when baking multiple. */
293 const int x = rr->tilerect.xmin;
294 const int y = rr->tilerect.ymin;
295 const int w = rr->tilerect.xmax - rr->tilerect.xmin;
296 const int h = rr->tilerect.ymax - rr->tilerect.ymin;
297
298 for (int ty = 0; ty < h; ty++) {
299 const size_t offset = ty * w;
300 const size_t bake_offset = (y + ty) * image->width + x;
301
302 const float *pass_rect = rpass->ibuf->float_buffer.data + offset * channels_num;
303 const BakePixel *bake_pixel = pixels + bake_offset;
304 float *bake_result = result + bake_offset * channels_num;
305
306 for (int tx = 0; tx < w; tx++) {
307 if (bake_pixel->object_id == engine->bake.object_id) {
308 memcpy(bake_result, pass_rect, channels_size);
309 }
310 pass_rect += channels_num;
311 bake_result += channels_num;
312 bake_pixel++;
313 }
314 }
315}
316
317/* Render Results */
318
320 RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
321{
322 if (engine->bake.targets) {
323 RenderResult *result = render_result_from_bake(engine, x, y, w, h, layername);
324 BLI_addtail(&engine->fullresult, result);
325 return result;
326 }
327
328 Render *re = engine->re;
330 rcti disprect;
331
332 /* ensure the coordinates are within the right limits */
333 CLAMP(x, 0, re->result->rectx);
334 CLAMP(y, 0, re->result->recty);
335 CLAMP(w, 0, re->result->rectx);
336 CLAMP(h, 0, re->result->recty);
337
338 if (x + w > re->result->rectx) {
339 w = re->result->rectx - x;
340 }
341 if (y + h > re->result->recty) {
342 h = re->result->recty - y;
343 }
344
345 /* allocate a render result */
346 disprect.xmin = x;
347 disprect.xmax = x + w;
348 disprect.ymin = y;
349 disprect.ymax = y + h;
350
351 result = render_result_new(re, &disprect, layername, viewname);
352
353 /* TODO: make this thread safe. */
354
355 /* can be nullptr if we CLAMP the width or height to 0 */
356 if (result) {
357 render_result_clone_passes(re, result, viewname);
359
360 BLI_addtail(&engine->fullresult, result);
361
362 result->tilerect.xmin += re->disprect.xmin;
363 result->tilerect.xmax += re->disprect.xmin;
364 result->tilerect.ymin += re->disprect.ymin;
365 result->tilerect.ymax += re->disprect.ymin;
366 }
367
368 return result;
369}
370
381
383{
384 if (engine->bake.targets) {
385 /* No interactive baking updates for now. */
386 return;
387 }
388
389 Render *re = engine->re;
390
391 if (result) {
393 render_result_merge(re->result, result);
394 result->renlay = static_cast<RenderLayer *>(
395 result->layers.first); /* weak, draws first layer always */
396 re->display_update(result, nullptr);
397 }
398}
399
401 const char *name,
402 int channels,
403 const char *chan_id,
404 const char *layername)
405{
406 Render *re = engine->re;
407
408 if (!re || !re->result) {
409 return;
410 }
411
412 RE_create_render_pass(re->result, name, channels, chan_id, layername, nullptr, false);
413}
414
416 RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
417{
418 Render *re = engine->re;
419
420 if (!result) {
421 return;
422 }
423
424 if (engine->bake.targets) {
425 if (!cancel || merge_results) {
426 render_result_to_bake(engine, result);
427 }
428 BLI_remlink(&engine->fullresult, result);
429 render_result_free(result);
430 return;
431 }
432
433 if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES)) {
435
436 if (tile_highlight) {
437 if (highlight) {
438 tile_highlight->highlight_tile_for_result(result);
439 }
440 else {
441 tile_highlight->unhighlight_tile_for_result(result);
442 }
443 }
444 }
445
446 if (!cancel || merge_results) {
447 if (!(re->test_break() && (re->r.scemode & R_BUTS_PREVIEW))) {
449 render_result_merge(re->result, result);
450 }
451
452 /* draw */
453 if (!re->test_break()) {
454 result->renlay = static_cast<RenderLayer *>(
455 result->layers.first); /* weak, draws first layer always */
456 re->display_update(result, nullptr);
457 }
458 }
459
460 /* free */
461 BLI_remlink(&engine->fullresult, result);
462 render_result_free(result);
463}
464
466{
467 return engine->re->result;
468}
469
470/* Cancel */
471
473{
474 Render *re = engine->re;
475
476 if (re) {
477 return re->test_break();
478 }
479
480 return false;
481}
482
483/* Statistics */
484
485void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
486{
487 Render *re = engine->re;
488
489 /* stats draw callback */
490 if (re) {
491 re->i.statstr = stats;
492 re->i.infostr = info;
493 re->stats_draw(&re->i);
494 re->i.infostr = nullptr;
495 re->i.statstr = nullptr;
496 }
497
498 /* set engine text */
499 engine->text[0] = '\0';
500
501 if (stats && stats[0] && info && info[0]) {
502 SNPRINTF(engine->text, "%s | %s", stats, info);
503 }
504 else if (info && info[0]) {
505 STRNCPY(engine->text, info);
506 }
507 else if (stats && stats[0]) {
508 STRNCPY(engine->text, stats);
509 }
510}
511
512void RE_engine_update_progress(RenderEngine *engine, float progress)
513{
514 Render *re = engine->re;
515
516 if (re) {
517 CLAMP(progress, 0.0f, 1.0f);
518 re->progress(progress);
519 }
520}
521
522void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
523{
524 Render *re = engine->re;
525
526 if (re) {
527 re->i.mem_used = mem_used;
528 re->i.mem_peak = mem_peak;
529 }
530}
531
532void RE_engine_report(RenderEngine *engine, int type, const char *msg)
533{
534 Render *re = engine->re;
535
536 if (re) {
537 BKE_report(engine->re->reports, (eReportType)type, msg);
538 }
539 else if (engine->reports) {
540 BKE_report(engine->reports, (eReportType)type, msg);
541 }
542}
543
544void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
545{
546 Render *re = engine->re;
547 if (re != nullptr) {
549 if (rr) {
550 if (rr->error != nullptr) {
551 MEM_freeN(rr->error);
552 }
553 rr->error = BLI_strdup(msg);
554 }
556 }
557}
558
559RenderPass *RE_engine_pass_by_index_get(RenderEngine *engine, const char *layer_name, int index)
560{
561 Render *re = engine->re;
562 if (re == nullptr) {
563 return nullptr;
564 }
565
566 RenderPass *pass = nullptr;
567
569 if (rr != nullptr) {
570 const RenderLayer *layer = RE_GetRenderLayer(rr, layer_name);
571 if (layer != nullptr) {
572 pass = static_cast<RenderPass *>(BLI_findlink(&layer->passes, index));
573 }
574 }
576
577 return pass;
578}
579
581{
582 Render *re = engine->re;
583 return RE_GetActiveRenderView(re);
584}
585
586void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
587{
588 Render *re = engine->re;
589 RE_SetActiveRenderView(re, viewname);
590}
591
592float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, bool use_spherical_stereo)
593{
594 /* When using spherical stereo, get camera shift without multiview,
595 * leaving stereo to be handled by the engine. */
596 Render *re = engine->re;
597 if (use_spherical_stereo || re == nullptr) {
598 return BKE_camera_multiview_shift_x(nullptr, camera, nullptr);
599 }
600
601 return BKE_camera_multiview_shift_x(&re->r, camera, re->viewname);
602}
603
605 Object *camera,
606 bool use_spherical_stereo,
607 float r_modelmat[16])
608{
609 /* When using spherical stereo, get model matrix without multiview,
610 * leaving stereo to be handled by the engine. */
611 Render *re = engine->re;
612 if (use_spherical_stereo || re == nullptr) {
613 BKE_camera_multiview_model_matrix(nullptr, camera, nullptr, (float(*)[4])r_modelmat);
614 }
615 else {
616 BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, (float(*)[4])r_modelmat);
617 }
618}
619
621{
622 Render *re = engine->re;
623 return BKE_camera_multiview_spherical_stereo(re ? &re->r : nullptr, camera) ? true : false;
624}
625
626const rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles)
627{
629 if (!tiles_highlight) {
630 *r_total_tiles = 0;
631 return nullptr;
632 };
633
634 blender::Span<rcti> highlighted_tiles = tiles_highlight->get_all_highlighted_tiles();
635
636 *r_total_tiles = highlighted_tiles.size();
637 return highlighted_tiles.data();
638}
639
641{
642 return &re->r;
643}
644
646{
647 /* Re-rendering is not supported with GPU contexts, since the GPU context
648 * is destroyed when the render thread exists. */
649 return (engine->re->r.mode & R_PERSISTENT_DATA) && !(engine->type->flag & RE_USE_GPU_CONTEXT);
650}
651
653{
654 /* For persistent data or GPU engines like Eevee, reuse the depsgraph between
655 * view layers and animation frames. For renderers like Cycles that create
656 * their own copy of the scene, persistent data must be explicitly enabled to
657 * keep memory usage low by default. */
658 return (engine->re->r.mode & R_PERSISTENT_DATA) || (engine->type->flag & RE_USE_GPU_CONTEXT);
659}
660
661/* Depsgraph */
662static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
663{
664 Main *bmain = engine->re->main;
665 Scene *scene = engine->re->scene;
666 bool reuse_depsgraph = false;
667
668 /* Reuse depsgraph from persistent data if possible. */
669 if (engine->depsgraph) {
670 if (DEG_get_bmain(engine->depsgraph) != bmain ||
671 DEG_get_input_scene(engine->depsgraph) != scene)
672 {
673 /* If bmain or scene changes, we need a completely new graph. */
674 engine_depsgraph_free(engine);
675 }
676 else if (DEG_get_input_view_layer(engine->depsgraph) != view_layer) {
677 /* If only view layer changed, reuse depsgraph in the hope of reusing
678 * objects shared between view layers. */
679 DEG_graph_replace_owners(engine->depsgraph, bmain, scene, view_layer);
681 }
682
683 reuse_depsgraph = true;
684 }
685
686 if (!engine->depsgraph) {
687 /* Ensure we only use persistent data for one scene / view layer at a time,
688 * to avoid excessive memory usage. */
689 RE_FreePersistentData(nullptr);
690
691 /* Create new depsgraph if not cached with persistent data. */
692 engine->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
693 DEG_debug_name_set(engine->depsgraph, "RENDER");
694 }
695
696 if (engine->re->r.scemode & R_BUTS_PREVIEW) {
697 /* Update for preview render. */
698 Depsgraph *depsgraph = engine->depsgraph;
700
701 /* Need GPU context since this might free GPU buffers. */
702 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT) && reuse_depsgraph;
703 if (use_gpu_context) {
705 }
706
708
709 if (use_gpu_context) {
711 }
712 }
713 else {
714 /* Go through update with full Python callbacks for regular render. */
716 }
717
719}
720
722{
723 if (engine->depsgraph) {
724 if (engine_keep_depsgraph(engine)) {
725 /* Clear recalc flags since the engine should have handled the updates for the currently
726 * rendered framed by now. */
727 DEG_ids_clear_recalc(engine->depsgraph, false);
728 }
729 else {
730 /* Free immediately to save memory. */
731 engine_depsgraph_free(engine);
732 }
733 }
734}
735
736void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
737{
738 if (!engine->depsgraph) {
739 return;
740 }
741
742 /* Clear recalc flags before update so engine can detect what changed. */
743 DEG_ids_clear_recalc(engine->depsgraph, false);
744
745 Render *re = engine->re;
746 double cfra = double(frame) + double(subframe);
747
748 CLAMP(cfra, MINAFRAME, MAXFRAME);
749 BKE_scene_frame_set(re->scene, cfra);
751
753}
754
755/* Bake */
756
758{
759 re->scene = scene;
760 re->main = bmain;
761 render_copy_renderdata(&re->r, &scene->r);
762}
763
765{
766 const RenderEngineType *type = RE_engines_find(re->r.engine);
767 return (type->bake != nullptr);
768}
769
771 Depsgraph *depsgraph,
772 Object *object,
773 const int object_id,
774 const BakePixel pixel_array[],
775 const BakeTargets *targets,
776 const eScenePassType pass_type,
777 const int pass_filter,
778 float result[])
779{
781 RenderEngine *engine;
782
783 /* set render info */
784 re->i.cfra = re->scene->r.cfra;
785 BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
786
787 /* render */
788 engine = re->engine;
789
790 if (!engine) {
791 engine = RE_engine_create(type);
792 re->engine = engine;
793 }
794
795 engine->flag |= RE_ENGINE_RENDERING;
796
797 /* TODO: actually link to a parent which shouldn't happen */
798 engine->re = re;
799
800 engine->resolution_x = re->winx;
801 engine->resolution_y = re->winy;
802
803 if (type->bake) {
804 engine->depsgraph = depsgraph;
805
806 /* update is only called so we create the engine.session */
807 if (type->update) {
808 type->update(engine, re->main, engine->depsgraph);
809 }
810
811 /* Bake all images. */
812 engine->bake.targets = targets;
813 engine->bake.pixels = pixel_array;
814 engine->bake.result = result;
815 engine->bake.object_id = object_id;
816
817 for (int i = 0; i < targets->images_num; i++) {
818 const BakeImage *image = &targets->images[i];
819 engine->bake.image_id = i;
820
821 type->bake(
822 engine, engine->depsgraph, object, pass_type, pass_filter, image->width, image->height);
823 }
824
825 /* Optionally let render images read bake images from disk delayed. */
826 if (type->render_frame_finish) {
827 engine->bake.image_id = 0;
828 type->render_frame_finish(engine);
829 }
830
831 memset(&engine->bake, 0, sizeof(engine->bake));
832
833 engine->depsgraph = nullptr;
834 }
835
836 engine->flag &= ~RE_ENGINE_RENDERING;
837
838 engine_depsgraph_free(engine);
839
840 RE_engine_free(engine);
841 re->engine = nullptr;
842
844 G.is_break = true;
845 }
846
847 return true;
848}
849
850/* Render */
851
853 RenderEngine *engine,
854 ViewLayer *view_layer_iter,
855 const bool use_engine,
856 const bool use_grease_pencil)
857{
858 /* Lock UI so scene can't be edited while we read from it in this render thread. */
859 re->draw_lock();
860
861 /* Create depsgraph with scene evaluated at render resolution. */
862 ViewLayer *view_layer = static_cast<ViewLayer *>(
863 BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name)));
864 if (!re->prepare_viewlayer(view_layer, engine->depsgraph)) {
865 re->draw_unlock();
866 return;
867 }
868 engine_depsgraph_init(engine, view_layer);
869
870 /* Sync data to engine, within draw lock so scene data can be accessed safely. */
871 if (use_engine) {
872 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
873 if (use_gpu_context) {
875 }
876 else if (engine->has_grease_pencil && use_grease_pencil && G.background) {
877 /* Workaround for specific NVidia drivers which crash on Linux when OptiX context is
878 * initialized prior to OpenGL context. This affects driver versions 545.29.06, 550.54.14,
879 * and 550.67 running on kernel 6.8.
880 *
881 * The idea here is to initialize GPU context before giving control to the render engine in
882 * cases when we know that the GPU context will definitely be needed later on.
883 *
884 * Only do it for background renders to avoid possible extra global locking during the
885 * context initialization. For the non-background renders the GPU context is already
886 * initialized for the Blender interface and no workaround is needed.
887 *
888 * Technically it is enough to only call WM_init_gpu() here, but it expects to only be called
889 * once, and from here it is not possible to know whether GPU sub-system is initialized or
890 * not. So instead temporarily enable the render context, which will take care of the GPU
891 * context initialization.
892 *
893 * For demo file and tracking progress of possible fixes on driver side refer to #120007. */
896 }
897
898 if (engine->type->update) {
899 engine->type->update(engine, re->main, engine->depsgraph);
900 }
901 if (use_gpu_context) {
903 }
904 }
905
906 re->draw_unlock();
907
908 /* Perform render with engine. */
909 if (use_engine) {
910 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
911 if (use_gpu_context) {
913 }
914
918
919 engine->type->render(engine, engine->depsgraph);
920
922 re->engine->flag &= ~RE_ENGINE_CAN_DRAW;
924
925 if (use_gpu_context) {
927 }
928 }
929
930 /* Optionally composite grease pencil over render result.
931 * Only do it if the passes are allocated (and the engine will not override the grease pencil
932 * when reading its result from EXR file and writing to the Blender side. */
933 if (engine->has_grease_pencil && use_grease_pencil && re->result->passes_allocated) {
934 /* NOTE: External engine might have been requested to free its
935 * dependency graph, which is only allowed if there is no grease
936 * pencil (pipeline is taking care of that). */
937 if (!RE_engine_test_break(engine) && engine->depsgraph != nullptr) {
938 DRW_render_gpencil(engine, engine->depsgraph);
939 }
940 }
941
942 /* Free dependency graph, if engine has not done it already. */
943 engine_depsgraph_exit(engine);
944}
945
946/* Callback function for engine_render_create_result to add all render passes to the result. */
947static void engine_render_add_result_pass_cb(void *user_data,
948 Scene * /*scene*/,
949 ViewLayer *view_layer,
950 const char *name,
951 int channels,
952 const char *chanid,
953 eNodeSocketDatatype /*type*/)
954{
955 RenderResult *rr = (RenderResult *)user_data;
956 RE_create_render_pass(rr, name, channels, chanid, view_layer->name, RR_ALL_VIEWS, false);
957}
958
960{
962 if (rr == nullptr) {
963 return nullptr;
964 }
965
966 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
968 re->engine, re->scene, view_layer, engine_render_add_result_pass_cb, rr);
969 }
971
972 /* Preview does not support deferred render result allocation. */
973 if (re->r.scemode & R_BUTS_PREVIEW) {
975 }
976
977 return rr;
978}
979
980bool RE_engine_render(Render *re, bool do_all)
981{
983
984 /* verify if we can render */
985 if (!type->render) {
986 return false;
987 }
988 if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW)) {
989 return false;
990 }
991 if (do_all && !(type->flag & RE_USE_POSTPROCESS)) {
992 return false;
993 }
994 if (!do_all && (type->flag & RE_USE_POSTPROCESS)) {
995 return false;
996 }
997
998 /* Lock drawing in UI during data phase. */
999 re->draw_lock();
1000
1001 if ((type->flag & RE_USE_GPU_CONTEXT) && !GPU_backend_supported()) {
1002 /* Clear UI drawing locks. */
1003 re->draw_unlock();
1004 BKE_report(re->reports, RPT_ERROR, "Cannot initialize the GPU");
1005 G.is_break = true;
1006 return true;
1007 }
1008
1009 /* Create engine. */
1010 RenderEngine *engine = re->engine;
1011
1012 if (!engine) {
1013 engine = RE_engine_create(type);
1014 re->engine = engine;
1015 }
1016
1017 /* Create render result. Do this before acquiring lock, to avoid lock
1018 * inversion as this calls python to get the render passes, while python UI
1019 * code can also hold a lock on the render result. */
1020 const bool create_new_result = (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW));
1021 RenderResult *new_result = (create_new_result) ? engine_render_create_result(re) : nullptr;
1022
1024 if (create_new_result) {
1025 if (re->result) {
1027 }
1028
1029 re->result = new_result;
1030 }
1032
1033 if (re->result == nullptr) {
1034 /* Clear UI drawing locks. */
1035 re->draw_unlock();
1036 /* Free engine. */
1037 RE_engine_free(engine);
1038 re->engine = nullptr;
1039 /* Too small image is handled earlier, here it could only happen if
1040 * there was no sufficient memory to allocate all passes.
1041 */
1042 BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
1043 G.is_break = true;
1044 return true;
1045 }
1046
1047 /* set render info */
1048 re->i.cfra = re->scene->r.cfra;
1049 STRNCPY(re->i.scene_name, re->scene->id.name + 2);
1050
1051 engine->flag |= RE_ENGINE_RENDERING;
1052
1053 /* TODO: actually link to a parent which shouldn't happen */
1054 engine->re = re;
1055
1056 if (re->flag & R_ANIMATION) {
1057 engine->flag |= RE_ENGINE_ANIMATION;
1058 }
1059 if (re->r.scemode & R_BUTS_PREVIEW) {
1060 engine->flag |= RE_ENGINE_PREVIEW;
1061 }
1062 engine->camera_override = re->camera_override;
1063
1064 engine->resolution_x = re->winx;
1065 engine->resolution_y = re->winy;
1066
1067 /* Clear UI drawing locks. */
1068 re->draw_unlock();
1069
1070 /* Render view layers. */
1071 bool delay_grease_pencil = false;
1072
1073 if (type->render) {
1074 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) {
1075 engine_render_view_layer(re, engine, view_layer_iter, true, true);
1076
1077 /* If render passes are not allocated the render engine deferred final pixels write for
1078 * later. Need to defer the grease pencil for until after the engine has written the
1079 * render result to Blender. */
1080 delay_grease_pencil = engine->has_grease_pencil && !re->result->passes_allocated;
1081
1082 if (RE_engine_test_break(engine)) {
1083 break;
1084 }
1085 }
1087 }
1088
1089 if (type->render_frame_finish) {
1090 type->render_frame_finish(engine);
1091 }
1092
1093 /* Perform delayed grease pencil rendering. */
1094 if (delay_grease_pencil) {
1095 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) {
1096 engine_render_view_layer(re, engine, view_layer_iter, false, true);
1097 if (RE_engine_test_break(engine)) {
1098 break;
1099 }
1100 }
1102 }
1103
1104 /* Clear tile data */
1105 engine->flag &= ~RE_ENGINE_RENDERING;
1106
1108 static_cast<RenderResult *>(engine->fullresult.first));
1109
1110 /* re->engine becomes zero if user changed active render engine during render */
1111 if (!engine_keep_depsgraph(engine) || !re->engine) {
1112 engine_depsgraph_free(engine);
1113
1114 RE_engine_free(engine);
1115 re->engine = nullptr;
1116 }
1117
1118 if (re->r.scemode & R_EXR_CACHE_FILE) {
1122 }
1123
1125 G.is_break = true;
1126 }
1127
1128#ifdef WITH_FREESTYLE
1129 if (re->r.mode & R_EDGE_FRS) {
1130 RE_RenderFreestyleExternal(re);
1131 }
1132#endif
1133
1134 return true;
1135}
1136
1138 Scene *scene,
1139 ViewLayer *view_layer,
1141 void *callback_data)
1142{
1143 if (!(scene && view_layer && engine && callback && engine->type->update_render_passes)) {
1144 return;
1145 }
1146
1148
1150 engine->update_render_passes_data = callback_data;
1151 engine->type->update_render_passes(engine, scene, view_layer);
1152 engine->update_render_passes_cb = nullptr;
1153 engine->update_render_passes_data = nullptr;
1154
1156}
1157
1159 Scene *scene,
1160 ViewLayer *view_layer,
1161 const char *name,
1162 int channels,
1163 const char *chanid,
1165{
1166 if (!(scene && view_layer && engine && engine->update_render_passes_cb)) {
1167 return;
1168 }
1169
1171 engine->update_render_passes_data, scene, view_layer, name, channels, chanid, type);
1172}
1173
1175{
1176 /* Weak way to save memory, but not crash grease pencil.
1177 *
1178 * TODO(sergey): Find better solution for this.
1179 */
1180 if (engine->has_grease_pencil || engine_keep_depsgraph(engine)) {
1181 return;
1182 }
1183 engine_depsgraph_free(engine);
1184}
1185
1187{
1188 return re->engine;
1189}
1190
1192{
1193 return view_render->engine;
1194}
1195
1197{
1198 RenderEngine *engine = re->engine;
1199
1200 if (!engine) {
1201 /* No engine-side drawing if the engine does not exist. */
1202 return false;
1203 }
1204
1205 if (!engine->type->draw) {
1206 /* Required callbacks are not implemented on the engine side. */
1207 return false;
1208 }
1209
1210 /* Lock before checking the flag, to avoid possible conflicts with the render thread. */
1212
1213 if ((engine->flag & RE_ENGINE_CAN_DRAW) == 0) {
1214 /* The rendering is not started yet, or has finished.
1215 *
1216 * In the former case there will nothing to be drawn, so can simply use RenderResult drawing
1217 * pipeline. In the latter case the engine has destroyed its display-only resources (textures,
1218 * graphics interops, etc..) so need to use the #RenderResult drawing pipeline. */
1220 return false;
1221 }
1222
1223 return true;
1224}
1225
1230
1232 RenderEngine *engine, int x, int y, int width, int height, bool highlight)
1233{
1234 if (!engine->re) {
1235 /* No render on the engine, so nowhere to store the highlighted tiles information. */
1236 return;
1237 }
1238 if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
1239 /* Engine reported it does not support tiles highlight, but attempted to set the highlight.
1240 * Technically it is a logic error, but there is no good way to inform an external engine about
1241 * it. */
1242 return;
1243 }
1244
1245 blender::render::TilesHighlight *tile_highlight = engine->re->get_tile_highlight();
1246 if (!tile_highlight) {
1247 /* The renderer itself does not support tiles highlight. */
1248 return;
1249 }
1250
1251 if (highlight) {
1252 tile_highlight->highlight_tile(x, y, width, height);
1253 }
1254 else {
1255 tile_highlight->unhighlight_tile(x, y, width, height);
1256 }
1257}
1258
1260{
1261 if (!engine->re) {
1262 /* No render on the engine, so nowhere to store the highlighted tiles information. */
1263 return;
1264 }
1265 if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
1266 /* Engine reported it does not support tiles highlight, but attempted to set the highlight.
1267 * Technically it is a logic error, but there is no good way to inform an external engine about
1268 * it. */
1269 return;
1270 }
1271
1272 blender::render::TilesHighlight *tile_highlight = engine->re->get_tile_highlight();
1273 if (!tile_highlight) {
1274 /* The renderer itself does not support tiles highlight. */
1275 return;
1276 }
1277
1278 tile_highlight->clear();
1279}
1280
1281/* -------------------------------------------------------------------- */
1291{
1292 /* If the there already is a draw manager render context available, reuse it. */
1293 engine->use_drw_render_context = (engine->re && RE_system_gpu_context_get(engine->re));
1294 if (engine->use_drw_render_context) {
1295 return true;
1296 }
1297
1298 /* Viewport render case where no render context is available. We are expected to be on
1299 * the main thread here to safely create a context. */
1301
1302 const bool drw_state = DRW_gpu_context_release();
1304
1305 if (engine->system_gpu_context) {
1306 /* Activate new GPU Context for GPUContext creation. */
1308 /* Requires GPUContext for usage of GPU Module for displaying results. */
1309 engine->blender_gpu_context = GPU_context_create(nullptr, engine->system_gpu_context);
1310 GPU_context_active_set(nullptr);
1311 /* Deactivate newly created GPU Context, as it is not needed until
1312 * `RE_engine_gpu_context_enable` is called. */
1314 }
1315 else {
1316 engine->blender_gpu_context = nullptr;
1317 }
1318
1319 DRW_gpu_context_activate(drw_state);
1320
1321 return engine->system_gpu_context != nullptr;
1322}
1323
1325{
1326 if (!engine->system_gpu_context) {
1327 return;
1328 }
1329
1330 const bool drw_state = DRW_gpu_context_release();
1331
1333 if (engine->blender_gpu_context) {
1334 GPUContext *restore_context = GPU_context_active_get();
1337 if (restore_context != engine->blender_gpu_context) {
1338 GPU_context_active_set(restore_context);
1339 }
1340 engine->blender_gpu_context = nullptr;
1341 }
1343 engine->system_gpu_context = nullptr;
1344
1345 DRW_gpu_context_activate(drw_state);
1346}
1347
1349{
1350 engine->gpu_restore_context = false;
1351 if (engine->use_drw_render_context) {
1353 return true;
1354 }
1355 if (engine->system_gpu_context) {
1357 /* If a previous GPU/GPUContext was active (DST.blender_gpu_context), we should later
1358 * restore this when disabling the RenderEngine context. */
1360
1361 /* Activate RenderEngine System and Blender GPU Context. */
1363 if (engine->blender_gpu_context) {
1366 }
1367 return true;
1368 }
1369 return false;
1370}
1371
1373{
1374 if (engine->use_drw_render_context) {
1376 }
1377 else {
1378 if (engine->system_gpu_context) {
1379 if (engine->blender_gpu_context) {
1380 GPU_context_active_set(nullptr);
1382 }
1384 /* Restore DRW state context if previously active. */
1387 }
1388 }
1389}
1390
1392{
1393 if (engine->use_drw_render_context) {
1394 /* Locking already handled by the draw manager. */
1395 }
1396 else {
1397 if (engine->system_gpu_context) {
1399 }
1400 }
1401}
1402
1404{
1405 if (engine->use_drw_render_context) {
1406 /* Locking already handled by the draw manager. */
1407 }
1408 else {
1409 if (engine->system_gpu_context) {
1411 }
1412 }
1413}
1414
Camera data-block and utility functions.
float BKE_camera_multiview_shift_x(const struct RenderData *rd, const struct Object *camera, const char *viewname)
void BKE_camera_multiview_model_matrix(const struct RenderData *rd, const struct Object *camera, const char *viewname, float r_modelmat[4][4])
bool BKE_camera_multiview_spherical_stereo(const struct RenderData *rd, const struct Object *camera)
bool BKE_reports_contain(ReportList *reports, eReportType level)
Definition report.cc:342
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
bool BKE_scene_uses_cycles(const Scene *scene)
Definition scene.cc:2782
void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, bool clear_recalc)
Definition scene.cc:2578
void BKE_scene_frame_set(Scene *scene, float frame)
Definition scene.cc:2336
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2213
bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
Definition scene.cc:2798
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2331
#define BLI_assert(a)
Definition BLI_assert.h:50
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:110
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:130
MINLINE float int_as_float(int i)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.c:40
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
void BLI_mutex_end(ThreadMutex *mutex)
Definition threads.cc:360
void BLI_mutex_init(ThreadMutex *mutex)
Definition threads.cc:340
#define THREAD_LOCK_WRITE
void BLI_rw_mutex_lock(ThreadRWMutex *mutex, int mode)
Definition threads.cc:467
int BLI_thread_is_main(void)
Definition threads.cc:179
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
void BLI_rw_mutex_unlock(ThreadRWMutex *mutex)
Definition threads.cc:477
#define CLAMP(a, b, c)
#define STREQ(a, b)
void BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr)
typedef double(DMatrix)[4][4]
void DEG_ids_clear_recalc(Depsgraph *depsgraph, bool backup)
@ DAG_EVAL_RENDER
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:273
void DEG_graph_replace_owners(Depsgraph *depsgraph, Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition depsgraph.cc:280
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:301
void DEG_evaluate_on_framechange(Depsgraph *graph, float frame, DepsgraphEvaluateSyncWriteback sync_writeback=DEG_EVALUATE_SYNC_WRITEBACK_NO)
void DEG_graph_tag_relations_update(Depsgraph *graph)
void DEG_graph_relations_update(Depsgraph *graph)
void DEG_debug_name_set(Depsgraph *depsgraph, const char *name)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Main * DEG_get_bmain(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
eNodeSocketDatatype
Object is a sort of wrapper for general info.
#define RE_PASSNAME_COMBINED
@ R_EXR_CACHE_FILE
@ R_BUTS_PREVIEW
#define MINAFRAME
@ R_PERSISTENT_DATA
@ R_EDGE_FRS
eScenePassType
#define MAXFRAME
bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
void DRW_gpu_context_disable()
void DRW_gpu_context_enable()
void DRW_engines_free()
void DRW_gpu_context_activate(bool drw_state)
void DRW_render_context_disable(Render *render)
void DRW_engine_register(DrawEngineType *draw_engine_type)
void DRW_render_gpencil(RenderEngine *engine, Depsgraph *depsgraph)
bool DRW_gpu_context_release()
void DRW_engines_register()
void DRW_render_context_enable(Render *render)
void GPU_render_end()
GPUContext * GPU_context_create(void *ghost_window, void *ghost_context)
bool GPU_backend_supported()
void GPU_render_begin()
GPUContext * GPU_context_active_get()
void GPU_context_discard(GPUContext *)
void GPU_context_active_set(GPUContext *)
Contains defines and structs used throughout the imbuf module.
Read Guarded memory(de)allocation.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between camera
@ RE_INTERNAL
Definition RE_engine.h:47
@ RE_USE_PREVIEW
Definition RE_engine.h:48
@ RE_USE_ALEMBIC_PROCEDURAL
Definition RE_engine.h:57
@ RE_USE_POSTPROCESS
Definition RE_engine.h:49
@ RE_USE_GPU_CONTEXT
Definition RE_engine.h:54
void(* update_render_passes_cb_t)(void *userdata, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int channels, const char *chanid, eNodeSocketDatatype type)
Definition RE_engine.h:125
@ RE_ENGINE_PREVIEW
Definition RE_engine.h:64
@ RE_ENGINE_HIGHLIGHT_TILES
Definition RE_engine.h:68
@ RE_ENGINE_RENDERING
Definition RE_engine.h:67
@ RE_ENGINE_CAN_DRAW
Definition RE_engine.h:69
@ RE_ENGINE_ANIMATION
Definition RE_engine.h:63
struct GPUContext GPUContext
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
static unsigned long seed
Definition btSoftBody.h:39
constexpr const T * data() const
Definition BLI_span.hh:216
constexpr int64_t size() const
Definition BLI_span.hh:253
void highlight_tile_for_result(const RenderResult *result)
void unhighlight_tile(int x, int y, int width, int height)
void unhighlight_tile_for_result(const RenderResult *result)
Span< rcti > get_all_highlighted_tiles() const
void highlight_tile(int x, int y, int width, int height)
const Depsgraph * depsgraph
DEGForeachIDComponentCallback callback
#define offsetof(t, d)
draw_view in_light_buf[] float
static void re_ensure_passes_allocated_thread_safe(Render *re)
void RE_engine_draw_release(Render *re)
bool RE_engine_is_external(const Render *re)
const char * RE_engine_active_view_get(RenderEngine *engine)
RenderEngine * RE_view_engine_get(const ViewRender *view_render)
static RenderResult * render_result_from_bake(RenderEngine *engine, int x, int y, int w, int h, const char *layername)
bool RE_bake_engine(Render *re, Depsgraph *depsgraph, Object *object, const int object_id, const BakePixel pixel_array[], const BakeTargets *targets, const eScenePassType pass_type, const int pass_filter, float result[])
void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
bool RE_engine_supports_alembic_procedural(const RenderEngineType *render_type, Scene *scene)
RenderResult * RE_engine_begin_result(RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
RenderResult * RE_engine_get_result(RenderEngine *engine)
static void engine_depsgraph_exit(RenderEngine *engine)
void RE_engine_add_pass(RenderEngine *engine, const char *name, int channels, const char *chan_id, const char *layername)
static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
void RE_engine_report(RenderEngine *engine, int type, const char *msg)
bool RE_bake_has_engine(const Render *re)
void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
bool RE_engine_use_persistent_data(RenderEngine *engine)
float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, bool use_spherical_stereo)
void RE_engine_update_result(RenderEngine *engine, RenderResult *result)
static void engine_render_view_layer(Render *re, RenderEngine *engine, ViewLayer *view_layer_iter, const bool use_engine, const bool use_grease_pencil)
void RE_engines_exit()
const rcti * RE_engine_get_current_tiles(Render *re, int *r_total_tiles)
void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
void RE_engine_update_render_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer, update_render_passes_cb_t callback, void *callback_data)
RenderEngine * RE_engine_get(const Render *re)
RenderPass * RE_engine_pass_by_index_get(RenderEngine *engine, const char *layer_name, int index)
RenderEngineType * RE_engines_find(const char *idname)
void RE_engine_tile_highlight_set(RenderEngine *engine, int x, int y, int width, int height, bool highlight)
bool RE_engine_draw_acquire(Render *re)
bool RE_engine_get_spherical_stereo(RenderEngine *engine, Object *camera)
RenderEngine * RE_engine_create(RenderEngineType *type)
bool RE_engine_render(Render *re, bool do_all)
bool RE_engine_test_break(RenderEngine *engine)
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
void RE_bake_engine_set_engine_parameters(Render *re, Main *bmain, Scene *scene)
void RE_engine_gpu_context_lock(RenderEngine *engine)
void RE_engine_gpu_context_unlock(RenderEngine *engine)
static void engine_depsgraph_free(RenderEngine *engine)
static RenderResult * engine_render_create_result(Render *re)
void RE_engines_register(RenderEngineType *render_type)
static void engine_render_add_result_pass_cb(void *user_data, Scene *, ViewLayer *view_layer, const char *name, int channels, const char *chanid, eNodeSocketDatatype)
void RE_engine_free(RenderEngine *engine)
RenderData * RE_engine_get_render_data(Render *re)
void RE_engine_free_blender_memory(RenderEngine *engine)
void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
void RE_engine_register_pass(RenderEngine *engine, Scene *scene, ViewLayer *view_layer, const char *name, int channels, const char *chanid, eNodeSocketDatatype type)
void RE_engine_end_result(RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
ListBase R_engines
void RE_engine_tile_highlight_clear_all(RenderEngine *engine)
static bool engine_keep_depsgraph(RenderEngine *engine)
void RE_engine_gpu_context_destroy(RenderEngine *engine)
static void render_result_to_bake(RenderEngine *engine, RenderResult *rr)
bool RE_engine_gpu_context_enable(RenderEngine *engine)
bool RE_engine_gpu_context_create(RenderEngine *engine)
void RE_engines_init()
void RE_engine_get_camera_model_matrix(RenderEngine *engine, Object *camera, bool use_spherical_stereo, float r_modelmat[16])
void RE_engine_update_progress(RenderEngine *engine, float progress)
void RE_engine_gpu_context_disable(RenderEngine *engine)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
static ulong * next
#define G(x, y, z)
void render_result_exr_file_cache_write(Render *re)
void render_result_merge(RenderResult *rr, RenderResult *rrpart)
RenderPass * render_layer_add_pass(RenderResult *rr, RenderLayer *rl, int channels, const char *name, const char *viewname, const char *chan_id, const bool allocate)
void render_result_passes_allocated_ensure(RenderResult *rr)
void render_result_free(RenderResult *rr)
void render_result_clone_passes(Render *re, RenderResult *rr, const char *viewname)
void render_result_free_list(ListBase *lb, RenderResult *rr)
RenderResult * render_result_new(Render *re, const rcti *partrct, const char *layername, const char *viewname)
void RE_create_render_pass(RenderResult *rr, const char *name, int channels, const char *chan_id, const char *layername, const char *viewname, const bool allocate)
#define FOREACH_VIEW_LAYER_TO_RENDER_END
#define RR_ALL_VIEWS
#define RR_ALL_LAYERS
#define FOREACH_VIEW_LAYER_TO_RENDER_BEGIN(re_, iter_)
#define R_ANIMATION
void * RE_system_gpu_context_get(Render *re)
RenderPass * RE_pass_find_by_name(RenderLayer *rl, const char *name, const char *viewname)
void render_copy_renderdata(RenderData *to, RenderData *from)
void RE_FreePersistentData(const Scene *scene)
RenderResult * RE_AcquireResultRead(Render *re)
RenderLayer * RE_GetRenderLayer(RenderResult *rr, const char *name)
void RE_ReleaseResult(Render *re)
const char * RE_GetActiveRenderView(Render *re)
void RE_SetActiveRenderView(Render *re, const char *viewname)
char render_layer_name[RE_MAXNAME]
Definition RE_bake.h:31
float dv_dx
Definition RE_bake.h:57
float du_dx
Definition RE_bake.h:56
int seed
Definition RE_bake.h:54
float du_dy
Definition RE_bake.h:56
float uv[2]
Definition RE_bake.h:55
float dv_dy
Definition RE_bake.h:57
int object_id
Definition RE_bake.h:53
int primitive_id
Definition RE_bake.h:53
int channels_num
Definition RE_bake.h:46
int images_num
Definition RE_bake.h:37
BakeImage * images
Definition RE_bake.h:36
ThreadMutex engine_draw_mutex
struct RenderEngine * engine
ThreadRWMutex resultmutex
RenderResult * result
char name[66]
Definition DNA_ID.h:425
ImBufFloatBuffer float_buffer
void * first
char engine[32]
void(* render)(struct RenderEngine *engine, struct Depsgraph *depsgraph)
Definition RE_engine.h:84
void(* update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph)
Definition RE_engine.h:82
struct DrawEngineType * draw_engine
Definition RE_engine.h:119
void(* draw)(struct RenderEngine *engine, const struct bContext *context, struct Depsgraph *depsgraph)
Definition RE_engine.h:93
void(* update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer)
Definition RE_engine.h:115
struct ReportList * reports
Definition RE_engine.h:147
struct Depsgraph * depsgraph
Definition RE_engine.h:158
RenderEngineType * type
Definition RE_engine.h:134
struct RenderEngine::@1361 bake
const struct BakePixel * pixels
Definition RE_engine.h:151
ThreadMutex blender_gpu_context_mutex
Definition RE_engine.h:168
float * result
Definition RE_engine.h:152
char text[512]
Definition RE_engine.h:143
bool has_grease_pencil
Definition RE_engine.h:159
bool use_drw_render_context
Definition RE_engine.h:169
struct Render * re
Definition RE_engine.h:141
struct GPUContext * blender_gpu_context
Definition RE_engine.h:170
void * update_render_passes_data
Definition RE_engine.h:164
ListBase fullresult
Definition RE_engine.h:142
void * py_instance
Definition RE_engine.h:135
void * system_gpu_context
Definition RE_engine.h:167
update_render_passes_cb_t update_render_passes_cb
Definition RE_engine.h:163
bool gpu_restore_context
Definition RE_engine.h:172
ThreadMutex update_render_passes_mutex
Definition RE_engine.h:162
const struct BakeTargets * targets
Definition RE_engine.h:150
struct Object * camera_override
Definition RE_engine.h:138
char name[RE_MAXNAME]
Definition RE_pipeline.h:89
struct ImBuf * ibuf
Definition RE_pipeline.h:68
ListBase layers
bool passes_allocated
const char * statstr
char scene_name[MAX_ID_NAME - 2]
const char * infostr
void draw_unlock() override
void draw_lock() override
void display_update(RenderResult *render_result, rcti *rect) override
bool test_break() override
RenderData r
struct Main * main
bool prepare_viewlayer(struct ViewLayer *view_layer, struct Depsgraph *depsgraph) override
Scene * scene
blender::render::TilesHighlight * get_tile_highlight() override
void progress(float progress) override
short flag
char viewname[MAX_NAME]
RenderStats i
struct ReportList * reports
rcti disprect
struct Object * camera_override
void stats_draw(RenderStats *render_stats) override
struct RenderData r
ListBase view_layers
char name[64]
int ymin
int ymax
int xmin
int xmax
void * WM_system_gpu_context_create()
void WM_system_gpu_context_dispose(void *context)
void WM_system_gpu_context_activate(void *context)
void WM_system_gpu_context_release(void *context)