Blender V4.5
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
8
9#include <cstddef>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "BLI_listbase.h"
16#include "BLI_math_bits.h"
17#include "BLI_string.h"
18#include "BLI_utildefines.h"
19
20#include "DNA_object_types.h"
21
22#include "BKE_camera.h"
23#include "BKE_global.hh"
24#include "BKE_node.hh"
25#include "BKE_report.hh"
26#include "BKE_scene.hh"
27
28#include "DEG_depsgraph.hh"
31
32#include "GPU_context.hh"
33
34#ifdef WITH_PYTHON
35# include "BPY_extern.hh"
36#endif
37
38#include "IMB_imbuf_types.hh"
39
40#include "RE_bake.h"
41#include "RE_engine.h"
42#include "RE_pipeline.h"
43
44#include "DRW_engine.hh"
45
46#include "WM_api.hh"
47
48#include "pipeline.hh"
49#include "render_result.h"
50#include "render_types.h"
51
52/* Render Engine Types */
53
54ListBase R_engines = {nullptr, nullptr};
55
61
63{
64 RenderEngineType *type, *next;
65
67 /* Clean resources if the DRW context exists.
68 * We need a context bound even when dealing with non context dependent GPU resources,
69 * since GL functions may be null otherwise (See #141233). */
73 }
74
75 for (type = static_cast<RenderEngineType *>(R_engines.first); type; type = next) {
76 next = type->next;
77
78 BLI_remlink(&R_engines, type);
79
80 if (!(type->flag & RE_INTERNAL)) {
81 if (type->rna_ext.free) {
82 type->rna_ext.free(type->rna_ext.data);
83 }
84
85 MEM_freeN(type);
86 }
87 }
88}
89
91{
92 BLI_addtail(&R_engines, render_type);
93}
94
96{
97 RenderEngineType *type = static_cast<RenderEngineType *>(
99 if (!type) {
100 type = static_cast<RenderEngineType *>(
101 BLI_findstring(&R_engines, "BLENDER_EEVEE_NEXT", offsetof(RenderEngineType, idname)));
102 }
103
104 return type;
105}
106
108{
109 return (re->engine && re->engine->type && re->engine->type->render);
110}
111
113{
114 if ((render_type->flag & RE_USE_ALEMBIC_PROCEDURAL) == 0) {
115 return false;
116 }
117
119 return false;
120 }
121
122 return true;
123}
124
125/* Create, Free */
126
128{
129 RenderEngine *engine = MEM_callocN<RenderEngine>("RenderEngine");
130 engine->type = type;
131
134
135 return engine;
136}
137
139{
140 if (engine->depsgraph) {
141 /* Need GPU context since this might free GPU buffers. */
142 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
143 if (use_gpu_context) {
144 /* This function can be called on the main thread before RenderEngine is destroyed.
145 * In this case, just bind the main draw context to gather the deleted GPU buffers.
146 * Binding the same GPU context as the render engine is not needed (see #129019). */
147 if (BLI_thread_is_main()) {
149 }
150 else {
152 }
153 }
154
155 DEG_graph_free(engine->depsgraph);
156 engine->depsgraph = nullptr;
157
158 if (use_gpu_context) {
159 if (BLI_thread_is_main()) {
161 }
162 else {
164 }
165 }
166 }
167}
168
170{
171#ifdef WITH_PYTHON
172 if (engine->py_instance) {
174 }
175#endif
176
177 engine_depsgraph_free(engine);
178
181
182 MEM_freeN(engine);
183}
184
185/* Bake Render Results */
186
188 RenderEngine *engine, int x, int y, int w, int h, const char *layername)
189{
190 BakeImage *image = &engine->bake.targets->images[engine->bake.image_id];
191 const BakePixel *pixels = engine->bake.pixels + image->offset;
192 const size_t channels_num = engine->bake.targets->channels_num;
193
194 /* Remember layer name for to match images in render_frame_finish. */
195 if (image->render_layer_name[0] == '\0') {
196 STRNCPY(image->render_layer_name, layername);
197 }
198
199 /* Create render result with specified size. */
201
202 rr->rectx = w;
203 rr->recty = h;
204 rr->tilerect.xmin = x;
205 rr->tilerect.ymin = y;
206 rr->tilerect.xmax = x + w;
207 rr->tilerect.ymax = y + h;
208
209 BKE_scene_ppm_get(&engine->re->r, rr->ppm);
210
211 /* Add single baking render layer. */
212 RenderLayer *rl = MEM_callocN<RenderLayer>("bake render layer");
213 STRNCPY(rl->name, layername);
214 rl->rectx = w;
215 rl->recty = h;
216 BLI_addtail(&rr->layers, rl);
217
218 /* Add render passes. */
219 render_layer_add_pass(rr, rl, channels_num, RE_PASSNAME_COMBINED, "", "RGBA", true);
220
221 RenderPass *primitive_pass = render_layer_add_pass(rr, rl, 3, "BakePrimitive", "", "RGB", true);
222 RenderPass *differential_pass = render_layer_add_pass(
223 rr, rl, 4, "BakeDifferential", "", "RGBA", true);
224
225 /* Per-pixel seeds are only needed for baking to vertex colors, see
226 * bake_targets_populate_pixels_color_attributes for more details. */
227 RenderPass *seed_pass = (image->image == nullptr) ?
228 render_layer_add_pass(rr, rl, 1, "BakeSeed", "", "X", true) :
229 nullptr;
230
231 /* Fill render passes from bake pixel array, to be read by the render engine. */
232 for (int ty = 0; ty < h; ty++) {
233 size_t offset = ty * w;
234 float *primitive = primitive_pass->ibuf->float_buffer.data + 3 * offset;
235 float *seed = (seed_pass != nullptr) ? (seed_pass->ibuf->float_buffer.data + offset) : nullptr;
236 float *differential = differential_pass->ibuf->float_buffer.data + 4 * offset;
237
238 size_t bake_offset = (y + ty) * image->width + x;
239 const BakePixel *bake_pixel = pixels + bake_offset;
240
241 for (int tx = 0; tx < w; tx++) {
242 if (bake_pixel->object_id != engine->bake.object_id) {
243 primitive[0] = int_as_float(-1);
244 primitive[1] = int_as_float(-1);
245 primitive[2] = int_as_float(-1);
246 }
247 else {
248 primitive[0] = bake_pixel->uv[0];
249 primitive[1] = bake_pixel->uv[1];
250 primitive[2] = int_as_float(bake_pixel->primitive_id);
251
252 differential[0] = bake_pixel->du_dx;
253 differential[1] = bake_pixel->du_dy;
254 differential[2] = bake_pixel->dv_dx;
255 differential[3] = bake_pixel->dv_dy;
256 }
257
258 if (seed_pass != nullptr) {
259 *seed = int_as_float(bake_pixel->seed);
260 seed += 1;
261 }
262
263 primitive += 3;
264 differential += 4;
265 bake_pixel++;
266 }
267 }
268
269 return rr;
270}
271
273{
274 RenderLayer *rl = static_cast<RenderLayer *>(rr->layers.first);
276 if (!rpass) {
277 return;
278 }
279
280 /* Find bake image corresponding to layer. */
281 int image_id = 0;
282 for (; image_id < engine->bake.targets->images_num; image_id++) {
283 if (STREQ(engine->bake.targets->images[image_id].render_layer_name, rl->name)) {
284 break;
285 }
286 }
287 if (image_id == engine->bake.targets->images_num) {
288 return;
289 }
290
291 const BakeImage *image = &engine->bake.targets->images[image_id];
292 const BakePixel *pixels = engine->bake.pixels + image->offset;
293 const size_t channels_num = engine->bake.targets->channels_num;
294 const size_t channels_size = channels_num * sizeof(float);
295 float *result = engine->bake.result + image->offset * channels_num;
296
297 /* Copy from tile render result to full image bake result. Just the pixels for the
298 * object currently being baked, to preserve other objects when baking multiple. */
299 const int x = rr->tilerect.xmin;
300 const int y = rr->tilerect.ymin;
301 const int w = rr->tilerect.xmax - rr->tilerect.xmin;
302 const int h = rr->tilerect.ymax - rr->tilerect.ymin;
303
304 for (int ty = 0; ty < h; ty++) {
305 const size_t offset = ty * w;
306 const size_t bake_offset = (y + ty) * image->width + x;
307
308 const float *pass_rect = rpass->ibuf->float_buffer.data + offset * channels_num;
309 const BakePixel *bake_pixel = pixels + bake_offset;
310 float *bake_result = result + bake_offset * channels_num;
311
312 for (int tx = 0; tx < w; tx++) {
313 if (bake_pixel->object_id == engine->bake.object_id) {
314 memcpy(bake_result, pass_rect, channels_size);
315 }
316 pass_rect += channels_num;
317 bake_result += channels_num;
318 bake_pixel++;
319 }
320 }
321}
322
323/* Render Results */
324
326 RenderEngine *engine, int x, int y, int w, int h, const char *layername, const char *viewname)
327{
328 if (engine->bake.targets) {
329 RenderResult *result = render_result_from_bake(engine, x, y, w, h, layername);
330 BLI_addtail(&engine->fullresult, result);
331 return result;
332 }
333
334 Render *re = engine->re;
336 rcti disprect;
337
338 /* ensure the coordinates are within the right limits */
339 CLAMP(x, 0, re->result->rectx);
340 CLAMP(y, 0, re->result->recty);
341 CLAMP(w, 0, re->result->rectx);
342 CLAMP(h, 0, re->result->recty);
343
344 if (x + w > re->result->rectx) {
345 w = re->result->rectx - x;
346 }
347 if (y + h > re->result->recty) {
348 h = re->result->recty - y;
349 }
350
351 /* allocate a render result */
352 disprect.xmin = x;
353 disprect.xmax = x + w;
354 disprect.ymin = y;
355 disprect.ymax = y + h;
356
357 result = render_result_new(re, &disprect, layername, viewname);
358
359 /* TODO: make this thread safe. */
360
361 /* can be nullptr if we CLAMP the width or height to 0 */
362 if (result) {
363 render_result_clone_passes(re, result, viewname);
365
366 BLI_addtail(&engine->fullresult, result);
367
368 result->tilerect.xmin += re->disprect.xmin;
369 result->tilerect.xmax += re->disprect.xmin;
370 result->tilerect.ymin += re->disprect.ymin;
371 result->tilerect.ymax += re->disprect.ymin;
372 }
373
374 return result;
375}
376
387
389{
390 if (engine->bake.targets) {
391 /* No interactive baking updates for now. */
392 return;
393 }
394
395 Render *re = engine->re;
396
397 if (result) {
400 result->renlay = static_cast<RenderLayer *>(
401 result->layers.first); /* weak, draws first layer always */
402 re->display_update(result, nullptr);
403 }
404}
405
407 const char *name,
408 int channels,
409 const char *chan_id,
410 const char *layername)
411{
412 Render *re = engine->re;
413
414 if (!re || !re->result) {
415 return;
416 }
417
418 RE_create_render_pass(re->result, name, channels, chan_id, layername, nullptr, false);
419}
420
422 RenderEngine *engine, RenderResult *result, bool cancel, bool highlight, bool merge_results)
423{
424 Render *re = engine->re;
425
426 if (!result) {
427 return;
428 }
429
430 if (engine->bake.targets) {
431 if (!cancel || merge_results) {
433 }
434 BLI_remlink(&engine->fullresult, result);
436 return;
437 }
438
439 if (re->engine && (re->engine->flag & RE_ENGINE_HIGHLIGHT_TILES)) {
441
442 if (tile_highlight) {
443 if (highlight) {
444 tile_highlight->highlight_tile_for_result(result);
445 }
446 else {
447 tile_highlight->unhighlight_tile_for_result(result);
448 }
449 }
450 }
451
452 if (!cancel || merge_results) {
453 if (!(re->test_break() && (re->r.scemode & R_BUTS_PREVIEW))) {
456 }
457
458 /* draw */
459 if (!re->test_break()) {
460 result->renlay = static_cast<RenderLayer *>(
461 result->layers.first); /* weak, draws first layer always */
462 re->display_update(result, nullptr);
463 }
464 }
465
466 /* free */
467 BLI_remlink(&engine->fullresult, result);
469}
470
472{
473 return engine->re->result;
474}
475
476/* Cancel */
477
479{
480 Render *re = engine->re;
481
482 if (re) {
483 return re->test_break();
484 }
485
486 return false;
487}
488
489/* Statistics */
490
491void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
492{
493 Render *re = engine->re;
494
495 /* stats draw callback */
496 if (re) {
497 re->i.statstr = stats;
498 re->i.infostr = info;
499 re->stats_draw(&re->i);
500 re->i.infostr = nullptr;
501 re->i.statstr = nullptr;
502 }
503
504 /* set engine text */
505 engine->text[0] = '\0';
506
507 if (stats && stats[0] && info && info[0]) {
508 SNPRINTF(engine->text, "%s | %s", stats, info);
509 }
510 else if (info && info[0]) {
511 STRNCPY(engine->text, info);
512 }
513 else if (stats && stats[0]) {
514 STRNCPY(engine->text, stats);
515 }
516}
517
519{
520 Render *re = engine->re;
521
522 if (re) {
523 CLAMP(progress, 0.0f, 1.0f);
524 re->progress(progress);
525 }
526}
527
528void RE_engine_update_memory_stats(RenderEngine *engine, float mem_used, float mem_peak)
529{
530 Render *re = engine->re;
531
532 if (re) {
533 re->i.mem_used = mem_used;
534 re->i.mem_peak = mem_peak;
535 }
536}
537
538void RE_engine_report(RenderEngine *engine, int type, const char *msg)
539{
540 Render *re = engine->re;
541
542 if (re) {
543 BKE_report(engine->re->reports, (eReportType)type, msg);
544 }
545 else if (engine->reports) {
546 BKE_report(engine->reports, (eReportType)type, msg);
547 }
548}
549
550void RE_engine_set_error_message(RenderEngine *engine, const char *msg)
551{
552 Render *re = engine->re;
553 if (re != nullptr) {
555 if (rr) {
556 if (rr->error != nullptr) {
557 MEM_freeN(rr->error);
558 }
559 rr->error = BLI_strdup(msg);
560 }
562 }
563}
564
565RenderPass *RE_engine_pass_by_index_get(RenderEngine *engine, const char *layer_name, int index)
566{
567 Render *re = engine->re;
568 if (re == nullptr) {
569 return nullptr;
570 }
571
572 RenderPass *pass = nullptr;
573
575 if (rr != nullptr) {
576 const RenderLayer *layer = RE_GetRenderLayer(rr, layer_name);
577 if (layer != nullptr) {
578 pass = static_cast<RenderPass *>(BLI_findlink(&layer->passes, index));
579 }
580 }
582
583 return pass;
584}
585
587{
588 Render *re = engine->re;
589 return RE_GetActiveRenderView(re);
590}
591
592void RE_engine_active_view_set(RenderEngine *engine, const char *viewname)
593{
594 Render *re = engine->re;
595 RE_SetActiveRenderView(re, viewname);
596}
597
598float RE_engine_get_camera_shift_x(RenderEngine *engine, Object *camera, bool use_spherical_stereo)
599{
600 /* When using spherical stereo, get camera shift without multiview,
601 * leaving stereo to be handled by the engine. */
602 Render *re = engine->re;
603 if (use_spherical_stereo || re == nullptr) {
604 return BKE_camera_multiview_shift_x(nullptr, camera, nullptr);
605 }
606
607 return BKE_camera_multiview_shift_x(&re->r, camera, re->viewname);
608}
609
611 Object *camera,
612 bool use_spherical_stereo,
613 float r_modelmat[16])
614{
615 /* When using spherical stereo, get model matrix without multiview,
616 * leaving stereo to be handled by the engine. */
617 Render *re = engine->re;
618 if (use_spherical_stereo || re == nullptr) {
619 BKE_camera_multiview_model_matrix(nullptr, camera, nullptr, (float(*)[4])r_modelmat);
620 }
621 else {
622 BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, (float(*)[4])r_modelmat);
623 }
624}
625
627{
628 Render *re = engine->re;
629 return BKE_camera_multiview_spherical_stereo(re ? &re->r : nullptr, camera) ? true : false;
630}
631
632const rcti *RE_engine_get_current_tiles(Render *re, int *r_total_tiles)
633{
635 if (!tiles_highlight) {
636 *r_total_tiles = 0;
637 return nullptr;
638 };
639
640 blender::Span<rcti> highlighted_tiles = tiles_highlight->get_all_highlighted_tiles();
641
642 *r_total_tiles = highlighted_tiles.size();
643 return highlighted_tiles.data();
644}
645
647{
648 return &re->r;
649}
650
652{
653 /* Re-rendering is not supported with GPU contexts, since the GPU context
654 * is destroyed when the render thread exists. */
655 return (engine->re->r.mode & R_PERSISTENT_DATA) && !(engine->type->flag & RE_USE_GPU_CONTEXT);
656}
657
659{
660 /* For persistent data or GPU engines like Eevee, reuse the depsgraph between
661 * view layers and animation frames. For renderers like Cycles that create
662 * their own copy of the scene, persistent data must be explicitly enabled to
663 * keep memory usage low by default. */
664 return (engine->re->r.mode & R_PERSISTENT_DATA) || (engine->type->flag & RE_USE_GPU_CONTEXT);
665}
666
667/* Depsgraph */
668static void engine_depsgraph_init(RenderEngine *engine, ViewLayer *view_layer)
669{
670 Main *bmain = engine->re->main;
671 Scene *scene = engine->re->scene;
672 bool reuse_depsgraph = false;
673
674 /* Reuse depsgraph from persistent data if possible. */
675 if (engine->depsgraph) {
676 if (DEG_get_bmain(engine->depsgraph) != bmain ||
677 DEG_get_input_scene(engine->depsgraph) != scene)
678 {
679 /* If bmain or scene changes, we need a completely new graph. */
680 engine_depsgraph_free(engine);
681 }
682 else if (DEG_get_input_view_layer(engine->depsgraph) != view_layer) {
683 /* If only view layer changed, reuse depsgraph in the hope of reusing
684 * objects shared between view layers. */
685 DEG_graph_replace_owners(engine->depsgraph, bmain, scene, view_layer);
687 }
688
689 reuse_depsgraph = true;
690 }
691
692 if (!engine->depsgraph) {
693 /* Ensure we only use persistent data for one scene / view layer at a time,
694 * to avoid excessive memory usage. */
695 RE_FreePersistentData(nullptr);
696
697 /* Create new depsgraph if not cached with persistent data. */
698 engine->depsgraph = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_RENDER);
699 DEG_debug_name_set(engine->depsgraph, "RENDER");
700 }
701
702 if (engine->re->r.scemode & R_BUTS_PREVIEW) {
703 /* Update for preview render. */
704 Depsgraph *depsgraph = engine->depsgraph;
706
707 /* Need GPU context since this might free GPU buffers. */
708 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT) && reuse_depsgraph;
709 if (use_gpu_context) {
711 }
712
714
715 if (use_gpu_context) {
717 }
718 }
719 else {
720 /* Go through update with full Python callbacks for regular render. */
722 }
723
725}
726
728{
729 if (engine->depsgraph) {
730 if (engine_keep_depsgraph(engine)) {
731 /* Clear recalc flags since the engine should have handled the updates for the currently
732 * rendered framed by now. */
733 DEG_ids_clear_recalc(engine->depsgraph, false);
734 }
735 else {
736 /* Free immediately to save memory. */
737 engine_depsgraph_free(engine);
738 }
739 }
740}
741
742void RE_engine_frame_set(RenderEngine *engine, int frame, float subframe)
743{
744 if (!engine->depsgraph) {
745 return;
746 }
747
748 /* Clear recalc flags before update so engine can detect what changed. */
749 DEG_ids_clear_recalc(engine->depsgraph, false);
750
751 Render *re = engine->re;
752 double cfra = double(frame) + double(subframe);
753
754 CLAMP(cfra, MINAFRAME, MAXFRAME);
755 BKE_scene_frame_set(re->scene, cfra);
757
759}
760
761/* Bake */
762
764{
765 re->scene = scene;
766 re->main = bmain;
767 render_copy_renderdata(&re->r, &scene->r);
768}
769
771{
772 const RenderEngineType *type = RE_engines_find(re->r.engine);
773 return (type->bake != nullptr);
774}
775
777 Depsgraph *depsgraph,
778 Object *object,
779 const int object_id,
780 const BakePixel pixel_array[],
781 const BakeTargets *targets,
782 const eScenePassType pass_type,
783 const int pass_filter,
784 float result[])
785{
787 RenderEngine *engine;
788
789 /* set render info */
790 re->i.cfra = re->scene->r.cfra;
791 BLI_strncpy(re->i.scene_name, re->scene->id.name + 2, sizeof(re->i.scene_name) - 2);
792
793 /* render */
794 engine = re->engine;
795
796 if (!engine) {
797 engine = RE_engine_create(type);
798 re->engine = engine;
799 }
800
801 engine->flag |= RE_ENGINE_RENDERING;
802
803 /* TODO: actually link to a parent which shouldn't happen */
804 engine->re = re;
805
806 engine->resolution_x = re->winx;
807 engine->resolution_y = re->winy;
808
809 if (type->bake) {
810 engine->depsgraph = depsgraph;
811
812 /* update is only called so we create the engine.session */
813 if (type->update) {
814 type->update(engine, re->main, engine->depsgraph);
815 }
816
817 /* Bake all images. */
818 engine->bake.targets = targets;
819 engine->bake.pixels = pixel_array;
820 engine->bake.result = result;
821 engine->bake.object_id = object_id;
822
823 for (int i = 0; i < targets->images_num; i++) {
824 const BakeImage *image = &targets->images[i];
825 engine->bake.image_id = i;
826
827 type->bake(
828 engine, engine->depsgraph, object, pass_type, pass_filter, image->width, image->height);
829 }
830
831 /* Optionally let render images read bake images from disk delayed. */
832 if (type->render_frame_finish) {
833 engine->bake.image_id = 0;
834 type->render_frame_finish(engine);
835 }
836
837 memset(&engine->bake, 0, sizeof(engine->bake));
838
839 engine->depsgraph = nullptr;
840 }
841
842 engine->flag &= ~RE_ENGINE_RENDERING;
843
844 engine_depsgraph_free(engine);
845
846 RE_engine_free(engine);
847 re->engine = nullptr;
848
850 G.is_break = true;
851 }
852
853 return true;
854}
855
856/* Render */
857
859{
861 return false;
862 }
863
864 const Scene *scene = re->pipeline_scene_eval;
865 return (scene->nodetree && scene->use_nodes && (scene->r.scemode & R_DOCOMP));
866}
867
869 RenderEngine *engine,
870 ViewLayer *view_layer_iter,
871 const bool use_engine,
872 const bool use_grease_pencil)
873{
874 /* Lock UI so scene can't be edited while we read from it in this render thread. */
875 re->draw_lock();
876
877 /* Create depsgraph with scene evaluated at render resolution. */
878 ViewLayer *view_layer = static_cast<ViewLayer *>(
879 BLI_findstring(&re->scene->view_layers, view_layer_iter->name, offsetof(ViewLayer, name)));
880 if (!re->prepare_viewlayer(view_layer, engine->depsgraph)) {
881 re->draw_unlock();
882 return;
883 }
884 engine_depsgraph_init(engine, view_layer);
885
886 /* Sync data to engine, within draw lock so scene data can be accessed safely. */
887 if (use_engine) {
888 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
889 if (use_gpu_context) {
891 }
892 else if (G.background && ((engine->has_grease_pencil && use_grease_pencil) ||
894 {
895 /* Workaround for specific NVidia drivers which crash on Linux when OptiX context is
896 * initialized prior to OpenGL context. This affects driver versions 545.29.06, 550.54.14,
897 * and 550.67 running on kernel 6.8.
898 *
899 * The idea here is to initialize GPU context before giving control to the render engine in
900 * cases when we know that the GPU context will definitely be needed later on.
901 *
902 * Only do it for background renders to avoid possible extra global locking during the
903 * context initialization. For the non-background renders the GPU context is already
904 * initialized for the Blender interface and no workaround is needed.
905 *
906 * Technically it is enough to only call WM_init_gpu() here, but it expects to only be called
907 * once, and from here it is not possible to know whether GPU sub-system is initialized or
908 * not. So instead temporarily enable the render context, which will take care of the GPU
909 * context initialization.
910 *
911 * For demo file and tracking progress of possible fixes on driver side refer to #120007. */
914 }
915
916 if (engine->type->update) {
917 engine->type->update(engine, re->main, engine->depsgraph);
918 }
919 if (use_gpu_context) {
921 }
922 }
923
924 re->draw_unlock();
925
926 /* Perform render with engine. */
927 if (use_engine) {
928 const bool use_gpu_context = (engine->type->flag & RE_USE_GPU_CONTEXT);
929 if (use_gpu_context) {
931 }
932
936
937 engine->type->render(engine, engine->depsgraph);
938
942
943 if (use_gpu_context) {
945 }
946 }
947
948 /* Optionally composite grease pencil over render result.
949 * Only do it if the passes are allocated (and the engine will not override the grease pencil
950 * when reading its result from EXR file and writing to the Blender side. */
951 if (engine->has_grease_pencil && use_grease_pencil && re->result->passes_allocated) {
952 /* NOTE: External engine might have been requested to free its
953 * dependency graph, which is only allowed if there is no grease
954 * pencil (pipeline is taking care of that). */
955 if (!RE_engine_test_break(engine) && engine->depsgraph != nullptr) {
956 DRW_render_gpencil(engine, engine->depsgraph);
957 }
958 }
959
960 /* Free dependency graph, if engine has not done it already. */
961 engine_depsgraph_exit(engine);
962}
963
964/* Callback function for engine_render_create_result to add all render passes to the result. */
965static void engine_render_add_result_pass_cb(void *user_data,
966 Scene * /*scene*/,
967 ViewLayer *view_layer,
968 const char *name,
969 int channels,
970 const char *chanid,
971 eNodeSocketDatatype /*type*/)
972{
973 RenderResult *rr = (RenderResult *)user_data;
974 RE_create_render_pass(rr, name, channels, chanid, view_layer->name, RR_ALL_VIEWS, false);
975}
976
978{
980 if (rr == nullptr) {
981 return nullptr;
982 }
983
984 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer) {
986 re->engine, re->scene, view_layer, engine_render_add_result_pass_cb, rr);
987 }
989
990 /* Preview does not support deferred render result allocation. */
991 if (re->r.scemode & R_BUTS_PREVIEW) {
993 }
994
995 return rr;
996}
997
998bool RE_engine_render(Render *re, bool do_all)
999{
1001
1002 /* verify if we can render */
1003 if (!type->render) {
1004 return false;
1005 }
1006 if ((re->r.scemode & R_BUTS_PREVIEW) && !(type->flag & RE_USE_PREVIEW)) {
1007 return false;
1008 }
1009 if (do_all && !(type->flag & RE_USE_POSTPROCESS)) {
1010 return false;
1011 }
1012 if (!do_all && (type->flag & RE_USE_POSTPROCESS)) {
1013 return false;
1014 }
1015
1016 /* Lock drawing in UI during data phase. */
1017 re->draw_lock();
1018
1019 if ((type->flag & RE_USE_GPU_CONTEXT) && !GPU_backend_supported()) {
1020 /* Clear UI drawing locks. */
1021 re->draw_unlock();
1022 BKE_report(re->reports, RPT_ERROR, "Cannot initialize the GPU");
1023 G.is_break = true;
1024 return true;
1025 }
1026
1027 /* Create engine. */
1028 RenderEngine *engine = re->engine;
1029
1030 if (!engine) {
1031 engine = RE_engine_create(type);
1032 re->engine = engine;
1033 }
1034
1035 /* Create render result. Do this before acquiring lock, to avoid lock
1036 * inversion as this calls python to get the render passes, while python UI
1037 * code can also hold a lock on the render result. */
1038 const bool create_new_result = (re->result == nullptr || !(re->r.scemode & R_BUTS_PREVIEW));
1039 RenderResult *new_result = (create_new_result) ? engine_render_create_result(re) : nullptr;
1040
1042 if (create_new_result) {
1043 if (re->result) {
1045 }
1046
1047 re->result = new_result;
1048 }
1050
1051 if (re->result == nullptr) {
1052 /* Clear UI drawing locks. */
1053 re->draw_unlock();
1054 /* Free engine. */
1055 RE_engine_free(engine);
1056 re->engine = nullptr;
1057 /* Too small image is handled earlier, here it could only happen if
1058 * there was no sufficient memory to allocate all passes.
1059 */
1060 BKE_report(re->reports, RPT_ERROR, "Failed allocate render result, out of memory");
1061 G.is_break = true;
1062 return true;
1063 }
1064
1065 /* set render info */
1066 re->i.cfra = re->scene->r.cfra;
1067 STRNCPY(re->i.scene_name, re->scene->id.name + 2);
1068
1069 engine->flag |= RE_ENGINE_RENDERING;
1070
1071 /* TODO: actually link to a parent which shouldn't happen */
1072 engine->re = re;
1073
1074 if (re->flag & R_ANIMATION) {
1075 engine->flag |= RE_ENGINE_ANIMATION;
1076 }
1077 if (re->r.scemode & R_BUTS_PREVIEW) {
1078 engine->flag |= RE_ENGINE_PREVIEW;
1079 }
1080 engine->camera_override = re->camera_override;
1081
1082 engine->resolution_x = re->winx;
1083 engine->resolution_y = re->winy;
1084
1085 /* Clear UI drawing locks. */
1086 re->draw_unlock();
1087
1088 /* Render view layers. */
1089 bool delay_grease_pencil = false;
1090
1091 if (type->render) {
1092 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) {
1093 const bool use_grease_pencil = (view_layer_iter->layflag & SCE_LAY_GREASE_PENCIL) != 0;
1094 engine_render_view_layer(re, engine, view_layer_iter, true, use_grease_pencil);
1095
1096 /* If render passes are not allocated the render engine deferred final pixels write for
1097 * later. Need to defer the grease pencil for until after the engine has written the
1098 * render result to Blender. */
1099 delay_grease_pencil = use_grease_pencil && engine->has_grease_pencil &&
1101
1102 if (RE_engine_test_break(engine)) {
1103 break;
1104 }
1105 }
1107 }
1108
1109 if (type->render_frame_finish) {
1110 type->render_frame_finish(engine);
1111 }
1112
1113 /* Perform delayed grease pencil rendering. */
1114 if (delay_grease_pencil) {
1115 FOREACH_VIEW_LAYER_TO_RENDER_BEGIN (re, view_layer_iter) {
1116 const bool use_grease_pencil = (view_layer_iter->layflag & SCE_LAY_GREASE_PENCIL) != 0;
1117 if (!use_grease_pencil) {
1118 continue;
1119 }
1120 engine_render_view_layer(re, engine, view_layer_iter, false, true);
1121 if (RE_engine_test_break(engine)) {
1122 break;
1123 }
1124 }
1126 }
1127
1128 /* Clear tile data */
1129 engine->flag &= ~RE_ENGINE_RENDERING;
1130
1132 static_cast<RenderResult *>(engine->fullresult.first));
1133
1134 /* re->engine becomes zero if user changed active render engine during render */
1135 if (!engine_keep_depsgraph(engine) || !re->engine) {
1136 engine_depsgraph_free(engine);
1137
1138 RE_engine_free(engine);
1139 re->engine = nullptr;
1140 }
1141
1142 if (re->r.scemode & R_EXR_CACHE_FILE) {
1146 }
1147
1149 G.is_break = true;
1150 }
1151
1152#ifdef WITH_FREESTYLE
1153 if (re->r.mode & R_EDGE_FRS) {
1154 RE_RenderFreestyleExternal(re);
1155 }
1156#endif
1157
1158 return true;
1159}
1160
1162 Scene *scene,
1163 ViewLayer *view_layer,
1165 void *callback_data)
1166{
1167 if (!(scene && view_layer && engine && callback && engine->type->update_render_passes)) {
1168 return;
1169 }
1170
1172
1173 engine->update_render_passes_cb = callback;
1174 engine->update_render_passes_data = callback_data;
1175 engine->type->update_render_passes(engine, scene, view_layer);
1176 engine->update_render_passes_cb = nullptr;
1177 engine->update_render_passes_data = nullptr;
1178
1180}
1181
1183 Scene *scene,
1184 ViewLayer *view_layer,
1185 const char *name,
1186 int channels,
1187 const char *chanid,
1189{
1190 if (!(scene && view_layer && engine && engine->update_render_passes_cb)) {
1191 return;
1192 }
1193
1195 engine->update_render_passes_data, scene, view_layer, name, channels, chanid, type);
1196}
1197
1199{
1200 /* Weak way to save memory, but not crash grease pencil.
1201 *
1202 * TODO(sergey): Find better solution for this.
1203 */
1204 if (engine->has_grease_pencil || engine_keep_depsgraph(engine)) {
1205 return;
1206 }
1207 engine_depsgraph_free(engine);
1208}
1209
1211{
1212 return re->engine;
1213}
1214
1216{
1217 return view_render->engine;
1218}
1219
1221{
1222 RenderEngine *engine = re->engine;
1223
1224 if (!engine) {
1225 /* No engine-side drawing if the engine does not exist. */
1226 return false;
1227 }
1228
1229 if (!engine->type->draw) {
1230 /* Required callbacks are not implemented on the engine side. */
1231 return false;
1232 }
1233
1234 /* Lock before checking the flag, to avoid possible conflicts with the render thread. */
1236
1237 if ((engine->flag & RE_ENGINE_CAN_DRAW) == 0) {
1238 /* The rendering is not started yet, or has finished.
1239 *
1240 * In the former case there will nothing to be drawn, so can simply use RenderResult drawing
1241 * pipeline. In the latter case the engine has destroyed its display-only resources (textures,
1242 * graphics interops, etc..) so need to use the #RenderResult drawing pipeline. */
1244 return false;
1245 }
1246
1247 return true;
1248}
1249
1254
1256 RenderEngine *engine, int x, int y, int width, int height, bool highlight)
1257{
1258 if (!engine->re) {
1259 /* No render on the engine, so nowhere to store the highlighted tiles information. */
1260 return;
1261 }
1262 if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
1263 /* Engine reported it does not support tiles highlight, but attempted to set the highlight.
1264 * Technically it is a logic error, but there is no good way to inform an external engine about
1265 * it. */
1266 return;
1267 }
1268
1269 blender::render::TilesHighlight *tile_highlight = engine->re->get_tile_highlight();
1270 if (!tile_highlight) {
1271 /* The renderer itself does not support tiles highlight. */
1272 return;
1273 }
1274
1275 if (highlight) {
1276 tile_highlight->highlight_tile(x, y, width, height);
1277 }
1278 else {
1279 tile_highlight->unhighlight_tile(x, y, width, height);
1280 }
1281}
1282
1284{
1285 if (!engine->re) {
1286 /* No render on the engine, so nowhere to store the highlighted tiles information. */
1287 return;
1288 }
1289 if ((engine->flag & RE_ENGINE_HIGHLIGHT_TILES) == 0) {
1290 /* Engine reported it does not support tiles highlight, but attempted to set the highlight.
1291 * Technically it is a logic error, but there is no good way to inform an external engine about
1292 * it. */
1293 return;
1294 }
1295
1296 blender::render::TilesHighlight *tile_highlight = engine->re->get_tile_highlight();
1297 if (!tile_highlight) {
1298 /* The renderer itself does not support tiles highlight. */
1299 return;
1300 }
1301
1302 tile_highlight->clear();
1303}
1304
1305/* -------------------------------------------------------------------- */
1313
1315{
1316 /* If the there already is a draw manager render context available, reuse it. */
1317 engine->use_drw_render_context = (engine->re && RE_system_gpu_context_get(engine->re));
1318 if (engine->use_drw_render_context) {
1319 return true;
1320 }
1321
1322 /* Viewport render case where no render context is available. We are expected to be on
1323 * the main thread here to safely create a context. */
1325
1326 const bool drw_state = DRW_gpu_context_release();
1328
1329 if (engine->system_gpu_context) {
1330 /* Activate new GPU Context for GPUContext creation. */
1332 /* Requires GPUContext for usage of GPU Module for displaying results. */
1333 engine->blender_gpu_context = GPU_context_create(nullptr, engine->system_gpu_context);
1334 GPU_context_active_set(nullptr);
1335 /* Deactivate newly created GPU Context, as it is not needed until
1336 * `RE_engine_gpu_context_enable` is called. */
1338 }
1339 else {
1340 engine->blender_gpu_context = nullptr;
1341 }
1342
1343 DRW_gpu_context_activate(drw_state);
1344
1345 return engine->system_gpu_context != nullptr;
1346}
1347
1349{
1350 if (!engine->system_gpu_context) {
1351 return;
1352 }
1353
1354 const bool drw_state = DRW_gpu_context_release();
1355
1357 if (engine->blender_gpu_context) {
1358 GPUContext *restore_context = GPU_context_active_get();
1361 if (restore_context != engine->blender_gpu_context) {
1362 GPU_context_active_set(restore_context);
1363 }
1364 engine->blender_gpu_context = nullptr;
1365 }
1367 engine->system_gpu_context = nullptr;
1368
1369 DRW_gpu_context_activate(drw_state);
1370}
1371
1373{
1374 engine->gpu_restore_context = false;
1375 if (engine->use_drw_render_context) {
1377 return true;
1378 }
1379 if (engine->system_gpu_context) {
1381 /* If a previous GPU/GPUContext was active (DST.blender_gpu_context), we should later
1382 * restore this when disabling the RenderEngine context. */
1384
1385 /* Activate RenderEngine System and Blender GPU Context. */
1387 if (engine->blender_gpu_context) {
1390 }
1391 return true;
1392 }
1393 return false;
1394}
1395
1397{
1398 if (engine->use_drw_render_context) {
1400 }
1401 else {
1402 if (engine->system_gpu_context) {
1403 if (engine->blender_gpu_context) {
1404 GPU_context_active_set(nullptr);
1406 }
1408 /* Restore DRW state context if previously active. */
1411 }
1412 }
1413}
1414
1416{
1417 if (engine->use_drw_render_context) {
1418 /* Locking already handled by the draw manager. */
1419 }
1420 else {
1421 if (engine->system_gpu_context) {
1423 }
1424 }
1425}
1426
1428{
1429 if (engine->use_drw_render_context) {
1430 /* Locking already handled by the draw manager. */
1431 }
1432 else {
1433 if (engine->system_gpu_context) {
1435 }
1436 }
1437}
1438
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:343
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
bool BKE_scene_uses_cycles(const Scene *scene)
Definition scene.cc:2832
void BKE_scene_graph_update_for_newframe_ex(Depsgraph *depsgraph, bool clear_recalc)
Definition scene.cc:2628
void BKE_scene_frame_set(Scene *scene, float frame)
Definition scene.cc:2386
bool BKE_scene_camera_switch_update(Scene *scene)
Definition scene.cc:2267
bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
Definition scene.cc:2848
float BKE_scene_frame_get(const Scene *scene)
Definition scene.cc:2381
void BKE_scene_ppm_get(const RenderData *rd, double r_ppm[2])
Definition scene.cc:3245
#define BLI_assert(a)
Definition BLI_assert.h:46
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
void * BLI_findstring(const ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:608
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
MINLINE float int_as_float(int i)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:599
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
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)
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:278
void DEG_graph_replace_owners(Depsgraph *depsgraph, Main *bmain, Scene *scene, ViewLayer *view_layer)
Definition depsgraph.cc:285
void DEG_graph_free(Depsgraph *graph)
Definition depsgraph.cc:306
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
#define MINAFRAME
@ SCE_LAY_GREASE_PENCIL
@ R_PERSISTENT_DATA
@ R_EDGE_FRS
@ R_EXR_CACHE_FILE
@ R_DOCOMP
@ R_BUTS_PREVIEW
@ SCE_COMPOSITOR_DEVICE_GPU
eScenePassType
#define MAXFRAME
bool DRW_render_check_grease_pencil(Depsgraph *depsgraph)
void DRW_module_exit()
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)
bool DRW_gpu_context_try_enable()
void DRW_module_init()
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 *)
Read Guarded memory(de)allocation.
@ RE_INTERNAL
Definition RE_engine.h:43
@ RE_USE_PREVIEW
Definition RE_engine.h:44
@ RE_USE_ALEMBIC_PROCEDURAL
Definition RE_engine.h:53
@ RE_USE_POSTPROCESS
Definition RE_engine.h:45
@ RE_USE_GPU_CONTEXT
Definition RE_engine.h:50
void(*)(void *userdata, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int channels, const char *chanid, eNodeSocketDatatype type) update_render_passes_cb_t
Definition RE_engine.h:122
@ RE_ENGINE_PREVIEW
Definition RE_engine.h:60
@ RE_ENGINE_HIGHLIGHT_TILES
Definition RE_engine.h:64
@ RE_ENGINE_RENDERING
Definition RE_engine.h:63
@ RE_ENGINE_CAN_DRAW
Definition RE_engine.h:65
@ RE_ENGINE_ANIMATION
Definition RE_engine.h:59
float progress
Definition WM_types.hh:1019
return true
BPy_StructRNA * depsgraph
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:215
constexpr int64_t size() const
Definition BLI_span.hh:252
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)
#define offsetof(t, d)
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)
static bool possibly_using_gpu_compositor(const Render *re)
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_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
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)
int height
Definition RE_bake.h:25
char render_layer_name[RE_MAXNAME]
Definition RE_bake.h:29
size_t offset
Definition RE_bake.h:26
struct Image * image
Definition RE_bake.h:21
int width
Definition RE_bake.h:24
float dv_dx
Definition RE_bake.h:55
float du_dx
Definition RE_bake.h:54
int seed
Definition RE_bake.h:52
float du_dy
Definition RE_bake.h:54
float uv[2]
Definition RE_bake.h:53
float dv_dy
Definition RE_bake.h:55
int object_id
Definition RE_bake.h:51
int primitive_id
Definition RE_bake.h:51
int channels_num
Definition RE_bake.h:44
int images_num
Definition RE_bake.h:35
BakeImage * images
Definition RE_bake.h:34
ThreadMutex engine_draw_mutex
struct RenderEngine * engine
ThreadRWMutex resultmutex
RenderResult * result
StructFreeFunc free
Definition RNA_types.hh:911
char name[66]
Definition DNA_ID.h:415
ImBufFloatBuffer float_buffer
void * first
char engine[32]
void(* render)(struct RenderEngine *engine, struct Depsgraph *depsgraph)
Definition RE_engine.h:80
void(* update)(struct RenderEngine *engine, struct Main *bmain, struct Depsgraph *depsgraph)
Definition RE_engine.h:78
ExtensionRNA rna_ext
Definition RE_engine.h:119
struct RenderEngineType * next
Definition RE_engine.h:71
void(* draw)(struct RenderEngine *engine, const struct bContext *context, struct Depsgraph *depsgraph)
Definition RE_engine.h:89
void(* render_frame_finish)(struct RenderEngine *engine)
Definition RE_engine.h:87
void(* update_render_passes)(struct RenderEngine *engine, struct Scene *scene, struct ViewLayer *view_layer)
Definition RE_engine.h:111
void(* bake)(struct RenderEngine *engine, struct Depsgraph *depsgraph, struct Object *object, int pass_type, int pass_filter, int width, int height)
Definition RE_engine.h:93
struct ReportList * reports
Definition RE_engine.h:144
struct RenderEngine::@234317041123312345317034025325215265244203147364 bake
struct Depsgraph * depsgraph
Definition RE_engine.h:155
RenderEngineType * type
Definition RE_engine.h:131
const struct BakePixel * pixels
Definition RE_engine.h:148
ThreadMutex blender_gpu_context_mutex
Definition RE_engine.h:165
float * result
Definition RE_engine.h:149
char text[512]
Definition RE_engine.h:140
bool has_grease_pencil
Definition RE_engine.h:156
bool use_drw_render_context
Definition RE_engine.h:166
struct Render * re
Definition RE_engine.h:138
struct GPUContext * blender_gpu_context
Definition RE_engine.h:167
void * update_render_passes_data
Definition RE_engine.h:161
ListBase fullresult
Definition RE_engine.h:139
void * py_instance
Definition RE_engine.h:132
void * system_gpu_context
Definition RE_engine.h:164
update_render_passes_cb_t update_render_passes_cb
Definition RE_engine.h:160
bool gpu_restore_context
Definition RE_engine.h:169
ThreadMutex update_render_passes_mutex
Definition RE_engine.h:159
const struct BakeTargets * targets
Definition RE_engine.h:147
struct Object * camera_override
Definition RE_engine.h:135
ListBase passes
Definition RE_pipeline.h:89
char name[RE_MAXNAME]
Definition RE_pipeline.h:81
struct ImBuf * ibuf
Definition RE_pipeline.h:60
ListBase layers
bool passes_allocated
double ppm[2]
const char * statstr
char scene_name[MAX_ID_NAME - 2]
const char * infostr
Scene * pipeline_scene_eval
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 bNodeTree * nodetree
struct RenderData r
ListBase view_layers
char name[64]
int ymin
int ymax
int xmin
int xmax
i
Definition text_draw.cc:230
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)