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_playback = draw_ctx->is_playback();
155 is_navigating = draw_ctx->is_navigating();
156 is_painting = draw_ctx->is_painting();
157 is_transforming = draw_ctx->is_transforming();
158 draw_overlays = v3d && (v3d->flag2 & V3D_HIDE_OVERLAYS) == 0;
159
160 /* Note: Do not update the value here as we use it during sync for checking ID updates. */
161 if (depsgraph_last_update_ != DEG_get_update_count(depsgraph)) {
162 sampling.reset();
163 }
165 draw_ctx->is_viewport_compositor_enabled()))
166 {
167 sampling.reset();
168 }
169 if (assign_if_different(debug_mode, (eDebugMode)G.debug_value)) {
170 sampling.reset();
171 }
172 if (output_res != film.display_extent_get()) {
173 sampling.reset();
174 }
175 if (output_rect) {
176 int2 offset = int2(output_rect->xmin, output_rect->ymin);
177 int2 extent = int2(BLI_rcti_size_x(output_rect), BLI_rcti_size_y(output_rect));
178 if (offset != film.get_data().offset || extent != film.get_data().extent) {
179 sampling.reset();
180 }
181 }
182 if (assign_if_different(overlays_enabled_, v3d && !(v3d->flag2 & V3D_HIDE_OVERLAYS))) {
183 sampling.reset();
184 }
185 if (is_painting) {
186 sampling.reset();
187 }
189 sampling.reset();
190 }
191 }
192 else {
193 is_image_render = true;
194 }
195
196 sampling.init(scene);
197 camera.init();
198 film.init(output_res, output_rect);
199 render_buffers.init();
200 ambient_occlusion.init();
201 velocity.init();
202 raytracing.init();
203 depth_of_field.init();
204 shadows.init();
205 motion_blur.init();
206 main_view.init();
207 light_probes.init();
208 planar_probes.init();
209 /* Irradiance Cache needs reflection probes to be initialized. */
210 sphere_probes.init();
211 volume_probes.init();
212 volume.init();
213 lookdev.init(visible_rect);
214
215 /* Request static shaders */
219 SET_FLAG_FROM_TEST(shader_request, depth_of_field.enabled(), DEPTH_OF_FIELD_SHADERS);
222 SET_FLAG_FROM_TEST(shader_request, motion_blur.postfx_enabled(), MOTION_BLUR_SHADERS);
223 SET_FLAG_FROM_TEST(shader_request, raytracing.use_fast_gi(), HORIZON_SCAN_SHADERS);
224 SET_FLAG_FROM_TEST(shader_request, raytracing.use_raytracing(), RAYTRACING_SHADERS);
225
227 loaded_shaders |= shaders.static_shaders_load_async(shader_request);
228 loaded_shaders |= materials.default_materials_load_async();
229
230 if (is_image_render) {
231 /* Ensure all deferred shaders have been compiled to kick-start asynchronous specialization. */
232 loaded_shaders |= shaders.static_shaders_wait_ready(DEFERRED_LIGHTING_SHADERS);
233 }
234
236 bool ready = shaders.request_specializations(
238 render_buffers.data.shadow_id,
239 shadows.get_data().ray_count,
240 shadows.get_data().step_count,
244 }
245
246 if (is_image_render) {
247 loaded_shaders |= shaders.static_shaders_wait_ready(shader_request);
248 loaded_shaders |= materials.default_materials_wait_ready();
249 }
250
251 /* Needed bits to be able to display something to the screen. */
252 needed_shaders = shader_request | DEFAULT_MATERIALS;
253
254 skip_render_ = !is_loaded(needed_shaders) || !film.is_valid_render_extent();
255}
256
258{
259 this->depsgraph = depsgraph;
260 this->manager = manager;
261 camera_orig_object = nullptr;
262 render = nullptr;
263 render_layer = nullptr;
264 drw_view = nullptr;
265 v3d = nullptr;
266 rv3d = nullptr;
267 update_eval_members();
268
269 is_light_bake = true;
270 debug_mode = (eDebugMode)G.debug_value;
271 info_ = "";
272
273 sampling.init(scene);
274 camera.init();
275 /* Film isn't used but init to avoid side effects in other module. */
276 rcti empty_rect{0, 0, 0, 0};
277 film.init(int2(1), &empty_rect);
278 render_buffers.init();
279 velocity.init();
280 depth_of_field.init();
281 shadows.init();
282 main_view.init();
283 light_probes.init();
284 planar_probes.init();
285 /* Irradiance Cache needs reflection probes to be initialized. */
286 sphere_probes.init();
287 volume_probes.init();
288 volume.init();
289 lookdev.init(&empty_rect);
290
292 shaders.static_shaders_load_async(needed_shaders);
293 shaders.static_shaders_wait_ready(needed_shaders);
294}
295
296void Instance::set_time(float time)
297{
300 update_eval_members();
301}
302
303void Instance::update_eval_members()
304{
308 nullptr;
309}
310
312
313/* -------------------------------------------------------------------- */
320
322{
323 /* Needs to be first for sun light parameters.
324 * Also not skipped to be able to request world shader.
325 * If engine shaders are not ready, will skip the pipeline sync. */
326 world.sync();
327
328 if (skip_render_) {
329 return;
330 }
331
332 materials.begin_sync();
333 velocity.begin_sync(); /* NOTE: Also syncs camera. */
334 lights.begin_sync();
335 shadows.begin_sync();
336 volume.begin_sync();
337 pipelines.begin_sync();
338 cryptomatte.begin_sync();
339 sphere_probes.begin_sync();
340 light_probes.begin_sync();
341
342 depth_of_field.sync();
343 raytracing.sync();
344 motion_blur.sync();
345 hiz_buffer.sync();
346 main_view.sync();
347 film.sync();
348 ambient_occlusion.sync();
349 volume_probes.sync();
350 lookdev.sync();
351
352 use_surfaces = (view_layer->layflag & SCE_LAY_SOLID) != 0;
353 use_curves = (view_layer->layflag & SCE_LAY_STRAND) != 0;
354 use_volumes = (view_layer->layflag & SCE_LAY_VOLUMES) != 0;
355
356 if (is_light_bake) {
357 /* Do not use render layer visibility during bake.
358 * NOTE: This is arbitrary and could be changed if needed. */
360 }
361
362 if (is_viewport() && velocity.camera_has_motion()) {
363 sampling.reset();
364 }
365}
366
367void Instance::object_sync(ObjectRef &ob_ref, Manager & /*manager*/)
368{
369 if (skip_render_) {
370 return;
371 }
372
373 Object *ob = ob_ref.object;
374 const bool is_renderable_type = ELEM(ob->type,
375 OB_CURVES,
377 OB_MESH,
379 OB_VOLUME,
380 OB_LAMP,
382 const int ob_visibility = DRW_object_visibility_in_active_context(ob);
383 const bool partsys_is_visible = (ob_visibility & OB_VISIBLE_PARTICLES) != 0 &&
384 (ob->type == OB_MESH);
385 const bool object_is_visible = DRW_object_is_renderable(ob) &&
386 (ob_visibility & OB_VISIBLE_SELF) != 0;
387
388 if (!is_renderable_type || (!partsys_is_visible && !object_is_visible)) {
389 return;
390 }
391
392 ObjectHandle &ob_handle = sync.sync_object(ob_ref);
393
394 if (partsys_is_visible && ob != draw_ctx->object_edit) {
395 auto sync_hair =
396 [&](ObjectHandle hair_handle, ModifierData &md, ParticleSystem &particle_sys) {
397 ResourceHandle _res_handle = manager->resource_handle_for_psys(ob_ref,
398 ob->object_to_world());
399 sync.sync_curves(ob, hair_handle, ob_ref, _res_handle, &md, &particle_sys);
400 };
401 foreach_hair_particle_handle(ob_ref, ob_handle, sync_hair);
402 }
403
404 if (object_is_visible) {
405 switch (ob->type) {
406 case OB_LAMP:
407 lights.sync_light(ob, ob_handle);
408 break;
409 case OB_MESH:
410 if (!sync.sync_sculpt(ob, ob_handle, ob_ref)) {
411 sync.sync_mesh(ob, ob_handle, ob_ref);
412 }
413 break;
414 case OB_POINTCLOUD:
415 sync.sync_pointcloud(ob, ob_handle, ob_ref);
416 break;
417 case OB_VOLUME:
418 sync.sync_volume(ob, ob_handle, ob_ref);
419 break;
420 case OB_CURVES:
421 sync.sync_curves(ob, ob_handle, ob_ref);
422 break;
423 case OB_LIGHTPROBE:
424 light_probes.sync_probe(ob, ob_handle);
425 break;
426 default:
427 break;
428 }
429 }
430}
431
433{
434 if (skip_render_) {
435 /* We might run in the case where the next check sets skip_render_ to false after the
436 * begin_sync was skipped, which would call `end_sync` function with invalid data. */
437 return;
438 }
439
440 bool use_sss = pipelines.deferred.closure_bits_get() & CLOSURE_SSS;
441 bool use_volume = volume.will_enable();
442
443 ShaderGroups request_bits = NONE;
444 SET_FLAG_FROM_TEST(request_bits, use_sss, SUBSURFACE_SHADERS);
445 SET_FLAG_FROM_TEST(request_bits, use_volume, VOLUME_EVAL_SHADERS);
446 loaded_shaders |= shaders.static_shaders_load_async(request_bits);
447 needed_shaders |= request_bits;
448
449 if (is_image_render) {
450 loaded_shaders |= shaders.static_shaders_wait_ready(request_bits);
451 }
452
453 materials.end_sync();
454 velocity.end_sync();
455 volume.end_sync(); /* Needs to be before shadows. */
456 shadows.end_sync(); /* Needs to be before lights. */
457 lights.end_sync();
458 sampling.end_sync();
459 subsurface.end_sync();
460 film.end_sync();
461 cryptomatte.end_sync();
462 pipelines.end_sync();
463 light_probes.end_sync();
464 sphere_probes.end_sync();
465 planar_probes.end_sync();
466
467 uniform_data.push_update();
468
469 depsgraph_last_update_ = DEG_get_update_count(depsgraph);
470}
471
473{
474 manager->begin_sync();
475
476 begin_sync();
477
479 render, depsgraph, [this](blender::draw::ObjectRef &ob_ref, RenderEngine *, Depsgraph *) {
480 this->object_sync(ob_ref, *this->manager);
481 });
482
483 velocity.geometry_steps_fill();
484
485 end_sync();
486
487 manager->end_sync();
488}
489
491{
492 return sphere_probes.update_probes_this_sample_;
493}
494
496{
497 return (materials.queued_shaders_count == 0) && (materials.queued_textures_count == 0) &&
499}
500
502{
503 return planar_probes.update_probes_;
504}
505
507{
508 return (materials.queued_shaders_count == 0) && (materials.queued_textures_count == 0) &&
510}
511
513
514/* -------------------------------------------------------------------- */
517
518void Instance::render_sample()
519{
522 film.display();
525 return;
526 }
527
528 /* Motion blur may need to do re-sync after a certain number of sample. */
529 if (!is_viewport() && sampling.do_render_sync()) {
530 render_sync();
534 /* This may need to happen more than once, since actual materials may require more passes
535 * (eg. volume ones) than the fallback material used for queued passes. */
536 /* TODO(@pragma37): There seems to be an issue where multiple `step_object_sync` calls on the
537 * same step can cause mismatching `has_motion` values between sync. */
538 render_sync();
539 }
540 }
541
542 DebugScope debug_scope(debug_scope_render_sample, "EEVEE.render_sample");
543
544 {
545 /* Critical section. Potential GPUShader concurrent usage. */
547
548 sampling.step();
549
550 capture_view.render_world();
551 capture_view.render_probes();
552
553 main_view.render();
554
555 lookdev_view.render();
556
558 }
559 motion_blur.step();
560}
561
562void Instance::render_read_result(RenderLayer *render_layer, const char *view_name)
563{
564 eViewLayerEEVEEPassType pass_bits = film.enabled_passes_get();
565
566 for (auto i : IndexRange(EEVEE_RENDER_PASS_MAX_BIT + 1)) {
567 eViewLayerEEVEEPassType pass_type = eViewLayerEEVEEPassType(pass_bits & (1 << i));
568 if (pass_type == 0) {
569 continue;
570 }
571
572 Vector<std::string> pass_names = Film::pass_to_render_pass_names(pass_type, view_layer);
573 for (int64_t pass_offset : IndexRange(pass_names.size())) {
574 RenderPass *rp = RE_pass_find_by_name(
575 render_layer, pass_names[pass_offset].c_str(), view_name);
576 if (!rp) {
577 continue;
578 }
579 float *result = film.read_pass(pass_type, pass_offset);
580
581 if (result) {
582 BLI_mutex_lock(&render->update_render_passes_mutex);
583 /* WORKAROUND: We use texture read to avoid using a frame-buffer to get the render result.
584 * However, on some implementation, we need a buffer with a few extra bytes for the read to
585 * happen correctly (see #GLTexture::read()). So we need a custom memory allocation. */
586 /* Avoid `memcpy()`, replace the pointer directly. */
588 BLI_mutex_unlock(&render->update_render_passes_mutex);
589 }
590 }
591 }
592
593 /* AOVs. */
594 LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
595 if ((aov->flag & AOV_CONFLICT) != 0) {
596 continue;
597 }
598 RenderPass *rp = RE_pass_find_by_name(render_layer, aov->name, view_name);
599 if (!rp) {
600 continue;
601 }
602 float *result = film.read_aov(aov);
603
604 if (result) {
605 BLI_mutex_lock(&render->update_render_passes_mutex);
606 /* WORKAROUND: We use texture read to avoid using a frame-buffer to get the render result.
607 * However, on some implementation, we need a buffer with a few extra bytes for the read to
608 * happen correctly (see #GLTexture::read()). So we need a custom memory allocation. */
609 /* Avoid #memcpy(), replace the pointer directly. */
611 BLI_mutex_unlock(&render->update_render_passes_mutex);
612 }
613 }
614
615 /* The vector pass is initialized to weird values. Set it to neutral value if not rendered. */
616 if ((pass_bits & EEVEE_RENDER_PASS_VECTOR) == 0) {
617 for (const std::string &vector_pass_name :
619 {
620 RenderPass *vector_rp = RE_pass_find_by_name(
621 render_layer, vector_pass_name.c_str(), view_name);
622 if (vector_rp) {
623 memset(vector_rp->ibuf->float_buffer.data,
624 0,
625 sizeof(float) * 4 * vector_rp->rectx * vector_rp->recty);
626 }
627 }
628 }
629}
630
632
633/* -------------------------------------------------------------------- */
636
637void Instance::render_frame(RenderEngine *engine, RenderLayer *render_layer, const char *view_name)
638{
639 skip_render_ = skip_render_ || !is_loaded(needed_shaders);
640
641 if (skip_render_) {
642 if (!info_.empty()) {
643 RE_engine_set_error_message(engine, info_.c_str());
644 info_ = "";
645 }
646 return;
647 }
648 /* TODO: Break on RE_engine_test_break(engine) */
649 while (!sampling.finished()) {
650 this->render_sample();
651
652 if ((sampling.sample_index() == 1) || ((sampling.sample_index() % 25) == 0) ||
653 sampling.finished())
654 {
655 /* TODO: Use `fmt`. */
656 std::string re_info = "Rendering " + std::to_string(sampling.sample_index()) + " / " +
657 std::to_string(sampling.sample_count()) + " samples";
658 RE_engine_update_stats(engine, nullptr, re_info.c_str());
659 }
660
661 /* Perform render step between samples to allow
662 * flushing of freed GPUBackend resources. */
664 GPU_flush();
665 }
667
668#if 0
669 /* TODO(fclem) print progression. */
670 RE_engine_update_progress(engine, float(sampling.sample_index()) / float(sampling.sample_count()));
671 /* TODO(fclem): Does not currently work. But would be better to just display to 2D view like
672 * cycles does. */
673 if (G.background == false && first_read) {
674 /* Allow to preview the first sample. */
675 /* TODO(fclem): Might want to not do this during animation render to avoid too much stall. */
676 this->render_read_result(render_layer, view_name);
677 first_read = false;
679 /* Allow the 2D viewport to grab the ticket mutex to display the render. */
681 }
682#endif
683 }
684
685 this->film.cryptomatte_sort();
686
687 this->render_read_result(render_layer, view_name);
688
689 if (!info_.empty()) {
691 engine, RPT_("Errors during render. See the System Console for more info."));
692 printf("%s", info_.c_str());
693 info_ = "";
694 }
695}
696
698{
699 if (skip_render_ || !is_loaded(needed_shaders)) {
700 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
703 info_append_i18n("Compiling EEVEE engine shaders");
705 }
706 /* Do not swap if the velocity module didn't go through a full sync cycle. */
708 /* The velocity module can reference some gpu::Batch. Calling this function
709 * make sure we release these references and don't de-reference them later as
710 * they might have been freed. */
711 velocity.step_swap();
712 }
713 return;
714 }
715
716 render_sample();
717 velocity.step_swap();
718
720 this->film.write_viewport_compositor_passes();
721 }
722
723 /* Do not request redraw during viewport animation to lock the frame-rate to the animation
724 * playback rate. This is in order to preserve motion blur aspect and also to avoid TAA reset
725 * that can show flickering. */
726 if (!sampling.finished_viewport() && !is_playback) {
728 }
729
730 if (materials.queued_shaders_count > 0 || materials.queued_textures_count > 0) {
731 if (materials.queued_textures_count > 0) {
732 info_append_i18n("Loading textures ({} remaining)", materials.queued_textures_count);
733 }
734 if (materials.queued_shaders_count > 0) {
735 info_append_i18n("Compiling shaders ({} remaining)", materials.queued_shaders_count);
737 /* Only recommend subprocesses when there is known gain. */
741 {
743 "Setting Preferences > System > Shader Compilation Method to Subprocess might improve "
744 "compilation time.");
745 }
746 }
748 }
749 else if (materials.queued_optimize_shaders_count > 0) {
750 info_append_i18n("Optimizing shaders ({} remaining)", materials.queued_optimize_shaders_count);
751 }
752}
753
755{
756 if (skip_render_) {
757 return;
758 }
759
760 do {
761 /* Render at least once to blit the finished image. */
762 this->render_sample();
763 } while (!sampling.finished_viewport());
764 velocity.step_swap();
765
767 this->film.write_viewport_compositor_passes();
768 }
769}
770
771void Instance::draw(Manager & /*manager*/)
772{
775 }
776 else {
778 }
780 DefaultFramebufferList *dfbl = draw_ctx->viewport_framebuffer_list_get();
782}
783
785{
786 if (skip_render_) {
787 return;
788 }
789 cryptomatte.store_metadata(render_result);
790}
791
793{
795
796#define CHECK_PASS_LEGACY(name, type, channels, chanid) \
797 if (view_layer->passflag & (SCE_PASS_##name)) { \
798 RE_engine_register_pass( \
799 engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
800 } \
801 ((void)0)
802#define CHECK_PASS_EEVEE(name, type, channels, chanid) \
803 if (view_layer->eevee.render_passes & (EEVEE_RENDER_PASS_##name)) { \
804 RE_engine_register_pass( \
805 engine, scene, view_layer, RE_PASSNAME_##name, channels, chanid, type); \
806 } \
807 ((void)0)
808
810 CHECK_PASS_LEGACY(MIST, SOCK_FLOAT, 1, "Z");
811 CHECK_PASS_LEGACY(NORMAL, SOCK_VECTOR, 3, "XYZ");
812 CHECK_PASS_LEGACY(POSITION, SOCK_VECTOR, 3, "XYZ");
814 CHECK_PASS_LEGACY(DIFFUSE_DIRECT, SOCK_RGBA, 3, "RGB");
815 CHECK_PASS_LEGACY(DIFFUSE_COLOR, SOCK_RGBA, 3, "RGB");
816 CHECK_PASS_LEGACY(GLOSSY_DIRECT, SOCK_RGBA, 3, "RGB");
817 CHECK_PASS_LEGACY(GLOSSY_COLOR, SOCK_RGBA, 3, "RGB");
818 CHECK_PASS_EEVEE(VOLUME_LIGHT, SOCK_RGBA, 3, "RGB");
819 CHECK_PASS_LEGACY(EMIT, SOCK_RGBA, 3, "RGB");
820 CHECK_PASS_LEGACY(ENVIRONMENT, SOCK_RGBA, 3, "RGB");
821 CHECK_PASS_LEGACY(SHADOW, SOCK_RGBA, 3, "RGB");
822 CHECK_PASS_LEGACY(AO, SOCK_RGBA, 3, "RGB");
823 CHECK_PASS_EEVEE(TRANSPARENT, SOCK_RGBA, 4, "RGBA");
824
825 LISTBASE_FOREACH (ViewLayerAOV *, aov, &view_layer->aovs) {
826 if ((aov->flag & AOV_CONFLICT) != 0) {
827 continue;
828 }
829 switch (aov->type) {
830 case AOV_TYPE_COLOR:
831 RE_engine_register_pass(engine, scene, view_layer, aov->name, 4, "RGBA", SOCK_RGBA);
832 break;
833 case AOV_TYPE_VALUE:
834 RE_engine_register_pass(engine, scene, view_layer, aov->name, 1, "X", SOCK_FLOAT);
835 break;
836 default:
837 break;
838 }
839 }
840
841 /* NOTE: Name channels lowercase `rgba` so that compression rules check in OpenEXR DWA code uses
842 * lossless compression. Reportedly this naming is the only one which works good from the
843 * interoperability point of view. Using `xyzw` naming is not portable. */
844 auto register_cryptomatte_passes = [&](eViewLayerCryptomatteFlags cryptomatte_layer,
845 eViewLayerEEVEEPassType eevee_pass) {
846 if (view_layer->cryptomatte_flag & cryptomatte_layer) {
847 for (const std::string &pass_name : Film::pass_to_render_pass_names(eevee_pass, view_layer))
848 {
850 engine, scene, view_layer, pass_name.c_str(), 4, "rgba", SOCK_RGBA);
851 }
852 }
853 };
856 register_cryptomatte_passes(VIEW_LAYER_CRYPTOMATTE_MATERIAL,
858}
859
861 Object &probe,
862 FunctionRef<void()> context_enable,
863 FunctionRef<void()> context_disable,
864 FunctionRef<bool()> stop,
865 FunctionRef<void(LightProbeGridCacheFrame *, float progress)> result_update)
866{
868
870 this->draw_ctx = &draw_ctx;
871
872 auto custom_pipeline_wrapper = [&](FunctionRef<void()> callback) {
873 context_enable();
875 callback();
877 context_disable();
878 };
879
880 auto context_wrapper = [&](FunctionRef<void()> callback) {
881 context_enable();
882 callback();
883 context_disable();
884 };
885
886 volume_probes.bake.init(probe);
887
888 custom_pipeline_wrapper([&]() {
889 this->render_sync();
890 while ((materials.queued_shaders_count > 0) || (materials.queued_textures_count > 0)) {
893 /* This may need to happen more than once, since actual materials may require more passes
894 * (eg. volume ones) than the fallback material used for queued passes. */
895 /* TODO(@pragma37): There seems to be an issue where multiple `step_object_sync` calls on the
896 * same step can cause mismatching `has_motion` values between sync. */
897 render_sync();
898 }
899 /* Sampling module needs to be initialized to computing lighting. */
900 sampling.init(probe);
901 sampling.step();
902
903 {
904 /* Critical section. Potential GPUShader concurrent usage. */
906
907 DebugScope debug_scope(debug_scope_irradiance_setup, "EEVEE.irradiance_setup");
908
909 capture_view.render_world();
910
911 volume_probes.bake.surfels_create(probe);
912
913 if (volume_probes.bake.should_break()) {
915 return;
916 }
917
918 volume_probes.bake.surfels_lights_eval();
919
920 volume_probes.bake.clusters_build();
921 volume_probes.bake.irradiance_offset();
922
924 }
925 });
926
927 if (volume_probes.bake.should_break()) {
928 return;
929 }
930
931 sampling.init(probe);
932 while (!sampling.finished()) {
933 context_wrapper([&]() {
934 DebugScope debug_scope(debug_scope_irradiance_sample, "EEVEE.irradiance_sample");
935
936 /* Batch ray cast by pack of 16. Avoids too much overhead of the update function & context
937 * switch. */
938 /* TODO(fclem): Could make the number of iteration depend on the computation time. */
939 for (int i = 0; i < 16 && !sampling.finished(); i++) {
940 sampling.step();
941 {
942 /* Critical section. Potential GPUShader concurrent usage. */
944
945 volume_probes.bake.raylists_build();
946 volume_probes.bake.propagate_light();
947 volume_probes.bake.irradiance_capture();
948
950 }
951 }
952
953 LightProbeGridCacheFrame *cache_frame;
954 if (sampling.finished()) {
955 cache_frame = volume_probes.bake.read_result_packed();
956 }
957 else {
958 /* TODO(fclem): Only do this read-back if needed. But it might be tricky to know when. */
959 cache_frame = volume_probes.bake.read_result_unpacked();
960 }
961
962 float progress = sampling.sample_index() / float(sampling.sample_count());
963 result_update(cache_frame, progress);
964 });
965
966 if (stop()) {
967 return;
968 }
969 }
970}
971
973
974} // 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_EEVEE_SHADOW_JITTERED_VIEWPORT
@ R_BORDER
@ SCE_LAY_SOLID
@ SCE_LAY_STRAND
@ SCE_LAY_VOLUMES
@ 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:4118
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