diff options
Diffstat (limited to 'intern/cycles/bvh')
-rw-r--r-- | intern/cycles/bvh/CMakeLists.txt | 12 | ||||
-rw-r--r-- | intern/cycles/bvh/build.cpp | 130 | ||||
-rw-r--r-- | intern/cycles/bvh/build.h | 2 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 14 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh2.cpp | 28 | ||||
-rw-r--r-- | intern/cycles/bvh/embree.cpp | 106 | ||||
-rw-r--r-- | intern/cycles/bvh/embree.h | 5 | ||||
-rw-r--r-- | intern/cycles/bvh/metal.h | 35 | ||||
-rw-r--r-- | intern/cycles/bvh/metal.mm | 33 | ||||
-rw-r--r-- | intern/cycles/bvh/optix.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/bvh/optix.h | 6 | ||||
-rw-r--r-- | intern/cycles/bvh/params.h | 17 | ||||
-rw-r--r-- | intern/cycles/bvh/split.cpp | 48 | ||||
-rw-r--r-- | intern/cycles/bvh/split.h | 14 |
14 files changed, 440 insertions, 20 deletions
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt index 9edc30cf9c4..b5c80f78f09 100644 --- a/intern/cycles/bvh/CMakeLists.txt +++ b/intern/cycles/bvh/CMakeLists.txt @@ -33,6 +33,17 @@ set(SRC unaligned.cpp ) +set(SRC_METAL + metal.mm +) + +if(WITH_CYCLES_DEVICE_METAL) + list(APPEND SRC + ${SRC_METAL} + ) + add_definitions(-DWITH_METAL) +endif() + set(SRC_HEADERS bvh.h bvh2.h @@ -46,6 +57,7 @@ set(SRC_HEADERS sort.h split.h unaligned.h + metal.h ) set(LIB diff --git a/intern/cycles/bvh/build.cpp b/intern/cycles/bvh/build.cpp index 3ce268dfb25..91198e4e2a2 100644 --- a/intern/cycles/bvh/build.cpp +++ b/intern/cycles/bvh/build.cpp @@ -26,6 +26,7 @@ #include "scene/hair.h" #include "scene/mesh.h" #include "scene/object.h" +#include "scene/pointcloud.h" #include "scene/scene.h" #include "util/algorithm.h" @@ -113,9 +114,9 @@ void BVHBuild::add_reference_triangles(BoundBox &root, else { /* Motion triangles, trace optimized case: we split triangle * primitives into separate nodes for each of the time steps. - * This way we minimize overlap of neighbor curve primitives. + * This way we minimize overlap of neighbor triangle primitives. */ - const int num_bvh_steps = params.num_motion_curve_steps * 2 + 1; + const int num_bvh_steps = params.num_motion_triangle_steps * 2 + 1; const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); const size_t num_verts = mesh->verts.size(); const size_t num_steps = mesh->motion_steps; @@ -269,6 +270,101 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair } } +void BVHBuild::add_reference_points(BoundBox &root, + BoundBox ¢er, + PointCloud *pointcloud, + int i) +{ + const Attribute *point_attr_mP = NULL; + if (pointcloud->has_motion_blur()) { + point_attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + } + + const float3 *points_data = &pointcloud->points[0]; + const float *radius_data = &pointcloud->radius[0]; + const size_t num_points = pointcloud->num_points(); + const float3 *motion_data = (point_attr_mP) ? point_attr_mP->data_float3() : NULL; + const size_t num_steps = pointcloud->get_motion_steps(); + + if (point_attr_mP == NULL) { + /* Really simple logic for static points. */ + for (uint j = 0; j < num_points; j++) { + const PointCloud::Point point = pointcloud->get_point(j); + BoundBox bounds = BoundBox::empty; + point.bounds_grow(points_data, radius_data, bounds); + if (bounds.valid()) { + references.push_back(BVHReference(bounds, j, i, PRIMITIVE_POINT)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + } + else if (params.num_motion_point_steps == 0 || params.use_spatial_split) { + /* Simple case of motion points: single node for the whole + * shutter time. Lowest memory usage but less optimal + * rendering. + */ + /* TODO(sergey): Support motion steps for spatially split BVH. */ + for (uint j = 0; j < num_points; j++) { + const PointCloud::Point point = pointcloud->get_point(j); + BoundBox bounds = BoundBox::empty; + point.bounds_grow(points_data, radius_data, bounds); + for (size_t step = 0; step < num_steps - 1; step++) { + point.bounds_grow(motion_data + step * num_points, radius_data, bounds); + } + if (bounds.valid()) { + references.push_back(BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT)); + root.grow(bounds); + center.grow(bounds.center2()); + } + } + } + else { + /* Motion points, trace optimized case: we split point + * primitives into separate nodes for each of the time steps. + * This way we minimize overlap of neighbor point primitives. + */ + const int num_bvh_steps = params.num_motion_point_steps * 2 + 1; + const float num_bvh_steps_inv_1 = 1.0f / (num_bvh_steps - 1); + + for (uint j = 0; j < num_points; j++) { + const PointCloud::Point point = pointcloud->get_point(j); + const size_t num_steps = pointcloud->get_motion_steps(); + const float3 *point_steps = point_attr_mP->data_float3(); + + /* Calculate bounding box of the previous time step. + * Will be reused later to avoid duplicated work on + * calculating BVH time step boundbox. + */ + float4 prev_key = point.motion_key( + points_data, radius_data, point_steps, num_points, num_steps, 0.0f, j); + BoundBox prev_bounds = BoundBox::empty; + point.bounds_grow(prev_key, prev_bounds); + /* Create all primitive time steps, */ + for (int bvh_step = 1; bvh_step < num_bvh_steps; ++bvh_step) { + const float curr_time = (float)(bvh_step)*num_bvh_steps_inv_1; + float4 curr_key = point.motion_key( + points_data, radius_data, point_steps, num_points, num_steps, curr_time, j); + BoundBox curr_bounds = BoundBox::empty; + point.bounds_grow(curr_key, curr_bounds); + BoundBox bounds = prev_bounds; + bounds.grow(curr_bounds); + if (bounds.valid()) { + const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1; + references.push_back( + BVHReference(bounds, j, i, PRIMITIVE_MOTION_POINT, prev_time, curr_time)); + root.grow(bounds); + center.grow(bounds.center2()); + } + /* Current time boundbox becomes previous one for the + * next time step. + */ + prev_bounds = curr_bounds; + } + } + } +} + void BVHBuild::add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, @@ -282,6 +378,10 @@ void BVHBuild::add_reference_geometry(BoundBox &root, Hair *hair = static_cast<Hair *>(geom); add_reference_curves(root, center, hair, object_index); } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + add_reference_points(root, center, pointcloud, object_index); + } } void BVHBuild::add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i) @@ -311,6 +411,10 @@ static size_t count_primitives(Geometry *geom) Hair *hair = static_cast<Hair *>(geom); return count_curve_segments(hair); } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + return pointcloud->num_points(); + } return 0; } @@ -328,8 +432,9 @@ void BVHBuild::add_references(BVHRange &root) if (!ob->get_geometry()->is_instanced()) { num_alloc_references += count_primitives(ob->get_geometry()); } - else + else { num_alloc_references++; + } } else { num_alloc_references += count_primitives(ob->get_geometry()); @@ -394,7 +499,7 @@ BVHNode *BVHBuild::run() spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha; spatial_free_index = 0; - need_prim_time = params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0; + need_prim_time = params.use_motion_steps(); /* init progress updates */ double build_start_time; @@ -535,7 +640,8 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, const vector<BVHReference> &references) const { size_t size = range.size(); - size_t max_leaf_size = max(params.max_triangle_leaf_size, params.max_curve_leaf_size); + size_t max_leaf_size = max(max(params.max_triangle_leaf_size, params.max_curve_leaf_size), + params.max_point_leaf_size); if (size > max_leaf_size) return false; @@ -544,6 +650,8 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, size_t num_motion_triangles = 0; size_t num_curves = 0; size_t num_motion_curves = 0; + size_t num_points = 0; + size_t num_motion_points = 0; for (int i = 0; i < size; i++) { const BVHReference &ref = references[range.start() + i]; @@ -564,12 +672,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, num_triangles++; } } + else if (ref.prim_type() & PRIMITIVE_ALL_POINT) { + if (ref.prim_type() & PRIMITIVE_ALL_MOTION) { + num_motion_points++; + } + else { + num_points++; + } + } } return (num_triangles <= params.max_triangle_leaf_size) && (num_motion_triangles <= params.max_motion_triangle_leaf_size) && (num_curves <= params.max_curve_leaf_size) && - (num_motion_curves <= params.max_motion_curve_leaf_size); + (num_motion_curves <= params.max_motion_curve_leaf_size) && + (num_points <= params.max_point_leaf_size) && + (num_motion_points <= params.max_motion_point_leaf_size); } /* multithreaded binning builder */ diff --git a/intern/cycles/bvh/build.h b/intern/cycles/bvh/build.h index 06b318f1ee0..5b9bb59d9f8 100644 --- a/intern/cycles/bvh/build.h +++ b/intern/cycles/bvh/build.h @@ -39,6 +39,7 @@ class Geometry; class Hair; class Mesh; class Object; +class PointCloud; class Progress; /* BVH Builder */ @@ -68,6 +69,7 @@ class BVHBuild { /* Adding references. */ void add_reference_triangles(BoundBox &root, BoundBox ¢er, Mesh *mesh, int i); void add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair, int i); + void add_reference_points(BoundBox &root, BoundBox ¢er, PointCloud *pointcloud, int i); void add_reference_geometry(BoundBox &root, BoundBox ¢er, Geometry *geom, int i); void add_reference_object(BoundBox &root, BoundBox ¢er, Object *ob, int i); void add_references(BVHRange &root); diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index ae6655eb27b..703639e29f3 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -19,6 +19,7 @@ #include "bvh/bvh2.h" #include "bvh/embree.h" +#include "bvh/metal.h" #include "bvh/multi.h" #include "bvh/optix.h" @@ -40,8 +41,12 @@ const char *bvh_layout_name(BVHLayout layout) return "EMBREE"; case BVH_LAYOUT_OPTIX: return "OPTIX"; + case BVH_LAYOUT_METAL: + return "METAL"; case BVH_LAYOUT_MULTI_OPTIX: + case BVH_LAYOUT_MULTI_METAL: case BVH_LAYOUT_MULTI_OPTIX_EMBREE: + case BVH_LAYOUT_MULTI_METAL_EMBREE: return "MULTI"; case BVH_LAYOUT_ALL: return "ALL"; @@ -103,8 +108,17 @@ BVH *BVH::create(const BVHParams ¶ms, (void)device; break; #endif + case BVH_LAYOUT_METAL: +#ifdef WITH_METAL + return bvh_metal_create(params, geometry, objects, device); +#else + (void)device; + break; +#endif case BVH_LAYOUT_MULTI_OPTIX: + case BVH_LAYOUT_MULTI_METAL: case BVH_LAYOUT_MULTI_OPTIX_EMBREE: + case BVH_LAYOUT_MULTI_METAL_EMBREE: return new BVHMulti(params, geometry, objects); case BVH_LAYOUT_NONE: case BVH_LAYOUT_ALL: diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp index 04290602145..744e7fa9898 100644 --- a/intern/cycles/bvh/bvh2.cpp +++ b/intern/cycles/bvh/bvh2.cpp @@ -20,6 +20,7 @@ #include "scene/hair.h" #include "scene/mesh.h" #include "scene/object.h" +#include "scene/pointcloud.h" #include "bvh/build.h" #include "bvh/node.h" @@ -409,6 +410,30 @@ void BVH2::refit_primitives(int start, int end, BoundBox &bbox, uint &visibility } } } + else if (pack.prim_type[prim] & PRIMITIVE_ALL_POINT) { + /* Points. */ + const PointCloud *pointcloud = static_cast<const PointCloud *>(ob->get_geometry()); + int prim_offset = (params.top_level) ? pointcloud->prim_offset : 0; + const float3 *points = &pointcloud->points[0]; + const float *radius = &pointcloud->radius[0]; + PointCloud::Point point = pointcloud->get_point(pidx - prim_offset); + + point.bounds_grow(points, radius, bbox); + + /* Motion points. */ + if (pointcloud->get_use_motion_blur()) { + Attribute *attr = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + + if (attr) { + size_t pointcloud_size = pointcloud->points.size(); + size_t steps = pointcloud->get_motion_steps() - 1; + float3 *point_steps = attr->data_float3(); + + for (size_t i = 0; i < steps; i++) + point.bounds_grow(point_steps + i * pointcloud_size, radius, bbox); + } + } + } else { /* Triangles. */ const Mesh *mesh = static_cast<const Mesh *>(ob->get_geometry()); @@ -505,7 +530,8 @@ void BVH2::pack_instances(size_t nodes_size, size_t leaf_nodes_size) pack.leaf_nodes.resize(leaf_nodes_size); pack.object_node.resize(objects.size()); - if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0) { + if (params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0 || + params.num_motion_point_steps > 0) { pack.prim_time.resize(prim_index_size); } diff --git a/intern/cycles/bvh/embree.cpp b/intern/cycles/bvh/embree.cpp index b54b38f2798..eab193f45cb 100644 --- a/intern/cycles/bvh/embree.cpp +++ b/intern/cycles/bvh/embree.cpp @@ -45,6 +45,7 @@ # include "scene/hair.h" # include "scene/mesh.h" # include "scene/object.h" +# include "scene/pointcloud.h" # include "util/foreach.h" # include "util/log.h" @@ -245,7 +246,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) } } -static void rtc_filter_func_thick_curve(const RTCFilterFunctionNArguments *args) +static void rtc_filter_func_backface_cull(const RTCFilterFunctionNArguments *args) { const RTCRay *ray = (RTCRay *)args->ray; RTCHit *hit = (RTCHit *)args->hit; @@ -258,7 +259,7 @@ static void rtc_filter_func_thick_curve(const RTCFilterFunctionNArguments *args) } } -static void rtc_filter_occluded_func_thick_curve(const RTCFilterFunctionNArguments *args) +static void rtc_filter_occluded_func_backface_cull(const RTCFilterFunctionNArguments *args) { const RTCRay *ray = (RTCRay *)args->ray; RTCHit *hit = (RTCHit *)args->hit; @@ -410,6 +411,12 @@ void BVHEmbree::add_object(Object *ob, int i) add_curves(ob, hair, i); } } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + if (pointcloud->num_points() > 0) { + add_points(ob, pointcloud, i); + } + } } void BVHEmbree::add_instance(Object *ob, int i) @@ -624,6 +631,89 @@ void BVHEmbree::set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, c } } +void BVHEmbree::set_point_vertex_buffer(RTCGeometry geom_id, + const PointCloud *pointcloud, + const bool update) +{ + const Attribute *attr_mP = NULL; + size_t num_motion_steps = 1; + if (pointcloud->has_motion_blur()) { + attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (attr_mP) { + num_motion_steps = pointcloud->get_motion_steps(); + } + } + + const size_t num_points = pointcloud->num_points(); + + /* Copy the point data to Embree */ + const int t_mid = (num_motion_steps - 1) / 2; + const float *radius = pointcloud->get_radius().data(); + for (int t = 0; t < num_motion_steps; ++t) { + const float3 *verts; + if (t == t_mid || attr_mP == NULL) { + verts = pointcloud->get_points().data(); + } + else { + int t_ = (t > t_mid) ? (t - 1) : t; + verts = &attr_mP->data_float3()[t_ * num_points]; + } + + float4 *rtc_verts = (update) ? (float4 *)rtcGetGeometryBufferData( + geom_id, RTC_BUFFER_TYPE_VERTEX, t) : + (float4 *)rtcSetNewGeometryBuffer(geom_id, + RTC_BUFFER_TYPE_VERTEX, + t, + RTC_FORMAT_FLOAT4, + sizeof(float) * 4, + num_points); + + assert(rtc_verts); + if (rtc_verts) { + for (size_t j = 0; j < num_points; ++j) { + rtc_verts[j] = float3_to_float4(verts[j]); + rtc_verts[j].w = radius[j]; + } + } + + if (update) { + rtcUpdateGeometryBuffer(geom_id, RTC_BUFFER_TYPE_VERTEX, t); + } + } +} + +void BVHEmbree::add_points(const Object *ob, const PointCloud *pointcloud, int i) +{ + size_t prim_offset = pointcloud->prim_offset; + + const Attribute *attr_mP = NULL; + size_t num_motion_steps = 1; + if (pointcloud->has_motion_blur()) { + attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + if (attr_mP) { + num_motion_steps = pointcloud->get_motion_steps(); + } + } + + enum RTCGeometryType type = RTC_GEOMETRY_TYPE_SPHERE_POINT; + + RTCGeometry geom_id = rtcNewGeometry(rtc_device, type); + + rtcSetGeometryBuildQuality(geom_id, build_quality); + rtcSetGeometryTimeStepCount(geom_id, num_motion_steps); + + set_point_vertex_buffer(geom_id, pointcloud, false); + + rtcSetGeometryUserData(geom_id, (void *)prim_offset); + rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_backface_cull); + rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_backface_cull); + rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); + + rtcCommitGeometry(geom_id); + rtcAttachGeometryByID(scene, geom_id, i * 2); + rtcReleaseGeometry(geom_id); +} + void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) { size_t prim_offset = hair->curve_segment_offset; @@ -678,8 +768,8 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); } else { - rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_thick_curve); - rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_thick_curve); + rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func_backface_cull); + rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func_backface_cull); } rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); @@ -716,6 +806,14 @@ void BVHEmbree::refit(Progress &progress) rtcCommitGeometry(geom); } } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + if (pointcloud->num_points() > 0) { + RTCGeometry geom = rtcGetGeometry(scene, geom_id); + set_point_vertex_buffer(geom, pointcloud, true); + rtcCommitGeometry(geom); + } + } } geom_id += 2; } diff --git a/intern/cycles/bvh/embree.h b/intern/cycles/bvh/embree.h index 746ca97b504..3b30b2bbcf7 100644 --- a/intern/cycles/bvh/embree.h +++ b/intern/cycles/bvh/embree.h @@ -33,6 +33,7 @@ CCL_NAMESPACE_BEGIN class Hair; class Mesh; +class PointCloud; class BVHEmbree : public BVH { public: @@ -51,11 +52,15 @@ class BVHEmbree : public BVH { void add_object(Object *ob, int i); void add_instance(Object *ob, int i); void add_curves(const Object *ob, const Hair *hair, int i); + void add_points(const Object *ob, const PointCloud *pointcloud, int i); void add_triangles(const Object *ob, const Mesh *mesh, int i); private: void set_tri_vertex_buffer(RTCGeometry geom_id, const Mesh *mesh, const bool update); void set_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair, const bool update); + void set_point_vertex_buffer(RTCGeometry geom_id, + const PointCloud *pointcloud, + const bool update); RTCDevice rtc_device; enum RTCBuildQuality build_quality; diff --git a/intern/cycles/bvh/metal.h b/intern/cycles/bvh/metal.h new file mode 100644 index 00000000000..8de07927e61 --- /dev/null +++ b/intern/cycles/bvh/metal.h @@ -0,0 +1,35 @@ +/* + * Copyright 2021 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __BVH_METAL_H__ +#define __BVH_METAL_H__ + +#ifdef WITH_METAL + +# include "bvh/bvh.h" + +CCL_NAMESPACE_BEGIN + +BVH *bvh_metal_create(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects, + Device *device); + +CCL_NAMESPACE_END + +#endif /* WITH_METAL */ + +#endif /* __BVH_METAL_H__ */ diff --git a/intern/cycles/bvh/metal.mm b/intern/cycles/bvh/metal.mm new file mode 100644 index 00000000000..90a52012f12 --- /dev/null +++ b/intern/cycles/bvh/metal.mm @@ -0,0 +1,33 @@ +/* + * Copyright 2021 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef WITH_METAL + +# include "device/metal/bvh.h" + +CCL_NAMESPACE_BEGIN + +BVH *bvh_metal_create(const BVHParams ¶ms, + const vector<Geometry *> &geometry, + const vector<Object *> &objects, + Device *device) +{ + return new BVHMetal(params, geometry, objects, device); +} + +CCL_NAMESPACE_END + +#endif /* WITH_METAL */ diff --git a/intern/cycles/bvh/optix.cpp b/intern/cycles/bvh/optix.cpp index ebc3fa68b97..671e1a42a31 100644 --- a/intern/cycles/bvh/optix.cpp +++ b/intern/cycles/bvh/optix.cpp @@ -30,15 +30,17 @@ BVHOptiX::BVHOptiX(const BVHParams ¶ms_, : BVH(params_, geometry_, objects_), device(device), traversable_handle(0), - as_data(device, params_.top_level ? "optix tlas" : "optix blas", false), - motion_transform_data(device, "optix motion transform", false) + as_data(make_unique<device_only_memory<char>>( + device, params.top_level ? "optix tlas" : "optix blas", false)), + motion_transform_data( + make_unique<device_only_memory<char>>(device, "optix motion transform", false)) { } BVHOptiX::~BVHOptiX() { - // Acceleration structure memory is delayed freed on device, since deleting the - // BVH may happen while still being used for rendering. + /* Acceleration structure memory is delayed freed on device, since deleting the + * BVH may happen while still being used for rendering. */ device->release_optix_bvh(this); } diff --git a/intern/cycles/bvh/optix.h b/intern/cycles/bvh/optix.h index 037e54980bd..cb855d786bf 100644 --- a/intern/cycles/bvh/optix.h +++ b/intern/cycles/bvh/optix.h @@ -25,14 +25,16 @@ # include "device/memory.h" +# include "util/unique_ptr.h" + CCL_NAMESPACE_BEGIN class BVHOptiX : public BVH { public: Device *device; uint64_t traversable_handle; - device_only_memory<char> as_data; - device_only_memory<char> motion_transform_data; + unique_ptr<device_only_memory<char>> as_data; + unique_ptr<device_only_memory<char>> motion_transform_data; protected: friend class BVH; diff --git a/intern/cycles/bvh/params.h b/intern/cycles/bvh/params.h index 8f185a2640f..16edf2e88e4 100644 --- a/intern/cycles/bvh/params.h +++ b/intern/cycles/bvh/params.h @@ -83,6 +83,8 @@ class BVHParams { int max_motion_triangle_leaf_size; int max_curve_leaf_size; int max_motion_curve_leaf_size; + int max_point_leaf_size; + int max_motion_point_leaf_size; /* object or mesh level bvh */ bool top_level; @@ -98,13 +100,13 @@ class BVHParams { /* Split time range to this number of steps and create leaf node for each * of this time steps. * - * Speeds up rendering of motion curve primitives in the cost of higher - * memory usage. + * Speeds up rendering of motion primitives in the cost of higher memory usage. */ - int num_motion_curve_steps; /* Same as above, but for triangle primitives. */ int num_motion_triangle_steps; + int num_motion_curve_steps; + int num_motion_point_steps; /* Same as in SceneParams. */ int bvh_type; @@ -132,6 +134,8 @@ class BVHParams { max_motion_triangle_leaf_size = 8; max_curve_leaf_size = 1; max_motion_curve_leaf_size = 4; + max_point_leaf_size = 8; + max_motion_point_leaf_size = 8; top_level = false; bvh_layout = BVH_LAYOUT_BVH2; @@ -139,6 +143,7 @@ class BVHParams { num_motion_curve_steps = 0; num_motion_triangle_steps = 0; + num_motion_point_steps = 0; bvh_type = 0; @@ -166,6 +171,12 @@ class BVHParams { return (size <= min_leaf_size || level >= MAX_DEPTH); } + bool use_motion_steps() + { + return num_motion_curve_steps > 0 || num_motion_triangle_steps > 0 || + num_motion_point_steps > 0; + } + /* Gets best matching BVH. * * If the requested layout is supported by the device, it will be used. diff --git a/intern/cycles/bvh/split.cpp b/intern/cycles/bvh/split.cpp index 102c50e2979..34d12de97c0 100644 --- a/intern/cycles/bvh/split.cpp +++ b/intern/cycles/bvh/split.cpp @@ -23,6 +23,7 @@ #include "scene/hair.h" #include "scene/mesh.h" #include "scene/object.h" +#include "scene/pointcloud.h" #include "util/algorithm.h" @@ -426,6 +427,32 @@ void BVHSpatialSplit::split_curve_primitive(const Hair *hair, } } +void BVHSpatialSplit::split_point_primitive(const PointCloud *pointcloud, + const Transform *tfm, + int prim_index, + int dim, + float pos, + BoundBox &left_bounds, + BoundBox &right_bounds) +{ + /* No real splitting support for points, assume they are small enough for it + * not to matter. */ + float3 point = pointcloud->get_points()[prim_index]; + + if (tfm != NULL) { + point = transform_point(tfm, point); + } + point = get_unaligned_point(point); + + if (point[dim] <= pos) { + left_bounds.grow(point); + } + + if (point[dim] >= pos) { + right_bounds.grow(point); + } +} + void BVHSpatialSplit::split_triangle_reference(const BVHReference &ref, const Mesh *mesh, int dim, @@ -453,6 +480,16 @@ void BVHSpatialSplit::split_curve_reference(const BVHReference &ref, right_bounds); } +void BVHSpatialSplit::split_point_reference(const BVHReference &ref, + const PointCloud *pointcloud, + int dim, + float pos, + BoundBox &left_bounds, + BoundBox &right_bounds) +{ + split_point_primitive(pointcloud, NULL, ref.prim_index(), dim, pos, left_bounds, right_bounds); +} + void BVHSpatialSplit::split_object_reference( const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds) { @@ -475,6 +512,13 @@ void BVHSpatialSplit::split_object_reference( } } } + else if (geom->geometry_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + for (int point_idx = 0; point_idx < pointcloud->num_points(); ++point_idx) { + split_point_primitive( + pointcloud, &object->get_tfm(), point_idx, dim, pos, left_bounds, right_bounds); + } + } } void BVHSpatialSplit::split_reference(const BVHBuild &builder, @@ -499,6 +543,10 @@ void BVHSpatialSplit::split_reference(const BVHBuild &builder, Hair *hair = static_cast<Hair *>(ob->get_geometry()); split_curve_reference(ref, hair, dim, pos, left_bounds, right_bounds); } + else if (ref.prim_type() & PRIMITIVE_ALL_POINT) { + PointCloud *pointcloud = static_cast<PointCloud *>(ob->get_geometry()); + split_point_reference(ref, pointcloud, dim, pos, left_bounds, right_bounds); + } else { split_object_reference(ob, dim, pos, left_bounds, right_bounds); } diff --git a/intern/cycles/bvh/split.h b/intern/cycles/bvh/split.h index 2650a500ea9..92953c40040 100644 --- a/intern/cycles/bvh/split.h +++ b/intern/cycles/bvh/split.h @@ -26,6 +26,7 @@ CCL_NAMESPACE_BEGIN class BVHBuild; class Hair; class Mesh; +class PointCloud; struct Transform; /* Object Split */ @@ -123,6 +124,13 @@ class BVHSpatialSplit { float pos, BoundBox &left_bounds, BoundBox &right_bounds); + void split_point_primitive(const PointCloud *pointcloud, + const Transform *tfm, + int prim_index, + int dim, + float pos, + BoundBox &left_bounds, + BoundBox &right_bounds); /* Lower-level functions which calculates boundaries of left and right nodes * needed for spatial split. @@ -141,6 +149,12 @@ class BVHSpatialSplit { float pos, BoundBox &left_bounds, BoundBox &right_bounds); + void split_point_reference(const BVHReference &ref, + const PointCloud *pointcloud, + int dim, + float pos, + BoundBox &left_bounds, + BoundBox &right_bounds); void split_object_reference( const Object *object, int dim, float pos, BoundBox &left_bounds, BoundBox &right_bounds); |