From 7293c1b3578e015a00e8b1e282baa62f51c5b4c4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Nov 2021 19:34:13 +0100 Subject: Fix T93106: Cycles SSS not working with normals pointing inside --- intern/cycles/kernel/integrator/subsurface.h | 4 ++++ intern/cycles/kernel/integrator/subsurface_disk.h | 4 ++++ intern/cycles/kernel/types.h | 19 ++++++++++--------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/intern/cycles/kernel/integrator/subsurface.h b/intern/cycles/kernel/integrator/subsurface.h index 9010318257f..59b0cd2596c 100644 --- a/intern/cycles/kernel/integrator/subsurface.h +++ b/intern/cycles/kernel/integrator/subsurface.h @@ -71,6 +71,10 @@ ccl_device int subsurface_bounce(KernelGlobals kg, } # endif + if (sd->flag & SD_BACKFACING) { + path_flag |= PATH_RAY_SUBSURFACE_BACKFACING; + } + INTEGRATOR_STATE_WRITE(state, path, throughput) *= weight; INTEGRATOR_STATE_WRITE(state, path, flag) = path_flag; diff --git a/intern/cycles/kernel/integrator/subsurface_disk.h b/intern/cycles/kernel/integrator/subsurface_disk.h index 6146b8c41fc..22327268e02 100644 --- a/intern/cycles/kernel/integrator/subsurface_disk.h +++ b/intern/cycles/kernel/integrator/subsurface_disk.h @@ -47,6 +47,7 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const float time = INTEGRATOR_STATE(state, ray, time); const float3 Ng = INTEGRATOR_STATE(state, subsurface, Ng); const int object = INTEGRATOR_STATE(state, isect, object); + const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag); /* Read subsurface scattering parameters. */ const float3 radius = INTEGRATOR_STATE(state, subsurface, radius); @@ -123,6 +124,9 @@ ccl_device_inline bool subsurface_disk(KernelGlobals kg, const int object = ss_isect.hits[hit].object; const int object_flag = kernel_tex_fetch(__object_flag, object); float3 hit_Ng = ss_isect.Ng[hit]; + if (path_flag & PATH_RAY_SUBSURFACE_BACKFACING) { + hit_Ng = -hit_Ng; + } if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) { hit_Ng = -hit_Ng; } diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 01700add22b..cae514d4dbd 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -279,33 +279,34 @@ enum PathRayFlag { PATH_RAY_SUBSURFACE_RANDOM_WALK = (1U << 20U), PATH_RAY_SUBSURFACE_DISK = (1U << 21U), PATH_RAY_SUBSURFACE_USE_FRESNEL = (1U << 22U), + PATH_RAY_SUBSURFACE_BACKFACING = (1U << 23U), PATH_RAY_SUBSURFACE = (PATH_RAY_SUBSURFACE_RANDOM_WALK | PATH_RAY_SUBSURFACE_DISK | - PATH_RAY_SUBSURFACE_USE_FRESNEL), + PATH_RAY_SUBSURFACE_USE_FRESNEL | PATH_RAY_SUBSURFACE_BACKFACING), /* Contribute to denoising features. */ - PATH_RAY_DENOISING_FEATURES = (1U << 23U), + PATH_RAY_DENOISING_FEATURES = (1U << 24U), /* Render pass categories. */ - PATH_RAY_SURFACE_PASS = (1U << 24U), - PATH_RAY_VOLUME_PASS = (1U << 25U), + PATH_RAY_SURFACE_PASS = (1U << 25U), + PATH_RAY_VOLUME_PASS = (1U << 26U), PATH_RAY_ANY_PASS = (PATH_RAY_SURFACE_PASS | PATH_RAY_VOLUME_PASS), /* Shadow ray is for a light or surface, or AO. */ - PATH_RAY_SHADOW_FOR_LIGHT = (1U << 26U), - PATH_RAY_SHADOW_FOR_AO = (1U << 27U), + PATH_RAY_SHADOW_FOR_LIGHT = (1U << 27U), + PATH_RAY_SHADOW_FOR_AO = (1U << 28U), /* A shadow catcher object was hit and the path was split into two. */ - PATH_RAY_SHADOW_CATCHER_HIT = (1U << 28U), + PATH_RAY_SHADOW_CATCHER_HIT = (1U << 29U), /* A shadow catcher object was hit and this path traces only shadow catchers, writing them into * their dedicated pass for later division. * * NOTE: Is not covered with `PATH_RAY_ANY_PASS` because shadow catcher does special handling * which is separate from the light passes. */ - PATH_RAY_SHADOW_CATCHER_PASS = (1U << 29U), + PATH_RAY_SHADOW_CATCHER_PASS = (1U << 30U), /* Path is evaluating background for an approximate shadow catcher with non-transparent film. */ - PATH_RAY_SHADOW_CATCHER_BACKGROUND = (1U << 30U), + PATH_RAY_SHADOW_CATCHER_BACKGROUND = (1U << 31U), }; /* Configure ray visibility bits for rays and objects respectively, -- cgit v1.2.3 From cfd0e96e47ed34888077b989854ba5a557bac43b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Nov 2021 20:44:31 +0100 Subject: Fix T93125: Cycles wrong remaining render time with high number of samples Avoid integer overflow. --- intern/cycles/blender/session.cpp | 8 ++++---- intern/cycles/blender/session.h | 4 ++-- intern/cycles/integrator/path_trace.cpp | 3 ++- intern/cycles/session/session.cpp | 4 ++-- intern/cycles/util/progress.h | 4 ++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index b7fd862bffd..c786b29d442 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -129,7 +129,7 @@ void BlenderSession::create_session() /* reset status/progress */ last_status = ""; last_error = ""; - last_progress = -1.0f; + last_progress = -1.0; start_resize_time = 0.0; /* create session */ @@ -854,7 +854,7 @@ void BlenderSession::get_status(string &status, string &substatus) session->progress.get_status(status, substatus); } -void BlenderSession::get_progress(float &progress, double &total_time, double &render_time) +void BlenderSession::get_progress(double &progress, double &total_time, double &render_time) { session->progress.get_time(total_time, render_time); progress = session->progress.get_progress(); @@ -862,7 +862,7 @@ void BlenderSession::get_progress(float &progress, double &total_time, double &r void BlenderSession::update_bake_progress() { - float progress = session->progress.get_progress(); + double progress = session->progress.get_progress(); if (progress != last_progress) { b_engine.update_progress(progress); @@ -874,7 +874,7 @@ void BlenderSession::update_status_progress() { string timestatus, status, substatus; string scene_status = ""; - float progress; + double progress; double total_time, remaining_time = 0, render_time; float mem_used = (float)session->stats.mem_used / 1024.0f / 1024.0f; float mem_peak = (float)session->stats.mem_peak / 1024.0f / 1024.0f; diff --git a/intern/cycles/blender/session.h b/intern/cycles/blender/session.h index fa24b5f7467..f837e97c17c 100644 --- a/intern/cycles/blender/session.h +++ b/intern/cycles/blender/session.h @@ -82,7 +82,7 @@ class BlenderSession { void tag_redraw(); void tag_update(); void get_status(string &status, string &substatus); - void get_progress(float &progress, double &total_time, double &render_time); + void get_progress(double &progress, double &total_time, double &render_time); void test_cancel(); void update_status_progress(); void update_bake_progress(); @@ -108,7 +108,7 @@ class BlenderSession { string last_status; string last_error; - float last_progress; + double last_progress; double last_status_time; int width, height; diff --git a/intern/cycles/integrator/path_trace.cpp b/intern/cycles/integrator/path_trace.cpp index f3a08b1659c..92bf8e69d19 100644 --- a/intern/cycles/integrator/path_trace.cpp +++ b/intern/cycles/integrator/path_trace.cpp @@ -847,7 +847,8 @@ void PathTrace::progress_update_if_needed(const RenderWork &render_work) { if (progress_ != nullptr) { const int2 tile_size = get_render_tile_size(); - const int num_samples_added = tile_size.x * tile_size.y * render_work.path_trace.num_samples; + const uint64_t num_samples_added = uint64_t(tile_size.x) * tile_size.y * + render_work.path_trace.num_samples; const int current_sample = render_work.path_trace.start_sample + render_work.path_trace.num_samples; progress_->add_samples(num_samples_added, current_sample); diff --git a/intern/cycles/session/session.cpp b/intern/cycles/session/session.cpp index b228939689c..170af5c70b6 100644 --- a/intern/cycles/session/session.cpp +++ b/intern/cycles/session/session.cpp @@ -504,7 +504,7 @@ void Session::set_display_driver(unique_ptr driver) double Session::get_estimated_remaining_time() const { - const float completed = progress.get_progress(); + const double completed = progress.get_progress(); if (completed == 0.0f) { return 0.0; } @@ -573,7 +573,7 @@ void Session::update_status_time(bool show_pause, bool show_done) } /* Sample. */ - if (num_samples == Integrator::MAX_SAMPLES) { + if (!params.background && num_samples == Integrator::MAX_SAMPLES) { substatus = status_append(substatus, string_printf("Sample %d", current_sample)); } else { diff --git a/intern/cycles/util/progress.h b/intern/cycles/util/progress.h index 4b0ff08aa7e..f2d80e49ab8 100644 --- a/intern/cycles/util/progress.h +++ b/intern/cycles/util/progress.h @@ -200,12 +200,12 @@ class Progress { total_pixel_samples = total_pixel_samples_; } - float get_progress() const + double get_progress() const { thread_scoped_lock lock(progress_mutex); if (total_pixel_samples > 0) { - return ((float)pixel_samples) / total_pixel_samples; + return ((double)pixel_samples) / (double)total_pixel_samples; } return 0.0f; } -- cgit v1.2.3 From 25d30e6c99a2d89bf7babfacb24a8c8aa61b3b3b Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 Nov 2021 14:49:58 -0600 Subject: Fix T92857: Deadlock in geometry nodes curve multi-threading The spline code, especially Bezier splines, often make use of lazily evaluation and caching. In order to do that, they use mutex locks. When multi-threading, this can lead to problems. Further detail can be found in rBfcc844f8fbd0d1. To fix the deadlock, isolate the task before multi-threading when holding a lock. Differential Revision: https://developer.blender.org/D13229 --- source/blender/blenkernel/intern/spline_bezier.cc | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/spline_bezier.cc b/source/blender/blenkernel/intern/spline_bezier.cc index 166fe0f5464..18d195f19da 100644 --- a/source/blender/blenkernel/intern/spline_bezier.cc +++ b/source/blender/blenkernel/intern/spline_bezier.cc @@ -599,7 +599,10 @@ Span BezierSpline::evaluated_mappings() const Span offsets = this->control_point_offsets(); - calculate_mappings_linear_resolution(offsets, size, resolution_, is_cyclic_, mappings); + blender::threading::isolate_task([&]() { + /* Isolate the task, since this is function is multi-threaded and holds a lock. */ + calculate_mappings_linear_resolution(offsets, size, resolution_, is_cyclic_, mappings); + }); mapping_cache_dirty_ = false; return mappings; @@ -635,10 +638,13 @@ Span BezierSpline::evaluated_positions() const Span offsets = this->control_point_offsets(); const int grain_size = std::max(512 / resolution_, 1); - blender::threading::parallel_for(IndexRange(size - 1), grain_size, [&](IndexRange range) { - for (const int i : range) { - this->evaluate_segment(i, i + 1, positions.slice(offsets[i], offsets[i + 1] - offsets[i])); - } + blender::threading::isolate_task([&]() { + /* Isolate the task, since this is function is multi-threaded and holds a lock. */ + blender::threading::parallel_for(IndexRange(size - 1), grain_size, [&](IndexRange range) { + for (const int i : range) { + this->evaluate_segment(i, i + 1, positions.slice(offsets[i], offsets[i + 1] - offsets[i])); + } + }); }); if (is_cyclic_) { this->evaluate_segment( -- cgit v1.2.3 From f30e1fd2f0648d6c88bc61142ecc003ffa33ce11 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Tue, 16 Nov 2021 14:51:03 -0600 Subject: Fix T93085: Incorrect geometry nodes modifier warning It's valid for a node group connected to the modifier not to have a geometry input, but I didn't consider that case with the last change I made here, f3bdabbe24fe591dc9. Differential Revision: https://developer.blender.org/D13231 --- source/blender/modifiers/intern/MOD_nodes.cc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 70f6020f5a9..c1cdfa43920 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -1031,11 +1031,9 @@ static void check_property_socket_sync(const Object *ob, ModifierData *md) int i; LISTBASE_FOREACH_INDEX (const bNodeSocket *, socket, &nmd->node_group->inputs, i) { /* The first socket is the special geometry socket for the modifier object. */ - if (i == 0) { - if (socket->type == SOCK_GEOMETRY) { - continue; - } - BKE_modifier_set_error(ob, md, "The first node group input must be a geometry"); + if (i == 0 && socket->type == SOCK_GEOMETRY) { + geometry_socket_count++; + continue; } IDProperty *property = IDP_GetPropertyFromGroup(nmd->settings.properties, socket->identifier); @@ -1056,7 +1054,12 @@ static void check_property_socket_sync(const Object *ob, ModifierData *md) } } - if (geometry_socket_count > 1) { + if (geometry_socket_count == 1) { + if (((bNodeSocket *)nmd->node_group->inputs.first)->type != SOCK_GEOMETRY) { + BKE_modifier_set_error(ob, md, "Node group's geometry input must be the first"); + } + } + else if (geometry_socket_count > 1) { BKE_modifier_set_error(ob, md, "Node group can only have one geometry input"); } } -- cgit v1.2.3