Blender V5.0
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 "CLG_log.h"
12
13#include "BKE_global.hh"
14#include "BKE_object.hh"
15
16#include "BLI_rect.h"
17#include "BLI_time.h"
18
19#include "BLT_translation.hh"
20
22
24#include "DNA_modifier_types.h"
25
26#include "ED_screen.hh"
27#include "ED_view3d.hh"
28#include "GPU_context.hh"
29#include "GPU_pass.hh"
30#include "IMB_imbuf_types.hh"
31
32#include "RE_pipeline.h"
33
34#include "eevee_instance.hh"
35
36#include "DNA_particle_types.h"
37
39#include "draw_debug.hh"
40#include "draw_view_data.hh"
41
42namespace blender::eevee {
43
44CLG_LogRef Instance::log = {"eevee"};
45
46void *Instance::debug_scope_render_sample = nullptr;
47void *Instance::debug_scope_irradiance_setup = nullptr;
48void *Instance::debug_scope_irradiance_sample = nullptr;
49
50/* -------------------------------------------------------------------- */
59
61{
62 this->draw_ctx = DRW_context_get();
63
64 Depsgraph *depsgraph = draw_ctx->depsgraph;
65 Scene *scene = draw_ctx->scene;
66 View3D *v3d = draw_ctx->v3d;
67 ARegion *region = draw_ctx->region;
68 RegionView3D *rv3d = draw_ctx->rv3d;
69
70 DefaultTextureList *dtxl = draw_ctx->viewport_texture_list_get();
72
73 draw::View &default_view = draw::View::default_get();
74
75 Object *camera = nullptr;
76 /* Get render borders. */
77 rcti rect;
78 BLI_rcti_init(&rect, 0, size[0], 0, size[1]);
79 rcti visible_rect = rect;
80 if (v3d) {
81 if (rv3d && (rv3d->persp == RV3D_CAMOB)) {
82 camera = v3d->camera;
83 }
84
85 if (camera) {
86 rctf default_border;
87 BLI_rctf_init(&default_border, 0.0f, 1.0f, 0.0f, 1.0f);
88 bool is_default_border = BLI_rctf_compare(&scene->r.border, &default_border, 0.0f);
89 bool use_border = scene->r.mode & R_BORDER;
90 if (!is_default_border && use_border) {
91 rctf viewborder;
92 /* TODO(fclem) Might be better to get it from DRW. */
93 ED_view3d_calc_camera_border(scene, depsgraph, region, v3d, rv3d, false, &viewborder);
94 float viewborder_sizex = BLI_rctf_size_x(&viewborder);
95 float viewborder_sizey = BLI_rctf_size_y(&viewborder);
96 rect.xmin = floorf(viewborder.xmin + (scene->r.border.xmin * viewborder_sizex));
97 rect.ymin = floorf(viewborder.ymin + (scene->r.border.ymin * viewborder_sizey));
98 rect.xmax = floorf(viewborder.xmin + (scene->r.border.xmax * viewborder_sizex));
99 rect.ymax = floorf(viewborder.ymin + (scene->r.border.ymax * viewborder_sizey));
100 /* Clamp it to the viewport area. */
101 rect.xmin = max(rect.xmin, 0);
102 rect.ymin = max(rect.ymin, 0);
103 rect.xmax = min(rect.xmax, size.x);
104 rect.ymax = min(rect.ymax, size.y);
105 }
106 }
107 else if (v3d->flag2 & V3D_RENDER_BORDER) {
108 rect.xmin = v3d->render_border.xmin * size[0];
109 rect.ymin = v3d->render_border.ymin * size[1];
110 rect.xmax = v3d->render_border.xmax * size[0];
111 rect.ymax = v3d->render_border.ymax * size[1];
112 }
113
114 if (draw_ctx->is_viewport_image_render()) {
115 const float2 vp_size = draw_ctx->viewport_size_get();
116 visible_rect.xmax = vp_size[0];
117 visible_rect.ymax = vp_size[1];
118 visible_rect.xmin = visible_rect.ymin = 0;
119 }
120 else {
121 visible_rect = *ED_region_visible_rect(region);
122 }
123 }
124
125 init(size, &rect, &visible_rect, nullptr, depsgraph, camera, nullptr, &default_view, v3d, rv3d);
126}
127
128void Instance::init(const int2 &output_res,
129 const rcti *output_rect,
130 const rcti *visible_rect,
131 RenderEngine *render_,
132 Depsgraph *depsgraph_,
133 Object *camera_object_,
134 const RenderLayer *render_layer_,
135 View *drw_view_,
136 const View3D *v3d_,
137 const RegionView3D *rv3d_)
138{
139 this->draw_ctx = DRW_context_get();
140
141 render = render_;
142 depsgraph = depsgraph_;
143 camera_orig_object = camera_object_;
144 render_layer = render_layer_;
145 drw_view = drw_view_;
146 v3d = v3d_;
147 rv3d = rv3d_;
149 update_eval_members();
150
151 info_ = "";
152
153 if (is_viewport()) {
154 is_image_render = draw_ctx->is_image_render();
155 is_viewport_image_render = draw_ctx->is_viewport_image_render();
156 is_viewport_compositor_enabled = draw_ctx->is_viewport_compositor_enabled();
157 is_playback = draw_ctx->is_playback();
158 is_navigating = draw_ctx->is_navigating();
159 is_painting = draw_ctx->is_painting();
160 is_transforming = draw_ctx->is_transforming();
161 draw_overlays = v3d && (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
162
163 /* Note: Do not update the value here as we use it during sync for checking ID updates. */
164 if (depsgraph_last_update_ != DEG_get_update_count(depsgraph)) {
165 sampling.reset();
166 }
167 if (assign_if_different(debug_mode, (eDebugMode)G.debug_value)) {
168 sampling.reset();
169 }
170 if (output_res != film.display_extent_get()) {
171 sampling.reset();
172 }
173 if (output_rect) {
174 int2 offset = int2(output_rect->xmin, output_rect->ymin);
175 int2 extent = int2(BLI_rcti_size_x(output_rect), BLI_rcti_size_y(output_rect));
176 if (offset != film.get_data().offset || extent != film.get_data().extent) {
177 sampling.reset();
178 }
179 }
180 if (assign_if_different(overlays_enabled_, v3d && !(v3d->flag2 & V3D_HIDE_OVERLAYS))) {
181 sampling.reset();
182 }
183 if (is_painting) {
184 sampling.reset();
185 }
187 sampling.reset();
188 }
189 }
190 else {
191 is_image_render = true;
192 }
193
194 sampling.init(scene);
195 camera.init();
196 film.init(output_res, output_rect);
197 render_buffers.init();
198 ambient_occlusion.init();
199 velocity.init();
200 raytracing.init();
201 depth_of_field.init();
202 shadows.init();
203 motion_blur.init();
204 main_view.init();
205 light_probes.init();
206 planar_probes.init();
207 /* Irradiance Cache needs reflection probes to be initialized. */
208 sphere_probes.init();
209 volume_probes.init();
210 volume.init();
211 lookdev.init(visible_rect);
212
213 /* Request static shaders */
217 SET_FLAG_FROM_TEST(shader_request, depth_of_field.enabled(), DEPTH_OF_FIELD_SHADERS);
220 SET_FLAG_FROM_TEST(shader_request, motion_blur.postfx_enabled(), MOTION_BLUR_SHADERS);
221 SET_FLAG_FROM_TEST(shader_request, raytracing.use_fast_gi(), HORIZON_SCAN_SHADERS);
222 SET_FLAG_FROM_TEST(shader_request, raytracing.use_raytracing(), RAYTRACING_SHADERS);
223
225 loaded_shaders |= shaders.static_shaders_load_async(shader_request);
226 loaded_shaders |= materials.default_materials_load_async();
227
228 if (is_image_render) {
229 /* Ensure all deferred shaders have been compiled to kick-start asynchronous specialization. */
230 loaded_shaders |= shaders.static_shaders_wait_ready(DEFERRED_LIGHTING_SHADERS);
231 }
232
234 bool ready = shaders.request_specializations(
236 render_buffers.data.shadow_id,
237 shadows.get_data().ray_count,
238 shadows.get_data().step_count,
242 }
243
244 if (is_image_render) {
245 loaded_shaders |= shaders.static_shaders_wait_ready(shader_request);
246 loaded_shaders |= materials.default_materials_wait_ready();
247 }
248
249 /* Needed bits to be able to display something to the screen. */
250 needed_shaders = shader_request | DEFAULT_MATERIALS;
251
252 skip_render_ = !is_loaded(needed_shaders) || !film.is_valid_render_extent();
253}
254
256{
257 this->depsgraph = depsgraph;
258 this->manager = manager;
259 camera_orig_object = nullptr;
260 render = nullptr;
261 render_layer = nullptr;
262 drw_view = nullptr;
263 v3d = nullptr;
264 rv3d = nullptr;
265 update_eval_members();
266
267 is_light_bake = true;
268 debug_mode = (eDebugMode)G.debug_value;
269 info_ = "";
270
271 sampling.init(scene);
272 camera.init();
273 /* Film isn't used but init to avoid side effects in other module. */
274 rcti empty_rect{0, 0, 0, 0};
275 film.init(int2(1), &empty_rect);
276 render_buffers.init();
277 ambient_occlusion.init();
278 velocity.init();
279 raytracing.init();
280 depth_of_field.init();
281 shadows.init();
282 motion_blur.init();
283 main_view.init();
284 light_probes.init();
285 planar_probes.init();
286 /* Irradiance Cache needs reflection probes to be initialized. */
287 sphere_probes.init();
288 volume_probes.init();
289 volume.init();
290 lookdev.init(&empty_rect);
291
293 shaders.static_shaders_load_async(needed_shaders);
294 shaders.static_shaders_wait_ready(needed_shaders);
295}
296
297void Instance::set_time(float time)
298{
301 update_eval_members();
302}
303
304void Instance::update_eval_members()
305{
309 nullptr;
310}
311
313
314/* -------------------------------------------------------------------- */
321
323{
324 /* Needs to be first for sun light parameters.
325 * Also not skipped to be able to request world shader.
326 * If engine shaders are not ready, will skip the pipeline sync. */
327 world.sync();
328
329 if (skip_render_) {
330 return;
331 }
332
333 materials.begin_sync();
334 velocity.begin_sync(); /* NOTE: Also syncs camera. */
335 lights.begin_sync();
336 shadows.begin_sync();
337 volume.begin_sync();
338 pipelines.begin_sync();
339 cryptomatte.begin_sync();
340 sphere_probes.begin_sync();
341 light_probes.begin_sync();
342
343 depth_of_field.sync();
344 raytracing.sync();
345 motion_blur.sync();
346 hiz_buffer.sync();
347 main_view.sync();
348 film.sync();
349 ambient_occlusion.sync();
350 volume_probes.sync();
351 lookdev.sync();
352
353 use_surfaces = (view_layer->layflag & SCE_LAY_SOLID) != 0;
354 use_curves = (view_layer->layflag & SCE_LAY_STRAND) != 0;
355 use_volumes = (view_layer->layflag & SCE_LAY_VOLUMES) != 0;
356
357 if (is_light_bake) {
358 /* Do not use render layer visibility during bake.
359 * NOTE: This is arbitrary and could be changed if needed. */
361 }
362
363 if (is_viewport() && velocity.camera_has_motion()) {
364 sampling.reset();
365 }
366}
367
368void Instance::object_sync(ObjectRef &ob_ref, Manager & /*manager*/)
369{
370 if (skip_render_) {
371 return;
372 }
373
374 Object *ob = ob_ref.object;
375 const bool is_renderable_type = ELEM(ob->type,
376 OB_CURVES,
378 OB_MESH,
380 OB_VOLUME,
381 OB_LAMP,
383 const int ob_visibility = DRW_object_visibility_in_active_context(ob);
384 const bool partsys_is_visible = (ob_visibility & OB_VISIBLE_PARTICLES) != 0 &&
385 (ob->type == OB_MESH);
386 const bool object_is_visible = DRW_object_is_renderable(ob) &&
387 (ob_visibility & OB_VISIBLE_SELF) != 0;
388
389 if (!is_renderable_type || (!partsys_is_visible && !object_is_visible)) {
390 return;
391 }
392
393 ObjectHandle &ob_handle = sync.sync_object(ob_ref);
394
395 if (partsys_is_visible && ob != draw_ctx->object_edit) {
396 auto sync_hair =
397 [&](ObjectHandle hair_handle, ModifierData &md, ParticleSystem &particle_sys) {
398 ResourceHandleRange _res_handle = manager->resource_handle_for_psys(
399 ob_ref, ob->object_to_world());
400 sync.sync_curves(ob, hair_handle, ob_ref, _res_handle, &md, &particle_sys);
401 };
402 foreach_hair_particle_handle(*this, ob_ref, ob_handle, sync_hair);
403 }
404
405 if (object_is_visible) {
406 switch (ob->type) {
407 case OB_LAMP:
408 lights.sync_light(ob, ob_handle);
409 break;
410 case OB_MESH:
411 if (!sync.sync_sculpt(ob, ob_handle, ob_ref)) {
412 sync.sync_mesh(ob, ob_handle, ob_ref);
413 }
414 break;
415 case OB_POINTCLOUD:
416 sync.sync_pointcloud(ob, ob_handle, ob_ref);
417 break;
418 case OB_VOLUME:
419 sync.sync_volume(ob, ob_handle, ob_ref);
420 break;
421 case OB_CURVES:
422 sync.sync_curves(ob, ob_handle, ob_ref);
423 break;
424 case OB_LIGHTPROBE:
425 light_probes.sync_probe(ob, ob_handle);
426 break;
427 default:
428 break;
429 }
430 }
431}
432
434{
435 if (skip_render_) {
436 /* We might run in the case where the next check sets skip_render_ to false after the
437 * begin_sync was skipped, which would call `end_sync` function with invalid data. */
438 return;
439 }
440
441 bool use_sss = pipelines.deferred.closure_bits_get() & CLOSURE_SSS;
442 bool use_volume = volume.will_enable();
443
444 ShaderGroups request_bits = NONE;
445 SET_FLAG_FROM_TEST(request_bits, use_sss, SUBSURFACE_SHADERS);
446 SET_FLAG_FROM_TEST(request_bits, use_volume, VOLUME_EVAL_SHADERS);
447 loaded_shaders |= shaders.static_shaders_load_async(request_bits);
448 needed_shaders |= request_bits;
449
450 if (is_image_render) {
451 loaded_shaders |= shaders.static_shaders_wait_ready(request_bits);
452 }
453
454 materials.end_sync();
455 velocity.end_sync();
456 volume.end_sync(); /* Needs to be before shadows. */
457 shadows.end_sync(); /* Needs to be before lights. */
458 lights.end_sync();
459 sampling.end_sync();
460 subsurface.end_sync();
461 film.end_sync();
462 cryptomatte.end_sync();
463 pipelines.end_sync();
464 light_probes.end_sync();
465 sphere_probes.end_sync();
466 planar_probes.end_sync();
467
468 uniform_data.push_update();
469
470 depsgraph_last_update_ = DEG_get_update_count(depsgraph);
471}
472
474{
475 manager->begin_sync();
476
477 begin_sync();
478
480 render, depsgraph, [this](blender::draw::ObjectRef &ob_ref, RenderEngine *, Depsgraph *) {
481 this->object_sync(ob_ref, *this->manager);
482 });
483
484 velocity.geometry_steps_fill();
485
486 end_sync();
487
488 manager->end_sync();
489}
490
492{
493 return sphere_probes.update_probes_this_sample_;
494}
495
497{
498 return (materials.queued_shaders_count == 0) && (materials.queued_textures_count == 0) &&
500}
501
503{
504 return planar_probes.update_probes_;
505}
506
508{
509 return (materials.queued_shaders_count == 0) && (materials.queued_textures_count == 0) &&
511}
512
514
515/* -------------------------------------------------------------------- */
518
519void Instance::render_sample()
520{
523 film.display();
526 return;
527 }
528
529 /* Motion blur may need to do re-sync after a certain number of sample. */
530 if (!is_viewport() && sampling.do_render_sync()) {
531 render_sync();
535 /* This may need to happen more than once, since actual materials may require more passes
536 * (eg. volume ones) than the fallback material used for queued passes. */
537 /* TODO(@pragma37): There seems to be an issue where multiple `step_object_sync` calls on the
538 * same step can cause mismatching `has_motion` values between sync. */
539 render_sync();
540 }
541 }
542
543 DebugScope debug_scope(debug_scope_render_sample, "EEVEE.render_sample");
544
545 {
546 /* Critical section. Potential gpu::Shader concurrent usage. */
548
549 sampling.step();
550
551 capture_view.render_world();
552 capture_view.render_probes();
553
554 main_view.render();
555
556 lookdev_view.render();
557
559 }
560 motion_blur.step();
561}
562
563void Instance::render_read_result(RenderLayer *render_layer, const char *view_name)
564{
565 eViewLayerEEVEEPassType pass_bits = film.enabled_passes_get();
566
567 for (auto i : IndexRange(EEVEE_RENDER_PASS_MAX_BIT + 1)) {
568 eViewLayerEEVEEPassType pass_type = eViewLayerEEVEEPassType(pass_bits & (1 << i));
569 if (pass_type == 0) {
570 continue;
571 }
572
573 Vector<std::string> pass_names = Film::pass_to_render_pass_names(pass_type, view_layer);
574 for (int64_t pass_offset : IndexRange(pass_names.size())) {
575 RenderPass *rp = RE_pass_find_by_name(
576 render_layer, pass_names[pass_offset].c_str(), view_name);
577 if (!rp) {
578 continue;
579 }
580 float *result = film.read_pass(pass_type, pass_offset);
581
582 if (result) {
583 BLI_mutex_lock(&render->update_render_passes_mutex);
584 /* WORKAROUND: We use texture read to avoid using a frame-buffer to get the render result.
585 * However, on some implementation, we need a buffer with a few extra bytes for the read to
586 * happen correctly (see #GLTexture::read()). So we need a custom memory allocation. */
587 /* Avoid `memcpy()`, replace the pointer directly. */
589 BLI_mutex_unlock(&render->update_render_passes_mutex);
590 }
591 }
592 }
593
594 /* AOVs. */
595 LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
596 if ((aov->flag & AOV_CONFLICT) != 0) {
597 continue;
598 }
599 RenderPass *rp = RE_pass_find_by_name(render_layer, aov->name, view_name);
600 if (!rp) {
601 continue;
602 }
603 float *result = film.read_aov(aov);
604
605 if (result) {
606 BLI_mutex_lock(&render->update_render_passes_mutex);
607 /* WORKAROUND: We use texture read to avoid using a frame-buffer to get the render result.
608 * However, on some implementation, we need a buffer with a few extra bytes for the read to
609 * happen correctly (see #GLTexture::read()). So we need a custom memory allocation. */
610 /* Avoid #memcpy(), replace the pointer directly. */
612 BLI_mutex_unlock(&render->update_render_passes_mutex);
613 }
614 }
615
616 /* The vector pass is initialized to weird values. Set it to neutral value if not rendered. */
617 if ((pass_bits & EEVEE_RENDER_PASS_VECTOR) == 0) {
618 for (const std::string &vector_pass_name :
620 {
621 RenderPass *vector_rp = RE_pass_find_by_name(
622 render_layer, vector_pass_name.c_str(), view_name);
623 if (vector_rp) {
624 memset(vector_rp->ibuf->float_buffer.data,
625 0,
626 sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
627 }
628 }
629 }
630}
631
633
634/* -------------------------------------------------------------------- */
637
638void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, const char *view_name)
639{
640 skip_render_ = skip_render_ || !is_loaded(needed_shaders);
641
642 if (skip_render_) {
643 if (!info_.empty()) {
644 RE_engine_set_error_message(engine, info_.c_str());
645 info_ = "";
646 }
647 return;
648 }
649 /* TODO: Break on RE_engine_test_break(engine) */
650 while (!sampling.finished()) {
651 this->render_sample();
652
653 if ((sampling.sample_index() == 1) || ((sampling.sample_index() % 25) == 0) ||
654 sampling.finished())
655 {
656 /* TODO: Use `fmt`. */
657 std::string re_info = "Rendering " + std::to_string(sampling.sample_index()) + " / " +
658 std::to_string(sampling.sample_count()) + " samples";
659 RE_engine_update_stats(engine, nullptr, re_info.c_str());
660 }
661
662 /* Perform render step between samples to allow
663 * flushing of freed GPUBackend resources. */
665 GPU_flush();
666 }
668
669#if 0
670 /* TODO(fclem) print progression. */
671 RE_engine_update_progress(engine, float(sampling.sample_index()) / float(sampling.sample_count()));
672 /* TODO(fclem): Does not currently work. But would be better to just display to 2D view like
673 * cycles does. */
674 if (G.background == false && first_read) {
675 /* Allow to preview the first sample. */
676 /* TODO(fclem): Might want to not do this during animation render to avoid too much stall. */
677 this->render_read_result(render_layer, view_name);
678 first_read = false;
680 /* Allow the 2D viewport to grab the ticket mutex to display the render. */
682 }
683#endif
684 }
685
686 this->film.cryptomatte_sort();
687
688 this->render_read_result(render_layer, view_name);
689
690 if (!info_.empty()) {
692 engine, RPT_("Errors during render. See the System Console for more info."));
693 printf("%s", info_.c_str());
694 info_ = "";
695 }
696}
697
699{
700 if (skip_render_ || !is_loaded(needed_shaders)) {
701 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
704 info_append_i18n("Compiling EEVEE engine shaders");
706 }
707 /* Do not swap if the velocity module didn't go through a full sync cycle. */
709 /* The velocity module can reference some gpu::Batch. Calling this function
710 * make sure we release these references and don't de-reference them later as
711 * they might have been freed. */
712 velocity.step_swap();
713 }
714 return;
715 }
716
717 render_sample();
718 velocity.step_swap();
719
721 this->film.write_viewport_compositor_passes();
722 }
723
724 /* Do not request redraw during viewport animation to lock the frame-rate to the animation
725 * playback rate. This is in order to preserve motion blur aspect and also to avoid TAA reset
726 * that can show flickering. */
727 if (!sampling.finished_viewport() && !is_playback) {
729 }
730
731 if (materials.queued_shaders_count > 0 || materials.queued_textures_count > 0) {
732 if (materials.queued_textures_count > 0) {
733 info_append_i18n("Loading textures ({} remaining)", materials.queued_textures_count);
734 }
735 if (materials.queued_shaders_count > 0) {
736 info_append_i18n("Compiling shaders ({} remaining)", materials.queued_shaders_count);
738 /* Only recommend subprocesses when there is known gain. */
742 {
744 "Setting Preferences > System > Shader Compilation Method to Subprocess might improve "
745 "compilation time.");
746 }
747 }
749 }
750 else if (materials.queued_optimize_shaders_count > 0) {
751 info_append_i18n("Optimizing shaders ({} remaining)", materials.queued_optimize_shaders_count);
752 }
753}
754
756{
757 if (skip_render_) {
758 return;
759 }
760
761 do {
762 /* Render at least once to blit the finished image. */
763 this->render_sample();
764 } while (!sampling.finished_viewport());
765 velocity.step_swap();
766
768 this->film.write_viewport_compositor_passes();
769 }
770}
771
772void Instance::draw(Manager & /*manager*/)
773{
776 }
777 else {
779 }
781 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
783}
784
786{
787 if (skip_render_) {
788 return;
789 }
790 cryptomatte.store_metadata(render_result);
791}
792
794{
796
797#define CHECK_PASS_LEGACY(name, type, channels, chanid) \
798 if (view_layer->passflag & (SCE_PASS_##name)) { \
799 RE_engine_register_pass( \
800 engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
801 } \
802 ((void)0)
803#define CHECK_PASS_EEVEE(name, type, channels, chanid) \
804 if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \
805 RE_engine_register_pass( \
806 engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
807 } \
808 ((void)0)
809
810 CHECK_PASS_LEGACY(DEPTH, SOCK_FLOAT, 1, "Z");
811 CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z");
812 CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ");
813 CHECK_PASS_LEGACY(POSITION, SOCK_VECTOR, 3, "XYZ");
815 CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB");
816 CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB");
817 CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB");
818 CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB");
819 CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB");
820 CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB");
821 CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB");
822 CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB");
823 CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB");
824 CHECK_PASS_EEVEE(TRANSPARENT, SOCK_RGBA, 4, "RGBA");
825
826 LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
827 if ((aov->flag & AOV_CONFLICT) != 0) {
828 continue;
829 }
830 switch (aov->type) {
831 case AOV_TYPE_COLOR:
832 RE_engine_register_pass(engine, scene, view_layer, aov->name, 4, "RGBA", SOCK_RGBA);
833 break;
834 case AOV_TYPE_VALUE:
835 RE_engine_register_pass(engine, scene, view_layer, aov->name, 1, "X", SOCK_FLOAT);
836 break;
837 default:
838 break;
839 }
840 }
841
842 /* NOTE: Name channels lowercase `rgba` so that compression rules check in OpenEXR DWA code uses
843 * lossless compression. Reportedly this naming is the only one which works good from the
844 * interoperability point of view. Using `xyzw` naming is not portable. */
845 auto register_cryptomatte_passes = [&](eViewLayerCryptomatteFlags cryptomatte_layer,
846 eViewLayerEEVEEPassType eevee_pass) {
847 if (view_layer->cryptomatte_flag & cryptomatte_layer) {
848 for (const std::string &pass_name : Film::pass_to_render_pass_names(eevee_pass, view_layer))
849 {
851 engine, scene, view_layer, pass_name.c_str(), 4, "rgba", SOCK_RGBA);
852 }
853 }
854 };
857 register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_MATERIAL,
859}
860
862 Object &probe,
863 FunctionRef<void()> context_enable,
864 FunctionRef<void()> context_disable,
865 FunctionRef<bool()> stop,
866 FunctionRef<void(LightProbeGridCacheFrame *, float progress)> result_update)
867{
869
871 this->draw_ctx = &draw_ctx;
872
873 auto custom_pipeline_wrapper = [&](FunctionRef<void()> callback) {
874 context_enable();
876 callback();
878 context_disable();
879 };
880
881 auto context_wrapper = [&](FunctionRef<void()> callback) {
882 context_enable();
883 callback();
884 context_disable();
885 };
886
887 volume_probes.bake.init(probe);
888
889 custom_pipeline_wrapper([&]() {
891 this->render_sync();
892 while ((materials.queued_shaders_count > 0) || (materials.queued_textures_count > 0)) {
895 /* This may need to happen more than once, since actual materials may require more passes
896 * (eg. volume ones) than the fallback material used for queued passes. */
897 /* TODO(@pragma37): There seems to be an issue where multiple `step_object_sync` calls on the
898 * same step can cause mismatching `has_motion` values between sync. */
899 render_sync();
900 }
901 /* Sampling module needs to be initialized to computing lighting. */
902 sampling.init(probe);
903 sampling.step();
904
905 {
906 /* Critical section. Potential gpu::Shader concurrent usage. */
908
909 DebugScope debug_scope(debug_scope_irradiance_setup, "EEVEE.irradiance_setup");
910
911 capture_view.render_world();
912
913 volume_probes.bake.surfels_create(probe);
914
915 if (volume_probes.bake.should_break()) {
917 return;
918 }
919
920 volume_probes.bake.surfels_lights_eval();
921
922 volume_probes.bake.clusters_build();
923 volume_probes.bake.irradiance_offset();
924
926 }
927
928 /* Avoid big setup job to be queued with the sampling commands. */
929 GPU_flush();
930 });
931
932 if (volume_probes.bake.should_break()) {
933 return;
934 }
935
936 sampling.init(probe);
937
938 /* Start with 1 sample and progressively ramp up. */
939 float time_per_sample_ms_smooth = 16.0f;
940 double last_update_timestamp = BLI_time_now_seconds();
941 while (!sampling.finished()) {
942 context_wrapper([&]() {
943 DebugScope debug_scope(debug_scope_irradiance_sample, "EEVEE.irradiance_sample");
944
945 int remaining_samples = sampling.sample_count() - sampling.sample_index();
946 /* In background mode, assume we don't need as much interactivity. */
947 int time_budget_ms = G.background ? 32 : 16;
948 /* Batch ray cast. Avoids too much overhead of the context switch. */
949 int sample_count_in_batch = ceilf(time_budget_ms / max(0.1f, time_per_sample_ms_smooth));
950 /* Avoid batching too many rays, keep system responsive in case of bad values. */
951 sample_count_in_batch = min_iii(32, sample_count_in_batch, remaining_samples);
952
953 CLOG_INFO(&Instance::log, "IrradianceBake: Casting %d rays.", sample_count_in_batch);
954
955 double time_it_begin_ms = BLI_time_now_seconds() * 1000.0;
956 for (int i = 0; i < sample_count_in_batch && !sampling.finished(); i++) {
957 sampling.step();
958 {
959 /* Critical section. Potential gpu::Shader concurrent usage. */
961
962 volume_probes.bake.raylists_build();
963 volume_probes.bake.propagate_light();
964 volume_probes.bake.irradiance_capture();
965
967 }
968 };
969 /* We use GPU_finish to take into account the GPU processing time. */
970 /* TODO(fclem): Could use timer queries to keep pipelining of GPU commands if that become a
971 * real bottleneck. */
972 GPU_finish();
973 double time_it_end_ms = BLI_time_now_seconds() * 1000.0;
974
975 float time_per_sample_ms = float(time_it_end_ms - time_it_begin_ms) / sample_count_in_batch;
976 /* Exponential average. */
977 time_per_sample_ms_smooth = interpolate(time_per_sample_ms_smooth, time_per_sample_ms, 0.7f);
978
979 if (sampling.finished()) {
980 result_update(volume_probes.bake.read_result_packed(), 1.0f);
981 }
982 else {
983 double time_since_last_update_ms = BLI_time_now_seconds() - last_update_timestamp;
984 /* Only readback every 1 second. This readback is relatively expensive. */
985 if (time_since_last_update_ms > 1.0) {
986 float progress = sampling.sample_index() / float(sampling.sample_count());
987 result_update(volume_probes.bake.read_result_unpacked(), progress);
988 last_update_timestamp = BLI_time_now_seconds();
989 }
990 }
991 });
992
993 if (stop()) {
994 return;
995 }
996 }
997}
998
1000
1001} // 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)
MINLINE int min_iii(int a, int b, int c)
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:693
void BLI_mutex_lock(ThreadMutex *mutex)
Definition threads.cc:345
void BLI_mutex_unlock(ThreadMutex *mutex)
Definition threads.cc:350
Platform independent time functions.
double BLI_time_now_seconds(void)
Definition time.cc:113
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define RPT_(msgid)
#define CLOG_INFO(clg_ref,...)
Definition CLG_log.h:190
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)
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
@ V3D_HIDE_OVERLAYS
@ V3D_RENDER_BORDER
@ RV3D_CAMOB
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:4301
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)
GPUBackendType GPU_backend_get_type()
void GPU_framebuffer_viewport_reset(blender::gpu::FrameBuffer *fb)
void GPU_framebuffer_clear_color_depth(blender::gpu::FrameBuffer *fb, const float clear_col[4], float clear_depth)
void GPU_pass_cache_wait_for_all()
Definition gpu_pass.cc:308
@ GPU_DEVICE_ATI
@ GPU_DEVICE_NVIDIA
@ GPU_DEVICE_INTEL
bool GPU_type_matches(GPUDeviceType device, GPUOSType os, GPUDriverType driver)
@ GPU_DRIVER_ANY
@ GPU_DRIVER_OFFICIAL
@ GPU_OS_WIN
@ GPU_OS_ANY
void GPU_flush()
Definition gpu_state.cc:305
void GPU_finish()
Definition gpu_state.cc:310
int GPU_texture_height(const blender::gpu::Texture *texture)
int GPU_texture_width(const blender::gpu::Texture *texture)
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)
nullptr float
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()
Simple API to draw debug shapes and log in the viewport.
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)
#define G(x, y, z)
void drw_debug_clear()
Definition draw_debug.cc:78
void foreach_hair_particle_handle(Instance &inst, ObjectRef &ob_ref, ObjectHandle ob_handle, HairHandleCallback callback)
T interpolate(const T &a, const T &b, const FactorT &t)
bool assign_if_different(T &old_value, T new_value)
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
VecBase< float, 2 > float2
#define floorf
#define fractf
#define ceilf
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)
blender::gpu::FrameBuffer * default_fb
blender::gpu::Texture * color
char info[GPU_INFO_SIZE]
Definition DRW_render.hh:72
ImBufFloatBuffer float_buffer
struct ImBuf * ibuf
Definition RE_pipeline.h:67
float xmin
float ymin
int ymin
int ymax
int xmin
int xmax
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251