Blender V4.5
eevee_instance.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include "BKE_global.hh"
12#include "BKE_object.hh"
13
14#include "BLI_rect.h"
15#include "BLI_time.h"
16
17#include "BLT_translation.hh"
18
20
21#include "DNA_ID.h"
23#include "DNA_modifier_types.h"
24
25#include "ED_screen.hh"
26#include "ED_view3d.hh"
27#include "GPU_context.hh"
28#include "GPU_pass.hh"
29#include "IMB_imbuf_types.hh"
30
31#include "RE_pipeline.h"
32
33#include "eevee_engine.h"
34#include "eevee_instance.hh"
35
36#include "DNA_particle_types.h"
37
38#include "draw_common.hh"
40#include "draw_view_data.hh"
41
42namespace blender::eevee {
43
44void *Instance::debug_scope_render_sample = nullptr;
45void *Instance::debug_scope_irradiance_setup = nullptr;
46void *Instance::debug_scope_irradiance_sample = nullptr;
47
48/* -------------------------------------------------------------------- */
57
59{
60 this->draw_ctx = DRW_context_get();
61
62 Depsgraph *depsgraph = draw_ctx->depsgraph;
63 Scene *scene = draw_ctx->scene;
64 View3D *v3d = draw_ctx->v3d;
65 ARegion *region = draw_ctx->region;
66 RegionView3D *rv3d = draw_ctx->rv3d;
67
68 DefaultTextureList *dtxl = draw_ctx->viewport_texture_list_get();
70
71 draw::View &default_view = draw::View::default_get();
72
73 Object *camera = nullptr;
74 /* Get render borders. */
75 rcti rect;
76 BLI_rcti_init(&rect, 0, size[0], 0, size[1]);
77 rcti visible_rect = rect;
78 if (v3d) {
79 if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
80 camera = v3d->camera;
81 }
82
83 if (camera) {
84 rctf default_border;
85 BLI_rctf_init(&default_border, 0.0f, 1.0f, 0.0f, 1.0f);
86 bool is_default_border = BLI_rctf_compare(&scene->r.border, &default_border, 0.0f);
87 bool use_border = scene->r.mode & R_BORDER;
88 if (!is_default_border && use_border) {
89 rctf viewborder;
90 /* TODO(fclem) Might be better to get it from DRW. */
91 ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, false, &viewborder);
92 float viewborder_sizex = BLI_rctf_size_x(&viewborder);
93 float viewborder_sizey = BLI_rctf_size_y(&viewborder);
94 rect.xmin = floorf(viewborder.xmin + (scene->r.border.xmin * viewborder_sizex));
95 rect.ymin = floorf(viewborder.ymin + (scene->r.border.ymin * viewborder_sizey));
96 rect.xmax = floorf(viewborder.xmin + (scene->r.border.xmax * viewborder_sizex));
97 rect.ymax = floorf(viewborder.ymin + (scene->r.border.ymax * viewborder_sizey));
98 /* Clamp it to the viewport area. */
99 rect.xmin = max(rect.xmin, 0);
100 rect.ymin = max(rect.ymin, 0);
101 rect.xmax = min(rect.xmax, size.x);
102 rect.ymax = min(rect.ymax, size.y);
103 }
104 }
105 else if (v3d->flag2 & V3D_RENDER_BORDER) {
106 rect.xmin = v3d->render_border.xmin * size[0];
107 rect.ymin = v3d->render_border.ymin * size[1];
108 rect.xmax = v3d->render_border.xmax * size[0];
109 rect.ymax = v3d->render_border.ymax * size[1];
110 }
111
112 if (draw_ctx->is_viewport_image_render()) {
113 const float2 vp_size = draw_ctx->viewport_size_get();
114 visible_rect.xmax = vp_size[0];
115 visible_rect.ymax = vp_size[1];
116 visible_rect.xmin = visible_rect.ymin = 0;
117 }
118 else {
119 visible_rect = *ED_region_visible_rect(region);
120 }
121 }
122
123 init(size, &rect, &visible_rect, nullptr, depsgraph, camera, nullptr, &default_view, v3d, rv3d);
124}
125
126void Instance::init(const int2 &output_res,
127 const rcti *output_rect,
128 const rcti *visible_rect,
129 RenderEngine *render_,
130 Depsgraph *depsgraph_,
131 Object *camera_object_,
132 const RenderLayer *render_layer_,
133 View *drw_view_,
134 const View3D *v3d_,
135 const RegionView3D *rv3d_)
136{
137 this->draw_ctx = DRW_context_get();
138
139 render = render_;
140 depsgraph = depsgraph_;
141 camera_orig_object = camera_object_;
142 render_layer = render_layer_;
143 drw_view = drw_view_;
144 v3d = v3d_;
145 rv3d = rv3d_;
147 update_eval_members();
148
149 info_ = "";
150
151 if (is_viewport()) {
152 is_image_render = draw_ctx->is_image_render();
153 is_viewport_image_render = draw_ctx->is_viewport_image_render();
154 is_viewport_compositor_enabled = draw_ctx->is_viewport_compositor_enabled();
155 is_playback = draw_ctx->is_playback();
156 is_navigating = draw_ctx->is_navigating();
157 is_painting = draw_ctx->is_painting();
158 is_transforming = draw_ctx->is_transforming();
159 draw_overlays = v3d && (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
160
161 /* Note: Do not update the value here as we use it during sync for checking ID updates. */
162 if (depsgraph_last_update_ != DEG_get_update_count(depsgraph)) {
163 sampling.reset();
164 }
165 if (assign_if_different(debug_mode, (eDebugMode)G.debug_value)) {
166 sampling.reset();
167 }
168 if (output_res != film.display_extent_get()) {
169 sampling.reset();
170 }
171 if (output_rect) {
172 int2 offset = int2(output_rect->xmin, output_rect->ymin);
173 int2 extent = int2(BLI_rcti_size_x(output_rect), BLI_rcti_size_y(output_rect));
174 if (offset != film.get_data().offset || extent != film.get_data().extent) {
175 sampling.reset();
176 }
177 }
178 if (assign_if_different(overlays_enabled_, v3d && !(v3d->flag2 & V3D_HIDE_OVERLAYS))) {
179 sampling.reset();
180 }
181 if (is_painting) {
182 sampling.reset();
183 }
185 sampling.reset();
186 }
187 }
188 else {
189 is_image_render = true;
190 }
191
192 sampling.init(scene);
193 camera.init();
194 film.init(output_res, output_rect);
195 render_buffers.init();
196 ambient_occlusion.init();
197 velocity.init();
198 raytracing.init();
199 depth_of_field.init();
200 shadows.init();
201 motion_blur.init();
202 main_view.init();
203 light_probes.init();
204 planar_probes.init();
205 /* Irradiance Cache needs reflection probes to be initialized. */
206 sphere_probes.init();
207 volume_probes.init();
208 volume.init();
209 lookdev.init(visible_rect);
210
211 /* Request static shaders */
215 SET_FLAG_FROM_TEST(shader_request, depth_of_field.enabled(), DEPTH_OF_FIELD_SHADERS);
218 SET_FLAG_FROM_TEST(shader_request, motion_blur.postfx_enabled(), MOTION_BLUR_SHADERS);
219 SET_FLAG_FROM_TEST(shader_request, raytracing.use_fast_gi(), HORIZON_SCAN_SHADERS);
220 SET_FLAG_FROM_TEST(shader_request, raytracing.use_raytracing(), RAYTRACING_SHADERS);
221
223 loaded_shaders |= shaders.static_shaders_load_async(shader_request);
224 loaded_shaders |= materials.default_materials_load_async();
225
226 if (is_image_render) {
227 /* Ensure all deferred shaders have been compiled to kick-start asynchronous specialization. */
228 loaded_shaders |= shaders.static_shaders_wait_ready(DEFERRED_LIGHTING_SHADERS);
229 }
230
232 bool ready = shaders.request_specializations(
234 render_buffers.data.shadow_id,
235 shadows.get_data().ray_count,
236 shadows.get_data().step_count,
240 }
241
242 if (is_image_render) {
243 loaded_shaders |= shaders.static_shaders_wait_ready(shader_request);
244 loaded_shaders |= materials.default_materials_wait_ready();
245 }
246
247 /* Needed bits to be able to display something to the screen. */
248 needed_shaders = shader_request | DEFAULT_MATERIALS;
249
250 skip_render_ = !is_loaded(needed_shaders) || !film.is_valid_render_extent();
251}
252
254{
255 this->depsgraph = depsgraph;
256 this->manager = manager;
257 camera_orig_object = nullptr;
258 render = nullptr;
259 render_layer = nullptr;
260 drw_view = nullptr;
261 v3d = nullptr;
262 rv3d = nullptr;
263 update_eval_members();
264
265 is_light_bake = true;
266 debug_mode = (eDebugMode)G.debug_value;
267 info_ = "";
268
269 sampling.init(scene);
270 camera.init();
271 /* Film isn't used but init to avoid side effects in other module. */
272 rcti empty_rect{0, 0, 0, 0};
273 film.init(int2(1), &empty_rect);
274 render_buffers.init();
275 velocity.init();
276 depth_of_field.init();
277 shadows.init();
278 main_view.init();
279 light_probes.init();
280 planar_probes.init();
281 /* Irradiance Cache needs reflection probes to be initialized. */
282 sphere_probes.init();
283 volume_probes.init();
284 volume.init();
285 lookdev.init(&empty_rect);
286
288 shaders.static_shaders_load_async(needed_shaders);
289 shaders.static_shaders_wait_ready(needed_shaders);
290}
291
292void Instance::set_time(float time)
293{
296 update_eval_members();
297}
298
299void Instance::update_eval_members()
300{
304 nullptr;
305}
306
308
309/* -------------------------------------------------------------------- */
316
318{
319 /* Needs to be first for sun light parameters.
320 * Also not skipped to be able to request world shader.
321 * If engine shaders are not ready, will skip the pipeline sync. */
322 world.sync();
323
324 if (skip_render_) {
325 return;
326 }
327
328 materials.begin_sync();
329 velocity.begin_sync(); /* NOTE: Also syncs camera. */
330 lights.begin_sync();
331 shadows.begin_sync();
332 volume.begin_sync();
333 pipelines.begin_sync();
334 cryptomatte.begin_sync();
335 sphere_probes.begin_sync();
336 light_probes.begin_sync();
337
338 depth_of_field.sync();
339 raytracing.sync();
340 motion_blur.sync();
341 hiz_buffer.sync();
342 main_view.sync();
343 film.sync();
344 ambient_occlusion.sync();
345 volume_probes.sync();
346 lookdev.sync();
347
348 use_surfaces = (view_layer->layflag & SCE_LAY_SOLID) != 0;
349 use_curves = (view_layer->layflag & SCE_LAY_STRAND) != 0;
350 use_volumes = (view_layer->layflag & SCE_LAY_VOLUMES) != 0;
351
352 if (is_light_bake) {
353 /* Do not use render layer visibility during bake.
354 * NOTE: This is arbitrary and could be changed if needed. */
356 }
357
358 if (is_viewport() && velocity.camera_has_motion()) {
359 sampling.reset();
360 }
361}
362
363void Instance::object_sync(ObjectRef &ob_ref, Manager & /*manager*/)
364{
365 if (skip_render_) {
366 return;
367 }
368
369 Object *ob = ob_ref.object;
370 const bool is_renderable_type = ELEM(ob->type,
371 OB_CURVES,
373 OB_MESH,
375 OB_VOLUME,
376 OB_LAMP,
378 const int ob_visibility = DRW_object_visibility_in_active_context(ob);
379 const bool partsys_is_visible = (ob_visibility & OB_VISIBLE_PARTICLES) != 0 &&
380 (ob->type == OB_MESH);
381 const bool object_is_visible = DRW_object_is_renderable(ob) &&
382 (ob_visibility & OB_VISIBLE_SELF) != 0;
383
384 if (!is_renderable_type || (!partsys_is_visible && !object_is_visible)) {
385 return;
386 }
387
388 ObjectHandle &ob_handle = sync.sync_object(ob_ref);
389
390 if (partsys_is_visible && ob != draw_ctx->object_edit) {
391 auto sync_hair =
392 [&](ObjectHandle hair_handle, ModifierData &md, ParticleSystem &particle_sys) {
393 ResourceHandle _res_handle = manager->resource_handle_for_psys(ob_ref,
394 ob->object_to_world());
395 sync.sync_curves(ob, hair_handle, ob_ref, _res_handle, &md, &particle_sys);
396 };
397 foreach_hair_particle_handle(ob_ref, ob_handle, sync_hair);
398 }
399
400 if (object_is_visible) {
401 switch (ob->type) {
402 case OB_LAMP:
403 lights.sync_light(ob, ob_handle);
404 break;
405 case OB_MESH:
406 if (!sync.sync_sculpt(ob, ob_handle, ob_ref)) {
407 sync.sync_mesh(ob, ob_handle, ob_ref);
408 }
409 break;
410 case OB_POINTCLOUD:
411 sync.sync_pointcloud(ob, ob_handle, ob_ref);
412 break;
413 case OB_VOLUME:
414 sync.sync_volume(ob, ob_handle, ob_ref);
415 break;
416 case OB_CURVES:
417 sync.sync_curves(ob, ob_handle, ob_ref);
418 break;
419 case OB_LIGHTPROBE:
420 light_probes.sync_probe(ob, ob_handle);
421 break;
422 default:
423 break;
424 }
425 }
426}
427
429{
430 if (skip_render_) {
431 /* We might run in the case where the next check sets skip_render_ to false after the
432 * begin_sync was skipped, which would call `end_sync` function with invalid data. */
433 return;
434 }
435
436 bool use_sss = pipelines.deferred.closure_bits_get() & CLOSURE_SSS;
437 bool use_volume = volume.will_enable();
438
439 ShaderGroups request_bits = NONE;
440 SET_FLAG_FROM_TEST(request_bits, use_sss, SUBSURFACE_SHADERS);
441 SET_FLAG_FROM_TEST(request_bits, use_volume, VOLUME_EVAL_SHADERS);
442 loaded_shaders |= shaders.static_shaders_load_async(request_bits);
443 needed_shaders |= request_bits;
444
445 if (is_image_render) {
446 loaded_shaders |= shaders.static_shaders_wait_ready(request_bits);
447 }
448
449 materials.end_sync();
450 velocity.end_sync();
451 volume.end_sync(); /* Needs to be before shadows. */
452 shadows.end_sync(); /* Needs to be before lights. */
453 lights.end_sync();
454 sampling.end_sync();
455 subsurface.end_sync();
456 film.end_sync();
457 cryptomatte.end_sync();
458 pipelines.end_sync();
459 light_probes.end_sync();
460 sphere_probes.end_sync();
461 planar_probes.end_sync();
462
463 uniform_data.push_update();
464
465 depsgraph_last_update_ = DEG_get_update_count(depsgraph);
466}
467
469{
470 manager->begin_sync();
471
472 begin_sync();
473
475 render, depsgraph, [this](blender::draw::ObjectRef &ob_ref, RenderEngine *, Depsgraph *) {
476 this->object_sync(ob_ref, *this->manager);
477 });
478
479 velocity.geometry_steps_fill();
480
481 end_sync();
482
483 manager->end_sync();
484}
485
487{
488 return sphere_probes.update_probes_this_sample_;
489}
490
492{
493 return (materials.queued_shaders_count == 0) && (materials.queued_textures_count == 0) &&
495}
496
498{
499 return planar_probes.update_probes_;
500}
501
503{
504 return (materials.queued_shaders_count == 0) && (materials.queued_textures_count == 0) &&
506}
507
509
510/* -------------------------------------------------------------------- */
513
514void Instance::render_sample()
515{
518 film.display();
521 return;
522 }
523
524 /* Motion blur may need to do re-sync after a certain number of sample. */
525 if (!is_viewport() && sampling.do_render_sync()) {
526 render_sync();
530 /* This may need to happen more than once, since actual materials may require more passes
531 * (eg. volume ones) than the fallback material used for queued passes. */
532 /* TODO(@pragma37): There seems to be an issue where multiple `step_object_sync` calls on the
533 * same step can cause mismatching `has_motion` values between sync. */
534 render_sync();
535 }
536 }
537
538 DebugScope debug_scope(debug_scope_render_sample, "EEVEE.render_sample");
539
540 {
541 /* Critical section. Potential GPUShader concurrent usage. */
543
544 sampling.step();
545
546 capture_view.render_world();
547 capture_view.render_probes();
548
549 main_view.render();
550
551 lookdev_view.render();
552
554 }
555 motion_blur.step();
556}
557
558void Instance::render_read_result(RenderLayer *render_layer, const char *view_name)
559{
560 eViewLayerEEVEEPassType pass_bits = film.enabled_passes_get();
561
562 for (auto i : IndexRange(EEVEE_RENDER_PASS_MAX_BIT + 1)) {
563 eViewLayerEEVEEPassType pass_type = eViewLayerEEVEEPassType(pass_bits & (1 << i));
564 if (pass_type == 0) {
565 continue;
566 }
567
568 Vector<std::string> pass_names = Film::pass_to_render_pass_names(pass_type, view_layer);
569 for (int64_t pass_offset : IndexRange(pass_names.size())) {
570 RenderPass *rp = RE_pass_find_by_name(
571 render_layer, pass_names[pass_offset].c_str(), view_name);
572 if (!rp) {
573 continue;
574 }
575 float *result = film.read_pass(pass_type, pass_offset);
576
577 if (result) {
578 BLI_mutex_lock(&render->update_render_passes_mutex);
579 /* WORKAROUND: We use texture read to avoid using a frame-buffer to get the render result.
580 * However, on some implementation, we need a buffer with a few extra bytes for the read to
581 * happen correctly (see #GLTexture::read()). So we need a custom memory allocation. */
582 /* Avoid `memcpy()`, replace the pointer directly. */
584 BLI_mutex_unlock(&render->update_render_passes_mutex);
585 }
586 }
587 }
588
589 /* AOVs. */
590 LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
591 if ((aov->flag & AOV_CONFLICT) != 0) {
592 continue;
593 }
594 RenderPass *rp = RE_pass_find_by_name(render_layer, aov->name, view_name);
595 if (!rp) {
596 continue;
597 }
598 float *result = film.read_aov(aov);
599
600 if (result) {
601 BLI_mutex_lock(&render->update_render_passes_mutex);
602 /* WORKAROUND: We use texture read to avoid using a frame-buffer to get the render result.
603 * However, on some implementation, we need a buffer with a few extra bytes for the read to
604 * happen correctly (see #GLTexture::read()). So we need a custom memory allocation. */
605 /* Avoid #memcpy(), replace the pointer directly. */
607 BLI_mutex_unlock(&render->update_render_passes_mutex);
608 }
609 }
610
611 /* The vector pass is initialized to weird values. Set it to neutral value if not rendered. */
612 if ((pass_bits & EEVEE_RENDER_PASS_VECTOR) == 0) {
613 for (const std::string &vector_pass_name :
615 {
616 RenderPass *vector_rp = RE_pass_find_by_name(
617 render_layer, vector_pass_name.c_str(), view_name);
618 if (vector_rp) {
619 memset(vector_rp->ibuf->float_buffer.data,
620 0,
621 sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
622 }
623 }
624 }
625}
626
628
629/* -------------------------------------------------------------------- */
632
633void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, const char *view_name)
634{
635 skip_render_ = skip_render_ || !is_loaded(needed_shaders);
636
637 if (skip_render_) {
638 if (!info_.empty()) {
639 RE_engine_set_error_message(engine, info_.c_str());
640 info_ = "";
641 }
642 return;
643 }
644 /* TODO: Break on RE_engine_test_break(engine) */
645 while (!sampling.finished()) {
646 this->render_sample();
647
648 if ((sampling.sample_index() == 1) || ((sampling.sample_index() % 25) == 0) ||
649 sampling.finished())
650 {
651 /* TODO: Use `fmt`. */
652 std::string re_info = "Rendering " + std::to_string(sampling.sample_index()) + " / " +
653 std::to_string(sampling.sample_count()) + " samples";
654 RE_engine_update_stats(engine, nullptr, re_info.c_str());
655 }
656
657 /* Perform render step between samples to allow
658 * flushing of freed GPUBackend resources. */
660 GPU_flush();
661 }
663
664#if 0
665 /* TODO(fclem) print progression. */
666 RE_engine_update_progress(engine, float(sampling.sample_index()) / float(sampling.sample_count()));
667 /* TODO(fclem): Does not currently work. But would be better to just display to 2D view like
668 * cycles does. */
669 if (G.background == false && first_read) {
670 /* Allow to preview the first sample. */
671 /* TODO(fclem): Might want to not do this during animation render to avoid too much stall. */
672 this->render_read_result(render_layer, view_name);
673 first_read = false;
675 /* Allow the 2D viewport to grab the ticket mutex to display the render. */
677 }
678#endif
679 }
680
681 this->film.cryptomatte_sort();
682
683 this->render_read_result(render_layer, view_name);
684
685 if (!info_.empty()) {
687 engine, RPT_("Errors during render. See the System Console for more info."));
688 printf("%s", info_.c_str());
689 info_ = "";
690 }
691}
692
694{
695 if (skip_render_ || !is_loaded(needed_shaders)) {
696 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
699 info_append_i18n("Compiling EEVEE engine shaders");
701 }
702 /* Do not swap if the velocity module didn't go through a full sync cycle. */
704 /* The velocity module can reference some gpu::Batch. Calling this function
705 * make sure we release these references and don't de-reference them later as
706 * they might have been freed. */
707 velocity.step_swap();
708 }
709 return;
710 }
711
712 render_sample();
713 velocity.step_swap();
714
716 this->film.write_viewport_compositor_passes();
717 }
718
719 /* Do not request redraw during viewport animation to lock the frame-rate to the animation
720 * playback rate. This is in order to preserve motion blur aspect and also to avoid TAA reset
721 * that can show flickering. */
722 if (!sampling.finished_viewport() && !is_playback) {
724 }
725
726 if (materials.queued_shaders_count > 0 || materials.queued_textures_count > 0) {
727 if (materials.queued_textures_count > 0) {
728 info_append_i18n("Loading textures ({} remaining)", materials.queued_textures_count);
729 }
730 if (materials.queued_shaders_count > 0) {
731 info_append_i18n("Compiling shaders ({} remaining)", materials.queued_shaders_count);
733 /* Only recommend subprocesses when there is known gain. */
737 {
739 "Setting Preferences > System > Shader Compilation Method to Subprocess might improve "
740 "compilation time.");
741 }
742 }
744 }
745 else if (materials.queued_optimize_shaders_count > 0) {
746 info_append_i18n("Optimizing shaders ({} remaining)", materials.queued_optimize_shaders_count);
747 }
748}
749
751{
752 if (skip_render_) {
753 return;
754 }
755
756 do {
757 /* Render at least once to blit the finished image. */
758 this->render_sample();
759 } while (!sampling.finished_viewport());
760 velocity.step_swap();
761
763 this->film.write_viewport_compositor_passes();
764 }
765}
766
767void Instance::draw(Manager & /*manager*/)
768{
771 }
772 else {
774 }
776 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
778}
779
781{
782 if (skip_render_) {
783 return;
784 }
785 cryptomatte.store_metadata(render_result);
786}
787
789{
791
792#define CHECK_PASS_LEGACY(name, type, channels, chanid) \
793 if (view_layer->passflag & (SCE_PASS_##name)) { \
794 RE_engine_register_pass( \
795 engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
796 } \
797 ((void)0)
798#define CHECK_PASS_EEVEE(name, type, channels, chanid) \
799 if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \
800 RE_engine_register_pass( \
801 engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
802 } \
803 ((void)0)
804
806 CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z");
807 CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ");
808 CHECK_PASS_LEGACY(POSITION, SOCK_VECTOR, 3, "XYZ");
810 CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB");
811 CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB");
812 CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB");
813 CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB");
814 CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB");
815 CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB");
816 CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB");
817 CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB");
818 CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB");
819 CHECK_PASS_EEVEE(TRANSPARENT, SOCK_RGBA, 4, "RGBA");
820
821 LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
822 if ((aov->flag & AOV_CONFLICT) != 0) {
823 continue;
824 }
825 switch (aov->type) {
826 case AOV_TYPE_COLOR:
827 RE_engine_register_pass(engine, scene, view_layer, aov->name, 4, "RGBA", SOCK_RGBA);
828 break;
829 case AOV_TYPE_VALUE:
830 RE_engine_register_pass(engine, scene, view_layer, aov->name, 1, "X", SOCK_FLOAT);
831 break;
832 default:
833 break;
834 }
835 }
836
837 /* NOTE: Name channels lowercase `rgba` so that compression rules check in OpenEXR DWA code uses
838 * lossless compression. Reportedly this naming is the only one which works good from the
839 * interoperability point of view. Using `xyzw` naming is not portable. */
840 auto register_cryptomatte_passes = [&](eViewLayerCryptomatteFlags cryptomatte_layer,
841 eViewLayerEEVEEPassType eevee_pass) {
842 if (view_layer->cryptomatte_flag & cryptomatte_layer) {
843 for (const std::string &pass_name : Film::pass_to_render_pass_names(eevee_pass, view_layer))
844 {
846 engine, scene, view_layer, pass_name.c_str(), 4, "rgba", SOCK_RGBA);
847 }
848 }
849 };
852 register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_MATERIAL,
854}
855
857 Object &probe,
858 FunctionRef<void()> context_enable,
859 FunctionRef<void()> context_disable,
860 FunctionRef<bool()> stop,
861 FunctionRef<void(LightProbeGridCacheFrame *, float progress)> result_update)
862{
864
866 this->draw_ctx = &draw_ctx;
867
868 auto custom_pipeline_wrapper = [&](FunctionRef<void()> callback) {
869 context_enable();
871 callback();
873 context_disable();
874 };
875
876 auto context_wrapper = [&](FunctionRef<void()> callback) {
877 context_enable();
878 callback();
879 context_disable();
880 };
881
882 volume_probes.bake.init(probe);
883
884 custom_pipeline_wrapper([&]() {
885 this->render_sync();
886 while ((materials.queued_shaders_count > 0) || (materials.queued_textures_count > 0)) {
889 /* This may need to happen more than once, since actual materials may require more passes
890 * (eg. volume ones) than the fallback material used for queued passes. */
891 /* TODO(@pragma37): There seems to be an issue where multiple `step_object_sync` calls on the
892 * same step can cause mismatching `has_motion` values between sync. */
893 render_sync();
894 }
895 /* Sampling module needs to be initialized to computing lighting. */
896 sampling.init(probe);
897 sampling.step();
898
899 {
900 /* Critical section. Potential GPUShader concurrent usage. */
902
903 DebugScope debug_scope(debug_scope_irradiance_setup, "EEVEE.irradiance_setup");
904
905 capture_view.render_world();
906
907 volume_probes.bake.surfels_create(probe);
908
909 if (volume_probes.bake.should_break()) {
911 return;
912 }
913
914 volume_probes.bake.surfels_lights_eval();
915
916 volume_probes.bake.clusters_build();
917 volume_probes.bake.irradiance_offset();
918
920 }
921 });
922
923 if (volume_probes.bake.should_break()) {
924 return;
925 }
926
927 sampling.init(probe);
928 while (!sampling.finished()) {
929 context_wrapper([&]() {
930 DebugScope debug_scope(debug_scope_irradiance_sample, "EEVEE.irradiance_sample");
931
932 /* Batch ray cast by pack of 16. Avoids too much overhead of the update function & context
933 * switch. */
934 /* TODO(fclem): Could make the number of iteration depend on the computation time. */
935 for (int i = 0; i < 16 && !sampling.finished(); i++) {
936 sampling.step();
937 {
938 /* Critical section. Potential GPUShader concurrent usage. */
940
941 volume_probes.bake.raylists_build();
942 volume_probes.bake.propagate_light();
943 volume_probes.bake.irradiance_capture();
944
946 }
947 }
948
949 LightProbeGridCacheFrame *cache_frame;
950 if (sampling.finished()) {
951 cache_frame = volume_probes.bake.read_result_packed();
952 }
953 else {
954 /* TODO(fclem): Only do this read-back if needed. But it might be tricky to know when. */
955 cache_frame = volume_probes.bake.read_result_unpacked();
956 }
957
958 float progress = sampling.sample_index() / float(sampling.sample_count());
959 result_update(cache_frame, progress);
960 });
961
962 if (stop()) {
963 return;
964 }
965 }
966}
967
969
970} // namespace blender::eevee
General operations, lookup, etc. for blender objects.
@ OB_VISIBLE_SELF
@ OB_VISIBLE_PARTICLES
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax)
Definition rct.cc:414
void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax)
Definition rct.cc:404
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
BLI_INLINE float BLI_rctf_size_x(const struct rctf *rct)
Definition BLI_rect.h:202
BLI_INLINE float BLI_rctf_size_y(const struct rctf *rct)
Definition BLI_rect.h:206
bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, float limit)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
Platform independent time functions.
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define RPT_(msgid)
uint64_t DEG_get_update_count(const Depsgraph *depsgraph)
Definition depsgraph.cc:355
Scene * DEG_get_evaluated_scene(const Depsgraph *graph)
ViewLayer * DEG_get_evaluated_view_layer(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
ID and Library types, which are fundamental for SDNA.
eViewLayerCryptomatteFlags
@ VIEW_LAYER_CRYPTOMATTE_MATERIAL
@ VIEW_LAYER_CRYPTOMATTE_ASSET
@ VIEW_LAYER_CRYPTOMATTE_OBJECT
#define EEVEE_RENDER_PASS_MAX_BIT
eViewLayerEEVEEPassType
@ EEVEE_RENDER_PASS_CRYPTOMATTE_MATERIAL
@ EEVEE_RENDER_PASS_CRYPTOMATTE_OBJECT
@ EEVEE_RENDER_PASS_CRYPTOMATTE_ASSET
@ EEVEE_RENDER_PASS_VECTOR
@ AOV_TYPE_COLOR
@ AOV_TYPE_VALUE
@ AOV_CONFLICT
struct ViewLayerAOV ViewLayerAOV
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_RGBA
@ OB_GREASE_PENCIL
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES
@ OB_LIGHTPROBE
#define RE_PASSNAME_COMBINED
@ SCE_LAY_SOLID
@ SCE_LAY_STRAND
@ SCE_LAY_VOLUMES
@ R_BORDER
@ SCE_EEVEE_SHADOW_JITTERED_VIEWPORT
@ RV3D_CAMOB
@ V3D_HIDE_OVERLAYS
@ V3D_RENDER_BORDER
void DRW_submission_end()
void DRW_render_context_disable(Render *render)
void DRW_submission_start()
void DRW_render_context_enable(Render *render)
const rcti * ED_region_visible_rect(ARegion *region)
Definition area.cc:4114
void ED_view3d_calc_camera_border(const Scene *scene, const Depsgraph *depsgraph, const ARegion *region, const View3D *v3d, const RegionView3D *rv3d, bool no_shift, rctf *r_viewborder)
bool GPU_use_subprocess_compilation()
void GPU_render_step(bool force_resource_release=false)
eGPUBackendType GPU_backend_get_type()
void GPU_framebuffer_viewport_reset(GPUFrameBuffer *fb)
void GPU_framebuffer_clear_color_depth(GPUFrameBuffer *fb, const float clear_col[4], float clear_depth)
void GPU_pass_cache_wait_for_all()
Definition gpu_pass.cc:331
@ GPU_DRIVER_ANY
@ GPU_DRIVER_OFFICIAL
@ GPU_OS_WIN
@ GPU_OS_ANY
@ GPU_DEVICE_ATI
@ GPU_DEVICE_NVIDIA
@ GPU_DEVICE_INTEL
bool GPU_type_matches(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver)
void GPU_flush()
Definition gpu_state.cc:305
int GPU_texture_height(const GPUTexture *texture)
int GPU_texture_width(const GPUTexture *texture)
#define Z
bool stop
Definition WM_types.hh:1016
float progress
Definition WM_types.hh:1019
BPy_StructRNA * depsgraph
long long int int64_t
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
int64_t size() const
static View & default_get()
Definition draw_view.cc:317
static bool do_merge_direct_indirect_eval(const Instance &inst)
static bool do_split_direct_indirect_radiance(const Instance &inst)
static const Vector< std::string > pass_to_render_pass_names(eViewLayerEEVEEPassType pass_type, const ViewLayer *view_layer)
VolumeProbeModule volume_probes
void render_frame(RenderEngine *engine, RenderLayer *render_layer, const char *view_name)
void draw(Manager &manager) final
SphereProbeModule sphere_probes
AmbientOcclusion ambient_occlusion
void info_append_i18n(const char *msg, Args &&...args)
SubsurfaceModule subsurface
void light_bake_irradiance(Object &probe, FunctionRef< void()> context_enable, FunctionRef< void()> context_disable, FunctionRef< bool()> stop, FunctionRef< void(LightProbeGridCacheFrame *, float progress)> result_update)
bool needs_lightprobe_sphere_passes() const
bool needs_planar_probe_passes() const
void object_sync(ObjectRef &ob_ref, Manager &manager) final
const RenderLayer * render_layer
const DRWContext * draw_ctx
const RegionView3D * rv3d
void store_metadata(RenderResult *render_result)
PlanarProbeModule planar_probes
static void update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)
bool is_loaded(ShaderGroups groups) const
bool do_lightprobe_sphere_sync() const
UniformDataModule uniform_data
LightProbeModule light_probes
MotionBlurModule motion_blur
void init_light_bake(Depsgraph *depsgraph, draw::Manager *manager)
#define floorf(x)
const DRWContext * DRW_context_get()
void DRW_custom_pipeline_begin(DRWContext &draw_ctx, Depsgraph *)
void DRW_render_object_iter(RenderEngine *engine, Depsgraph *depsgraph, std::function< void(blender::draw::ObjectRef &, RenderEngine *, Depsgraph *)> callback)
bool DRW_object_is_renderable(const Object *ob)
int DRW_object_visibility_in_active_context(const Object *ob)
void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, float subframe)
void DRW_custom_pipeline_end(DRWContext &draw_ctx)
void DRW_viewport_request_redraw()
blender::draw::Manager * DRW_manager_get()
#define CHECK_PASS_EEVEE(name, type, channels, chanid)
#define CHECK_PASS_LEGACY(name, type, channels, chanid)
#define printf(...)
void RE_engine_update_stats(RenderEngine *engine, const char *stats, const char *info)
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_update_progress(RenderEngine *engine, float progress)
MINLINE float fractf(float a)
#define G(x, y, z)
void foreach_hair_particle_handle(ObjectRef &ob_ref, ObjectHandle ob_handle, HairHandleCallback callback)
bool assign_if_different(T &old_value, T new_value)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
void RE_pass_set_buffer_data(RenderPass *pass, float *data)
#define min(a, b)
Definition sort.cc:36
RenderPass * RE_pass_find_by_name(RenderLayer *rl, const char *name, const char *viewname)
GPUFrameBuffer * default_fb
char info[GPU_INFO_SIZE]
Definition DRW_render.hh:70
ImBufFloatBuffer float_buffer
struct ImBuf * ibuf
Definition RE_pipeline.h:60
float xmin
float ymin
int ymin
int ymax
int xmin
int xmax
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251