From cef4d344f948ce75a7787ad0c3915c87e1716ca1 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 18 Feb 2020 14:02:40 +0100 Subject: Fix Embree failing on objects with a very high number of motion steps Set the limit to 129 to match Embree. This applies to all devices for consistent render results. Ref T73778 --- intern/cycles/blender/addon/properties.py | 2 +- intern/cycles/blender/blender_object.cpp | 2 +- intern/cycles/blender/blender_util.h | 8 +++++--- intern/cycles/bvh/bvh_embree.cpp | 28 +++++++++++++++++++--------- intern/cycles/render/geometry.h | 3 +++ intern/cycles/render/object.h | 3 +++ 6 files changed, 32 insertions(+), 14 deletions(-) (limited to 'intern/cycles') diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index eafe37618b3..23ff1771995 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -1132,7 +1132,7 @@ class CyclesObjectSettings(bpy.types.PropertyGroup): motion_steps: IntProperty( name="Motion Steps", description="Control accuracy of motion blur, more steps gives more memory usage (actual number of steps is 2^(steps - 1))", - min=1, soft_max=8, + min=1, max=7, default=1, ) diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 2b1d1eff7e5..334c25cafe1 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -266,7 +266,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, uint motion_steps; if (need_motion == Scene::MOTION_BLUR) { - motion_steps = object_motion_steps(b_parent, b_ob); + motion_steps = object_motion_steps(b_parent, b_ob, Object::MAX_MOTION_STEPS); geom->motion_steps = motion_steps; if (motion_steps && object_use_deform_motion(b_parent, b_ob)) { geom->use_motion_blur = true; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index cb7d1c62f60..ad90a5f8d52 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -483,7 +483,9 @@ static inline void mesh_texture_space(BL::Mesh &b_mesh, float3 &loc, float3 &siz } /* Object motion steps, returns 0 if no motion blur needed. */ -static inline uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob) +static inline uint object_motion_steps(BL::Object &b_parent, + BL::Object &b_ob, + const int max_steps = INT_MAX) { /* Get motion enabled and steps from object itself. */ PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles"); @@ -492,7 +494,7 @@ static inline uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob) return 0; } - uint steps = max(1, get_int(cobject, "motion_steps")); + int steps = max(1, get_int(cobject, "motion_steps")); /* Also check parent object, so motion blur and steps can be * controlled by dupligroup duplicator for linked groups. */ @@ -510,7 +512,7 @@ static inline uint object_motion_steps(BL::Object &b_parent, BL::Object &b_ob) /* Use uneven number of steps so we get one keyframe at the current frame, * and use 2^(steps - 1) so objects with more/fewer steps still have samples * at the same times, to avoid sampling at many different times. */ - return (2 << (steps - 1)) + 1; + return min((2 << (steps - 1)) + 1, max_steps); } /* object uses deformation motion blur */ diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 2d3cc622891..84b00aab91c 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -58,6 +58,11 @@ CCL_NAMESPACE_BEGIN +static_assert(Object::MAX_MOTION_STEPS <= RTC_MAX_TIME_STEP_COUNT, + "Object and Embree max motion steps inconsistent"); +static_assert(Object::MAX_MOTION_STEPS == Geometry::MAX_MOTION_STEPS, + "Object and Geometry max motion steps inconsistent"); + # define IS_HAIR(x) (x & 1) /* This gets called by Embree at every valid ray/object intersection. @@ -557,7 +562,10 @@ void BVHEmbree::add_instance(Object *ob, int i) instance_bvh->top_level = this; } - const size_t num_motion_steps = ob->use_motion() ? ob->motion.size() : 1; + const size_t num_object_motion_steps = ob->use_motion() ? ob->motion.size() : 1; + const size_t num_motion_steps = min(num_object_motion_steps, RTC_MAX_TIME_STEP_COUNT); + assert(num_object_motion_steps <= RTC_MAX_TIME_STEP_COUNT); + RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_INSTANCE); rtcSetGeometryInstancedScene(geom_id, instance_bvh->scene); rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); @@ -600,18 +608,17 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) { size_t prim_offset = pack.prim_index.size(); const Attribute *attr_mP = NULL; - size_t num_motion_steps = 1; + size_t num_geometry_motion_steps = 1; if (mesh->has_motion_blur()) { attr_mP = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_motion_steps = mesh->motion_steps; - if (num_motion_steps > RTC_MAX_TIME_STEP_COUNT) { - assert(0); - num_motion_steps = RTC_MAX_TIME_STEP_COUNT; - } + num_geometry_motion_steps = mesh->motion_steps; } } + const size_t num_motion_steps = min(num_geometry_motion_steps, RTC_MAX_TIME_STEP_COUNT); + assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT); + const size_t num_triangles = mesh->num_triangles(); RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, RTC_GEOMETRY_TYPE_TRIANGLE); rtcSetGeometryBuildQuality(geom_id, build_quality); @@ -782,14 +789,17 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) { size_t prim_offset = pack.prim_index.size(); const Attribute *attr_mP = NULL; - size_t num_motion_steps = 1; + size_t num_geometry_motion_steps = 1; if (hair->has_motion_blur()) { attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); if (attr_mP) { - num_motion_steps = hair->motion_steps; + num_geometry_motion_steps = hair->motion_steps; } } + const size_t num_motion_steps = min(num_geometry_motion_steps, RTC_MAX_TIME_STEP_COUNT); + assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT); + const size_t num_curves = hair->num_curves(); size_t num_segments = 0; for (size_t j = 0; j < num_curves; ++j) { diff --git a/intern/cycles/render/geometry.h b/intern/cycles/render/geometry.h index 711da1c81e8..66ae8472102 100644 --- a/intern/cycles/render/geometry.h +++ b/intern/cycles/render/geometry.h @@ -72,6 +72,9 @@ class Geometry : public Node { uint motion_steps; bool use_motion_blur; + /* Maximum number of motion steps supported (due to Embree). */ + static const uint MAX_MOTION_STEPS = 129; + /* BVH */ BVH *bvh; size_t attr_map_offset; diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h index c5d878ec938..7bd3edf769b 100644 --- a/intern/cycles/render/object.h +++ b/intern/cycles/render/object.h @@ -81,6 +81,9 @@ class Object : public Node { int motion_step(float time) const; void update_motion(); + /* Maximum number of motion steps supported (due to Embree). */ + static const uint MAX_MOTION_STEPS = 129; + /* Check whether object is traceable and it worth adding it to * kernel scene. */ -- cgit v1.2.3