diff options
author | Julian Eisel <julian@blender.org> | 2020-07-01 18:13:57 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2020-07-01 18:13:57 +0300 |
commit | 0829cebeb024095c268f190c34daa8ae9a5a224c (patch) | |
tree | 12ee5a4a1c2a32e12eff47c8eb9bb0ed217791c1 /intern/cycles/bvh | |
parent | cfde6ebf450594faa57c4bfeaecff10fe512c91b (diff) | |
parent | 42be3964eb201180f6b0fa1ff6ce43b8c3845bc2 (diff) |
Merge branch 'master' into asset-uuid--archivedasset-uuid--archived
Diffstat (limited to 'intern/cycles/bvh')
-rw-r--r-- | intern/cycles/bvh/CMakeLists.txt | 4 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 72 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.h | 2 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh4.cpp | 447 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh4.h | 88 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh8.cpp | 541 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh8.h | 99 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.cpp | 169 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.h | 15 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_embree.cpp | 161 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_embree.h | 2 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_optix.cpp | 13 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_params.h | 2 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_sort.cpp | 15 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_split.cpp | 10 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_split.h | 10 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_unaligned.cpp | 6 |
17 files changed, 181 insertions, 1475 deletions
diff --git a/intern/cycles/bvh/CMakeLists.txt b/intern/cycles/bvh/CMakeLists.txt index fb724704a84..8b8f3ca7265 100644 --- a/intern/cycles/bvh/CMakeLists.txt +++ b/intern/cycles/bvh/CMakeLists.txt @@ -9,8 +9,6 @@ set(INC_SYS set(SRC bvh.cpp bvh2.cpp - bvh4.cpp - bvh8.cpp bvh_binning.cpp bvh_build.cpp bvh_embree.cpp @@ -24,8 +22,6 @@ set(SRC set(SRC_HEADERS bvh.h bvh2.h - bvh4.h - bvh8.h bvh_binning.h bvh_build.h bvh_embree.h diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 0313bcd68b0..e9e67fd1305 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -22,17 +22,10 @@ #include "render/object.h" #include "bvh/bvh2.h" -#include "bvh/bvh4.h" -#include "bvh/bvh8.h" #include "bvh/bvh_build.h" +#include "bvh/bvh_embree.h" #include "bvh/bvh_node.h" - -#ifdef WITH_OPTIX -# include "bvh/bvh_optix.h" -#endif -#ifdef WITH_EMBREE -# include "bvh/bvh_embree.h" -#endif +#include "bvh/bvh_optix.h" #include "util/util_foreach.h" #include "util/util_logging.h" @@ -47,10 +40,6 @@ const char *bvh_layout_name(BVHLayout layout) switch (layout) { case BVH_LAYOUT_BVH2: return "BVH2"; - case BVH_LAYOUT_BVH4: - return "BVH4"; - case BVH_LAYOUT_BVH8: - return "BVH8"; case BVH_LAYOUT_NONE: return "NONE"; case BVH_LAYOUT_EMBREE: @@ -114,10 +103,6 @@ BVH *BVH::create(const BVHParams ¶ms, switch (params.bvh_layout) { case BVH_LAYOUT_BVH2: return new BVH2(params, geometry, objects); - case BVH_LAYOUT_BVH4: - return new BVH4(params, geometry, objects); - case BVH_LAYOUT_BVH8: - return new BVH8(params, geometry, objects); case BVH_LAYOUT_EMBREE: #ifdef WITH_EMBREE return new BVHEmbree(params, geometry, objects); @@ -337,13 +322,6 @@ void BVH::pack_primitives() void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) { - /* The BVH's for instances are built separately, but for traversal all - * BVH's are stored in global arrays. This function merges them into the - * top level BVH, adjusting indexes and offsets where appropriate. - */ - const bool use_qbvh = (params.bvh_layout == BVH_LAYOUT_BVH4); - const bool use_obvh = (params.bvh_layout == BVH_LAYOUT_BVH8); - /* Adjust primitive index to point to the triangle in the global array, for * geometry with transform applied and already in the top level BVH. */ @@ -506,53 +484,21 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) for (size_t i = 0, j = 0; i < bvh_nodes_size; j++) { size_t nsize, nsize_bbox; if (bvh_nodes[i].x & PATH_RAY_NODE_UNALIGNED) { - if (use_obvh) { - nsize = BVH_UNALIGNED_ONODE_SIZE; - nsize_bbox = BVH_UNALIGNED_ONODE_SIZE - 1; - } - else { - nsize = use_qbvh ? BVH_UNALIGNED_QNODE_SIZE : BVH_UNALIGNED_NODE_SIZE; - nsize_bbox = (use_qbvh) ? BVH_UNALIGNED_QNODE_SIZE - 1 : 0; - } + nsize = BVH_UNALIGNED_NODE_SIZE; + nsize_bbox = 0; } else { - if (use_obvh) { - nsize = BVH_ONODE_SIZE; - nsize_bbox = BVH_ONODE_SIZE - 1; - } - else { - nsize = (use_qbvh) ? BVH_QNODE_SIZE : BVH_NODE_SIZE; - nsize_bbox = (use_qbvh) ? BVH_QNODE_SIZE - 1 : 0; - } + nsize = BVH_NODE_SIZE; + nsize_bbox = 0; } memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox * sizeof(int4)); /* Modify offsets into arrays */ int4 data = bvh_nodes[i + nsize_bbox]; - - if (use_obvh) { - int4 data1 = bvh_nodes[i + nsize_bbox - 1]; - data.z += (data.z < 0) ? -noffset_leaf : noffset; - data.w += (data.w < 0) ? -noffset_leaf : noffset; - data.x += (data.x < 0) ? -noffset_leaf : noffset; - data.y += (data.y < 0) ? -noffset_leaf : noffset; - data1.z += (data1.z < 0) ? -noffset_leaf : noffset; - data1.w += (data1.w < 0) ? -noffset_leaf : noffset; - data1.x += (data1.x < 0) ? -noffset_leaf : noffset; - data1.y += (data1.y < 0) ? -noffset_leaf : noffset; - pack_nodes[pack_nodes_offset + nsize_bbox] = data; - pack_nodes[pack_nodes_offset + nsize_bbox - 1] = data1; - } - else { - data.z += (data.z < 0) ? -noffset_leaf : noffset; - data.w += (data.w < 0) ? -noffset_leaf : noffset; - if (use_qbvh) { - data.x += (data.x < 0) ? -noffset_leaf : noffset; - data.y += (data.y < 0) ? -noffset_leaf : noffset; - } - pack_nodes[pack_nodes_offset + nsize_bbox] = data; - } + data.z += (data.z < 0) ? -noffset_leaf : noffset; + data.w += (data.w < 0) ? -noffset_leaf : noffset; + pack_nodes[pack_nodes_offset + nsize_bbox] = data; /* Usually this copies nothing, but we better * be prepared for possible node size extension. diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index bdde38640c9..6639e06b0bc 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -76,7 +76,7 @@ struct PackedBVH { } }; -enum BVH_TYPE { bvh2, bvh4, bvh8 }; +enum BVH_TYPE { bvh2 }; /* BVH */ diff --git a/intern/cycles/bvh/bvh4.cpp b/intern/cycles/bvh/bvh4.cpp deleted file mode 100644 index 143c3e54f94..00000000000 --- a/intern/cycles/bvh/bvh4.cpp +++ /dev/null @@ -1,447 +0,0 @@ -/* - * Adapted from code copyright 2009-2010 NVIDIA Corporation - * Modifications Copyright 2011, 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. - */ - -#include "bvh/bvh4.h" - -#include "render/mesh.h" -#include "render/object.h" - -#include "bvh/bvh_node.h" -#include "bvh/bvh_unaligned.h" - -CCL_NAMESPACE_BEGIN - -/* Can we avoid this somehow or make more generic? - * - * Perhaps we can merge nodes in actual tree and make our - * life easier all over the place. - */ - -BVH4::BVH4(const BVHParams ¶ms_, - const vector<Geometry *> &geometry_, - const vector<Object *> &objects_) - : BVH(params_, geometry_, objects_) -{ - params.bvh_layout = BVH_LAYOUT_BVH4; -} - -namespace { - -BVHNode *bvh_node_merge_children_recursively(const BVHNode *node) -{ - if (node->is_leaf()) { - return new LeafNode(*reinterpret_cast<const LeafNode *>(node)); - } - /* Collect nodes of one layer deeper, allowing us to have more children in an inner layer. */ - assert(node->num_children() <= 2); - const BVHNode *children[4]; - const BVHNode *child0 = node->get_child(0); - const BVHNode *child1 = node->get_child(1); - int num_children = 0; - if (child0->is_leaf()) { - children[num_children++] = child0; - } - else { - children[num_children++] = child0->get_child(0); - children[num_children++] = child0->get_child(1); - } - if (child1->is_leaf()) { - children[num_children++] = child1; - } - else { - children[num_children++] = child1->get_child(0); - children[num_children++] = child1->get_child(1); - } - /* Merge children in subtrees. */ - BVHNode *children4[4]; - for (int i = 0; i < num_children; ++i) { - children4[i] = bvh_node_merge_children_recursively(children[i]); - } - /* Allocate new node. */ - BVHNode *node4 = new InnerNode(node->bounds, children4, num_children); - /* TODO(sergey): Consider doing this from the InnerNode() constructor. - * But in order to do this nicely need to think of how to pass all the - * parameters there. */ - if (node->is_unaligned) { - node4->is_unaligned = true; - node4->aligned_space = new Transform(); - *node4->aligned_space = *node->aligned_space; - } - return node4; -} - -} // namespace - -BVHNode *BVH4::widen_children_nodes(const BVHNode *root) -{ - if (root == NULL) { - return NULL; - } - if (root->is_leaf()) { - return const_cast<BVHNode *>(root); - } - BVHNode *root4 = bvh_node_merge_children_recursively(root); - /* TODO(sergey): Pack children nodes to parents which has less that 4 - * children. */ - return root4; -} - -void BVH4::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf) -{ - float4 data[BVH_QNODE_LEAF_SIZE]; - memset(data, 0, sizeof(data)); - if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) { - /* object */ - data[0].x = __int_as_float(~(leaf->lo)); - data[0].y = __int_as_float(0); - } - else { - /* triangle */ - data[0].x = __int_as_float(leaf->lo); - data[0].y = __int_as_float(leaf->hi); - } - data[0].z = __uint_as_float(leaf->visibility); - if (leaf->num_triangles() != 0) { - data[0].w = __uint_as_float(pack.prim_type[leaf->lo]); - } - - memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_QNODE_LEAF_SIZE); -} - -void BVH4::pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) -{ - bool has_unaligned = false; - /* Check whether we have to create unaligned node or all nodes are aligned - * and we can cut some corner here. - */ - if (params.use_unaligned_nodes) { - for (int i = 0; i < num; i++) { - if (en[i].node->is_unaligned) { - has_unaligned = true; - break; - } - } - } - if (has_unaligned) { - /* There's no unaligned children, pack into AABB node. */ - pack_unaligned_inner(e, en, num); - } - else { - /* Create unaligned node with orientation transform for each of the - * children. - */ - pack_aligned_inner(e, en, num); - } -} - -void BVH4::pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) -{ - BoundBox bounds[4]; - int child[4]; - for (int i = 0; i < num; ++i) { - bounds[i] = en[i].node->bounds; - child[i] = en[i].encodeIdx(); - } - pack_aligned_node( - e.idx, bounds, child, e.node->visibility, e.node->time_from, e.node->time_to, num); -} - -void BVH4::pack_aligned_node(int idx, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num) -{ - float4 data[BVH_QNODE_SIZE]; - memset(data, 0, sizeof(data)); - - data[0].x = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED); - data[0].y = time_from; - data[0].z = time_to; - - for (int i = 0; i < num; i++) { - float3 bb_min = bounds[i].min; - float3 bb_max = bounds[i].max; - - data[1][i] = bb_min.x; - data[2][i] = bb_max.x; - data[3][i] = bb_min.y; - data[4][i] = bb_max.y; - data[5][i] = bb_min.z; - data[6][i] = bb_max.z; - - data[7][i] = __int_as_float(child[i]); - } - - for (int i = num; i < 4; i++) { - /* We store BB which would never be recorded as intersection - * so kernel might safely assume there are always 4 child nodes. - */ - data[1][i] = FLT_MAX; - data[2][i] = -FLT_MAX; - - data[3][i] = FLT_MAX; - data[4][i] = -FLT_MAX; - - data[5][i] = FLT_MAX; - data[6][i] = -FLT_MAX; - - data[7][i] = __int_as_float(0); - } - - memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_QNODE_SIZE); -} - -void BVH4::pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) -{ - Transform aligned_space[4]; - BoundBox bounds[4]; - int child[4]; - for (int i = 0; i < num; ++i) { - aligned_space[i] = en[i].node->get_aligned_space(); - bounds[i] = en[i].node->bounds; - child[i] = en[i].encodeIdx(); - } - pack_unaligned_node(e.idx, - aligned_space, - bounds, - child, - e.node->visibility, - e.node->time_from, - e.node->time_to, - num); -} - -void BVH4::pack_unaligned_node(int idx, - const Transform *aligned_space, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num) -{ - float4 data[BVH_UNALIGNED_QNODE_SIZE]; - memset(data, 0, sizeof(data)); - - data[0].x = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED); - data[0].y = time_from; - data[0].z = time_to; - - for (int i = 0; i < num; i++) { - Transform space = BVHUnaligned::compute_node_transform(bounds[i], aligned_space[i]); - - data[1][i] = space.x.x; - data[2][i] = space.x.y; - data[3][i] = space.x.z; - - data[4][i] = space.y.x; - data[5][i] = space.y.y; - data[6][i] = space.y.z; - - data[7][i] = space.z.x; - data[8][i] = space.z.y; - data[9][i] = space.z.z; - - data[10][i] = space.x.w; - data[11][i] = space.y.w; - data[12][i] = space.z.w; - - data[13][i] = __int_as_float(child[i]); - } - - for (int i = num; i < 4; i++) { - /* We store BB which would never be recorded as intersection - * so kernel might safely assume there are always 4 child nodes. - */ - - data[1][i] = NAN; - data[2][i] = NAN; - data[3][i] = NAN; - - data[4][i] = NAN; - data[5][i] = NAN; - data[6][i] = NAN; - - data[7][i] = NAN; - data[8][i] = NAN; - data[9][i] = NAN; - - data[10][i] = NAN; - data[11][i] = NAN; - data[12][i] = NAN; - - data[13][i] = __int_as_float(0); - } - - memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_QNODE_SIZE); -} - -/* Quad SIMD Nodes */ - -void BVH4::pack_nodes(const BVHNode *root) -{ - /* Calculate size of the arrays required. */ - const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT); - const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); - assert(num_leaf_nodes <= num_nodes); - const size_t num_inner_nodes = num_nodes - num_leaf_nodes; - size_t node_size; - if (params.use_unaligned_nodes) { - const size_t num_unaligned_nodes = root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT); - node_size = (num_unaligned_nodes * BVH_UNALIGNED_QNODE_SIZE) + - (num_inner_nodes - num_unaligned_nodes) * BVH_QNODE_SIZE; - } - else { - node_size = num_inner_nodes * BVH_QNODE_SIZE; - } - /* Resize arrays. */ - pack.nodes.clear(); - pack.leaf_nodes.clear(); - /* For top level BVH, first merge existing BVH's so we know the offsets. */ - if (params.top_level) { - pack_instances(node_size, num_leaf_nodes * BVH_QNODE_LEAF_SIZE); - } - else { - pack.nodes.resize(node_size); - pack.leaf_nodes.resize(num_leaf_nodes * BVH_QNODE_LEAF_SIZE); - } - - int nextNodeIdx = 0, nextLeafNodeIdx = 0; - - vector<BVHStackEntry> stack; - stack.reserve(BVHParams::MAX_DEPTH * 2); - if (root->is_leaf()) { - stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); - } - else { - stack.push_back(BVHStackEntry(root, nextNodeIdx)); - nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE : BVH_QNODE_SIZE; - } - - while (stack.size()) { - BVHStackEntry e = stack.back(); - stack.pop_back(); - - if (e.node->is_leaf()) { - /* leaf node */ - const LeafNode *leaf = reinterpret_cast<const LeafNode *>(e.node); - pack_leaf(e, leaf); - } - else { - /* Inner node. */ - /* Collect nodes. */ - const BVHNode *children[4]; - const int num_children = e.node->num_children(); - /* Push entries on the stack. */ - for (int i = 0; i < num_children; ++i) { - int idx; - children[i] = e.node->get_child(i); - assert(children[i] != NULL); - if (children[i]->is_leaf()) { - idx = nextLeafNodeIdx++; - } - else { - idx = nextNodeIdx; - nextNodeIdx += children[i]->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE : BVH_QNODE_SIZE; - } - stack.push_back(BVHStackEntry(children[i], idx)); - } - /* Set node. */ - pack_inner(e, &stack[stack.size() - num_children], num_children); - } - } - - assert(node_size == nextNodeIdx); - /* Root index to start traversal at, to handle case of single leaf node. */ - pack.root_index = (root->is_leaf()) ? -1 : 0; -} - -void BVH4::refit_nodes() -{ - assert(!params.top_level); - - BoundBox bbox = BoundBox::empty; - uint visibility = 0; - refit_node(0, (pack.root_index == -1) ? true : false, bbox, visibility); -} - -void BVH4::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility) -{ - if (leaf) { - /* Refit leaf node. */ - int4 *data = &pack.leaf_nodes[idx]; - int4 c = data[0]; - - BVH::refit_primitives(c.x, c.y, bbox, visibility); - - /* TODO(sergey): This is actually a copy of pack_leaf(), - * but this chunk of code only knows actual data and has - * no idea about BVHNode. - * - * Would be nice to de-duplicate code, but trying to make - * making code more general ends up in much nastier code - * in my opinion so far. - * - * Same applies to the inner nodes case below. - */ - float4 leaf_data[BVH_QNODE_LEAF_SIZE]; - leaf_data[0].x = __int_as_float(c.x); - leaf_data[0].y = __int_as_float(c.y); - leaf_data[0].z = __uint_as_float(visibility); - leaf_data[0].w = __uint_as_float(c.w); - memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_QNODE_LEAF_SIZE); - } - else { - int4 *data = &pack.nodes[idx]; - bool is_unaligned = (data[0].x & PATH_RAY_NODE_UNALIGNED) != 0; - int4 c; - if (is_unaligned) { - c = data[13]; - } - else { - c = data[7]; - } - /* Refit inner node, set bbox from children. */ - BoundBox child_bbox[4] = {BoundBox::empty, BoundBox::empty, BoundBox::empty, BoundBox::empty}; - uint child_visibility[4] = {0}; - int num_nodes = 0; - - for (int i = 0; i < 4; ++i) { - if (c[i] != 0) { - refit_node((c[i] < 0) ? -c[i] - 1 : c[i], (c[i] < 0), child_bbox[i], child_visibility[i]); - ++num_nodes; - bbox.grow(child_bbox[i]); - visibility |= child_visibility[i]; - } - } - - if (is_unaligned) { - Transform aligned_space[4] = { - transform_identity(), transform_identity(), transform_identity(), transform_identity()}; - pack_unaligned_node( - idx, aligned_space, child_bbox, &c[0], visibility, 0.0f, 1.0f, num_nodes); - } - else { - pack_aligned_node(idx, child_bbox, &c[0], visibility, 0.0f, 1.0f, num_nodes); - } - } -} - -CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh4.h b/intern/cycles/bvh/bvh4.h deleted file mode 100644 index afbb9007afb..00000000000 --- a/intern/cycles/bvh/bvh4.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Adapted from code copyright 2009-2010 NVIDIA Corporation - * Modifications Copyright 2011, 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 __BVH4_H__ -#define __BVH4_H__ - -#include "bvh/bvh.h" -#include "bvh/bvh_params.h" - -#include "util/util_types.h" -#include "util/util_vector.h" - -CCL_NAMESPACE_BEGIN - -class BVHNode; -struct BVHStackEntry; -class BVHParams; -class BoundBox; -class LeafNode; -class Object; -class Progress; - -#define BVH_QNODE_SIZE 8 -#define BVH_QNODE_LEAF_SIZE 1 -#define BVH_UNALIGNED_QNODE_SIZE 14 - -/* BVH4 - * - * Quad BVH, with each node having four children, to use with SIMD instructions. - */ -class BVH4 : public BVH { - protected: - /* constructor */ - friend class BVH; - BVH4(const BVHParams ¶ms, - const vector<Geometry *> &geometry, - const vector<Object *> &objects); - - /* Building process. */ - virtual BVHNode *widen_children_nodes(const BVHNode *root) override; - - /* pack */ - void pack_nodes(const BVHNode *root) override; - - void pack_leaf(const BVHStackEntry &e, const LeafNode *leaf); - void pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num); - - void pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num); - void pack_aligned_node(int idx, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num); - - void pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num); - void pack_unaligned_node(int idx, - const Transform *aligned_space, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num); - - /* refit */ - void refit_nodes() override; - void refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility); -}; - -CCL_NAMESPACE_END - -#endif /* __BVH4_H__ */ diff --git a/intern/cycles/bvh/bvh8.cpp b/intern/cycles/bvh/bvh8.cpp deleted file mode 100644 index b805865b2c8..00000000000 --- a/intern/cycles/bvh/bvh8.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Original code Copyright 2017, Intel Corporation - * Modifications Copyright 2018, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "bvh/bvh8.h" - -#include "render/hair.h" -#include "render/mesh.h" -#include "render/object.h" - -#include "bvh/bvh_node.h" -#include "bvh/bvh_unaligned.h" - -CCL_NAMESPACE_BEGIN - -BVH8::BVH8(const BVHParams ¶ms_, - const vector<Geometry *> &geometry_, - const vector<Object *> &objects_) - : BVH(params_, geometry_, objects_) -{ -} - -namespace { - -BVHNode *bvh_node_merge_children_recursively(const BVHNode *node) -{ - if (node->is_leaf()) { - return new LeafNode(*reinterpret_cast<const LeafNode *>(node)); - } - /* Collect nodes of two layer deeper, allowing us to have more childrem in - * an inner layer. */ - assert(node->num_children() <= 2); - const BVHNode *children[8]; - const BVHNode *child0 = node->get_child(0); - const BVHNode *child1 = node->get_child(1); - int num_children = 0; - if (child0->is_leaf()) { - children[num_children++] = child0; - } - else { - const BVHNode *child00 = child0->get_child(0), *child01 = child0->get_child(1); - if (child00->is_leaf()) { - children[num_children++] = child00; - } - else { - children[num_children++] = child00->get_child(0); - children[num_children++] = child00->get_child(1); - } - if (child01->is_leaf()) { - children[num_children++] = child01; - } - else { - children[num_children++] = child01->get_child(0); - children[num_children++] = child01->get_child(1); - } - } - if (child1->is_leaf()) { - children[num_children++] = child1; - } - else { - const BVHNode *child10 = child1->get_child(0), *child11 = child1->get_child(1); - if (child10->is_leaf()) { - children[num_children++] = child10; - } - else { - children[num_children++] = child10->get_child(0); - children[num_children++] = child10->get_child(1); - } - if (child11->is_leaf()) { - children[num_children++] = child11; - } - else { - children[num_children++] = child11->get_child(0); - children[num_children++] = child11->get_child(1); - } - } - /* Merge children in subtrees. */ - BVHNode *children4[8]; - for (int i = 0; i < num_children; ++i) { - children4[i] = bvh_node_merge_children_recursively(children[i]); - } - /* Allocate new node. */ - BVHNode *node8 = new InnerNode(node->bounds, children4, num_children); - /* TODO(sergey): Consider doing this from the InnerNode() constructor. - * But in order to do this nicely need to think of how to pass all the - * parameters there. */ - if (node->is_unaligned) { - node8->is_unaligned = true; - node8->aligned_space = new Transform(); - *node8->aligned_space = *node->aligned_space; - } - return node8; -} - -} // namespace - -BVHNode *BVH8::widen_children_nodes(const BVHNode *root) -{ - if (root == NULL) { - return NULL; - } - if (root->is_leaf()) { - return const_cast<BVHNode *>(root); - } - BVHNode *root8 = bvh_node_merge_children_recursively(root); - /* TODO(sergey): Pack children nodes to parents which has less that 4 - * children. */ - return root8; -} - -void BVH8::pack_leaf(const BVHStackEntry &e, const LeafNode *leaf) -{ - float4 data[BVH_ONODE_LEAF_SIZE]; - memset(data, 0, sizeof(data)); - if (leaf->num_triangles() == 1 && pack.prim_index[leaf->lo] == -1) { - /* object */ - data[0].x = __int_as_float(~(leaf->lo)); - data[0].y = __int_as_float(0); - } - else { - /* triangle */ - data[0].x = __int_as_float(leaf->lo); - data[0].y = __int_as_float(leaf->hi); - } - data[0].z = __uint_as_float(leaf->visibility); - if (leaf->num_triangles() != 0) { - data[0].w = __uint_as_float(pack.prim_type[leaf->lo]); - } - - memcpy(&pack.leaf_nodes[e.idx], data, sizeof(float4) * BVH_ONODE_LEAF_SIZE); -} - -void BVH8::pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) -{ - bool has_unaligned = false; - /* Check whether we have to create unaligned node or all nodes are aligned - * and we can cut some corner here. - */ - if (params.use_unaligned_nodes) { - for (int i = 0; i < num; i++) { - if (en[i].node->is_unaligned) { - has_unaligned = true; - break; - } - } - } - if (has_unaligned) { - /* There's no unaligned children, pack into AABB node. */ - pack_unaligned_inner(e, en, num); - } - else { - /* Create unaligned node with orientation transform for each of the - * children. - */ - pack_aligned_inner(e, en, num); - } -} - -void BVH8::pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) -{ - BoundBox bounds[8]; - int child[8]; - for (int i = 0; i < num; ++i) { - bounds[i] = en[i].node->bounds; - child[i] = en[i].encodeIdx(); - } - pack_aligned_node( - e.idx, bounds, child, e.node->visibility, e.node->time_from, e.node->time_to, num); -} - -void BVH8::pack_aligned_node(int idx, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num) -{ - float8 data[8]; - memset(data, 0, sizeof(data)); - - data[0].a = __uint_as_float(visibility & ~PATH_RAY_NODE_UNALIGNED); - data[0].b = time_from; - data[0].c = time_to; - - for (int i = 0; i < num; i++) { - float3 bb_min = bounds[i].min; - float3 bb_max = bounds[i].max; - - data[1][i] = bb_min.x; - data[2][i] = bb_max.x; - data[3][i] = bb_min.y; - data[4][i] = bb_max.y; - data[5][i] = bb_min.z; - data[6][i] = bb_max.z; - - data[7][i] = __int_as_float(child[i]); - } - - for (int i = num; i < 8; i++) { - /* We store BB which would never be recorded as intersection - * so kernel might safely assume there are always 4 child nodes. - */ - data[1][i] = FLT_MAX; - data[2][i] = -FLT_MAX; - - data[3][i] = FLT_MAX; - data[4][i] = -FLT_MAX; - - data[5][i] = FLT_MAX; - data[6][i] = -FLT_MAX; - - data[7][i] = __int_as_float(0); - } - - memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_ONODE_SIZE); -} - -void BVH8::pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num) -{ - Transform aligned_space[8]; - BoundBox bounds[8]; - int child[8]; - for (int i = 0; i < num; ++i) { - aligned_space[i] = en[i].node->get_aligned_space(); - bounds[i] = en[i].node->bounds; - child[i] = en[i].encodeIdx(); - } - pack_unaligned_node(e.idx, - aligned_space, - bounds, - child, - e.node->visibility, - e.node->time_from, - e.node->time_to, - num); -} - -void BVH8::pack_unaligned_node(int idx, - const Transform *aligned_space, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num) -{ - float8 data[BVH_UNALIGNED_ONODE_SIZE]; - memset(data, 0, sizeof(data)); - - data[0].a = __uint_as_float(visibility | PATH_RAY_NODE_UNALIGNED); - data[0].b = time_from; - data[0].c = time_to; - - for (int i = 0; i < num; i++) { - Transform space = BVHUnaligned::compute_node_transform(bounds[i], aligned_space[i]); - - data[1][i] = space.x.x; - data[2][i] = space.x.y; - data[3][i] = space.x.z; - - data[4][i] = space.y.x; - data[5][i] = space.y.y; - data[6][i] = space.y.z; - - data[7][i] = space.z.x; - data[8][i] = space.z.y; - data[9][i] = space.z.z; - - data[10][i] = space.x.w; - data[11][i] = space.y.w; - data[12][i] = space.z.w; - - data[13][i] = __int_as_float(child[i]); - } - - for (int i = num; i < 8; i++) { - /* We store BB which would never be recorded as intersection - * so kernel might safely assume there are always 4 child nodes. - */ - - data[1][i] = NAN; - data[2][i] = NAN; - data[3][i] = NAN; - - data[4][i] = NAN; - data[5][i] = NAN; - data[6][i] = NAN; - - data[7][i] = NAN; - data[8][i] = NAN; - data[9][i] = NAN; - - data[10][i] = NAN; - data[11][i] = NAN; - data[12][i] = NAN; - - data[13][i] = __int_as_float(0); - } - - memcpy(&pack.nodes[idx], data, sizeof(float4) * BVH_UNALIGNED_ONODE_SIZE); -} - -/* Quad SIMD Nodes */ - -void BVH8::pack_nodes(const BVHNode *root) -{ - /* Calculate size of the arrays required. */ - const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT); - const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); - assert(num_leaf_nodes <= num_nodes); - const size_t num_inner_nodes = num_nodes - num_leaf_nodes; - size_t node_size; - if (params.use_unaligned_nodes) { - const size_t num_unaligned_nodes = root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT); - node_size = (num_unaligned_nodes * BVH_UNALIGNED_ONODE_SIZE) + - (num_inner_nodes - num_unaligned_nodes) * BVH_ONODE_SIZE; - } - else { - node_size = num_inner_nodes * BVH_ONODE_SIZE; - } - /* Resize arrays. */ - pack.nodes.clear(); - pack.leaf_nodes.clear(); - /* For top level BVH, first merge existing BVH's so we know the offsets. */ - if (params.top_level) { - pack_instances(node_size, num_leaf_nodes * BVH_ONODE_LEAF_SIZE); - } - else { - pack.nodes.resize(node_size); - pack.leaf_nodes.resize(num_leaf_nodes * BVH_ONODE_LEAF_SIZE); - } - - int nextNodeIdx = 0, nextLeafNodeIdx = 0; - - vector<BVHStackEntry> stack; - stack.reserve(BVHParams::MAX_DEPTH * 2); - if (root->is_leaf()) { - stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); - } - else { - stack.push_back(BVHStackEntry(root, nextNodeIdx)); - nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE : BVH_ONODE_SIZE; - } - - while (stack.size()) { - BVHStackEntry e = stack.back(); - stack.pop_back(); - - if (e.node->is_leaf()) { - /* leaf node */ - const LeafNode *leaf = reinterpret_cast<const LeafNode *>(e.node); - pack_leaf(e, leaf); - } - else { - /* Inner node. */ - /* Collect nodes. */ - const BVHNode *children[8]; - int num_children = e.node->num_children(); - /* Push entries on the stack. */ - for (int i = 0; i < num_children; ++i) { - int idx; - children[i] = e.node->get_child(i); - if (children[i]->is_leaf()) { - idx = nextLeafNodeIdx++; - } - else { - idx = nextNodeIdx; - nextNodeIdx += children[i]->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE : BVH_ONODE_SIZE; - } - stack.push_back(BVHStackEntry(children[i], idx)); - } - /* Set node. */ - pack_inner(e, &stack[stack.size() - num_children], num_children); - } - } - - assert(node_size == nextNodeIdx); - /* Root index to start traversal at, to handle case of single leaf node. */ - pack.root_index = (root->is_leaf()) ? -1 : 0; -} - -void BVH8::refit_nodes() -{ - assert(!params.top_level); - - BoundBox bbox = BoundBox::empty; - uint visibility = 0; - refit_node(0, (pack.root_index == -1) ? true : false, bbox, visibility); -} - -void BVH8::refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility) -{ - if (leaf) { - int4 *data = &pack.leaf_nodes[idx]; - int4 c = data[0]; - /* Refit leaf node. */ - for (int prim = c.x; prim < c.y; prim++) { - int pidx = pack.prim_index[prim]; - int tob = pack.prim_object[prim]; - Object *ob = objects[tob]; - - if (pidx == -1) { - /* Object instance. */ - bbox.grow(ob->bounds); - } - else { - /* Primitives. */ - if (pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { - /* Curves. */ - const Hair *hair = static_cast<const Hair *>(ob->geometry); - int prim_offset = (params.top_level) ? hair->prim_offset : 0; - Hair::Curve curve = hair->get_curve(pidx - prim_offset); - int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); - - curve.bounds_grow(k, &hair->curve_keys[0], &hair->curve_radius[0], bbox); - - /* Motion curves. */ - if (hair->use_motion_blur) { - Attribute *attr = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if (attr) { - size_t hair_size = hair->curve_keys.size(); - size_t steps = hair->motion_steps - 1; - float3 *key_steps = attr->data_float3(); - - for (size_t i = 0; i < steps; i++) { - curve.bounds_grow(k, key_steps + i * hair_size, &hair->curve_radius[0], bbox); - } - } - } - } - else { - /* Triangles. */ - const Mesh *mesh = static_cast<const Mesh *>(ob->geometry); - int prim_offset = (params.top_level) ? mesh->prim_offset : 0; - Mesh::Triangle triangle = mesh->get_triangle(pidx - prim_offset); - const float3 *vpos = &mesh->verts[0]; - - triangle.bounds_grow(vpos, bbox); - - /* Motion triangles. */ - if (mesh->use_motion_blur) { - Attribute *attr = mesh->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); - - if (attr) { - size_t mesh_size = mesh->verts.size(); - size_t steps = mesh->motion_steps - 1; - float3 *vert_steps = attr->data_float3(); - - for (size_t i = 0; i < steps; i++) { - triangle.bounds_grow(vert_steps + i * mesh_size, bbox); - } - } - } - } - } - - visibility |= ob->visibility; - } - - float4 leaf_data[BVH_ONODE_LEAF_SIZE]; - leaf_data[0].x = __int_as_float(c.x); - leaf_data[0].y = __int_as_float(c.y); - leaf_data[0].z = __uint_as_float(visibility); - leaf_data[0].w = __uint_as_float(c.w); - memcpy(&pack.leaf_nodes[idx], leaf_data, sizeof(float4) * BVH_ONODE_LEAF_SIZE); - } - else { - float8 *data = (float8 *)&pack.nodes[idx]; - bool is_unaligned = (__float_as_uint(data[0].a) & PATH_RAY_NODE_UNALIGNED) != 0; - /* Refit inner node, set bbox from children. */ - BoundBox child_bbox[8] = {BoundBox::empty, - BoundBox::empty, - BoundBox::empty, - BoundBox::empty, - BoundBox::empty, - BoundBox::empty, - BoundBox::empty, - BoundBox::empty}; - int child[8]; - uint child_visibility[8] = {0}; - int num_nodes = 0; - - for (int i = 0; i < 8; ++i) { - child[i] = __float_as_int(data[(is_unaligned) ? 13 : 7][i]); - - if (child[i] != 0) { - refit_node((child[i] < 0) ? -child[i] - 1 : child[i], - (child[i] < 0), - child_bbox[i], - child_visibility[i]); - ++num_nodes; - bbox.grow(child_bbox[i]); - visibility |= child_visibility[i]; - } - } - - if (is_unaligned) { - Transform aligned_space[8] = {transform_identity(), - transform_identity(), - transform_identity(), - transform_identity(), - transform_identity(), - transform_identity(), - transform_identity(), - transform_identity()}; - pack_unaligned_node( - idx, aligned_space, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes); - } - else { - pack_aligned_node(idx, child_bbox, child, visibility, 0.0f, 1.0f, num_nodes); - } - } -} - -CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh8.h b/intern/cycles/bvh/bvh8.h deleted file mode 100644 index d23fa528e3e..00000000000 --- a/intern/cycles/bvh/bvh8.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Original code Copyright 2017, Intel Corporation - * Modifications Copyright 2018, Blender Foundation. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef __BVH8_H__ -#define __BVH8_H__ - -#include "bvh/bvh.h" -#include "bvh/bvh_params.h" - -#include "util/util_types.h" -#include "util/util_vector.h" - -CCL_NAMESPACE_BEGIN - -class BVHNode; -struct BVHStackEntry; -class BVHParams; -class BoundBox; -class LeafNode; -class Object; -class Progress; - -#define BVH_ONODE_SIZE 16 -#define BVH_ONODE_LEAF_SIZE 1 -#define BVH_UNALIGNED_ONODE_SIZE 28 - -/* BVH8 - * - * Octo BVH, with each node having eight children, to use with SIMD instructions. - */ -class BVH8 : public BVH { - protected: - /* constructor */ - friend class BVH; - BVH8(const BVHParams ¶ms, - const vector<Geometry *> &geometry, - const vector<Object *> &objects); - - /* Building process. */ - virtual BVHNode *widen_children_nodes(const BVHNode *root) override; - - /* pack */ - void pack_nodes(const BVHNode *root) override; - - void pack_leaf(const BVHStackEntry &e, const LeafNode *leaf); - void pack_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num); - - void pack_aligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num); - void pack_aligned_node(int idx, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num); - - void pack_unaligned_inner(const BVHStackEntry &e, const BVHStackEntry *en, int num); - void pack_unaligned_node(int idx, - const Transform *aligned_space, - const BoundBox *bounds, - const int *child, - const uint visibility, - const float time_from, - const float time_to, - const int num); - - /* refit */ - void refit_nodes() override; - void refit_node(int idx, bool leaf, BoundBox &bbox, uint &visibility); -}; - -CCL_NAMESPACE_END - -#endif /* __BVH8_H__ */ diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 814b5ced5d2..86ab7b00815 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -39,48 +39,6 @@ CCL_NAMESPACE_BEGIN -/* BVH Build Task */ - -class BVHBuildTask : public Task { - public: - BVHBuildTask( - BVHBuild *build, InnerNode *node, int child, const BVHObjectBinning &range, int level) - : range_(range) - { - run = function_bind(&BVHBuild::thread_build_node, build, node, child, &range_, level); - } - - private: - BVHObjectBinning range_; -}; - -class BVHSpatialSplitBuildTask : public Task { - public: - BVHSpatialSplitBuildTask(BVHBuild *build, - InnerNode *node, - int child, - const BVHRange &range, - const vector<BVHReference> &references, - int level) - : range_(range), - references_(references.begin() + range.start(), references.begin() + range.end()) - { - range_.set_start(0); - run = function_bind(&BVHBuild::thread_build_spatial_split_node, - build, - node, - child, - &range_, - &references_, - level, - _1); - } - - private: - BVHRange range_; - vector<BVHReference> references_; -}; - /* Constructor / Destructor */ BVHBuild::BVHBuild(const vector<Object *> &objects_, @@ -201,6 +159,13 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair if (hair->has_motion_blur()) { curve_attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); } + + const PrimitiveType primitive_type = + (curve_attr_mP != NULL) ? + ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : + PRIMITIVE_MOTION_CURVE_THICK) : + ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK); + const size_t num_curves = hair->num_curves(); for (uint j = 0; j < num_curves; j++) { const Hair::Curve curve = hair->get_curve(j); @@ -211,7 +176,7 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair BoundBox bounds = BoundBox::empty; curve.bounds_grow(k, &hair->curve_keys[0], curve_radius, bounds); if (bounds.valid()) { - int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_CURVE, k); + int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k); references.push_back(BVHReference(bounds, j, i, packed_type)); root.grow(bounds); center.grow(bounds.center2()); @@ -232,7 +197,7 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair curve.bounds_grow(k, key_steps + step * num_keys, curve_radius, bounds); } if (bounds.valid()) { - int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); + int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k); references.push_back(BVHReference(bounds, j, i, packed_type)); root.grow(bounds); center.grow(bounds.center2()); @@ -288,7 +253,7 @@ void BVHBuild::add_reference_curves(BoundBox &root, BoundBox ¢er, Hair *hair bounds.grow(curr_bounds); if (bounds.valid()) { const float prev_time = (float)(bvh_step - 1) * num_bvh_steps_inv_1; - int packed_type = PRIMITIVE_PACK_SEGMENT(PRIMITIVE_MOTION_CURVE, k); + int packed_type = PRIMITIVE_PACK_SEGMENT(primitive_type, k); references.push_back(BVHReference(bounds, j, i, packed_type, prev_time, curr_time)); root.grow(bounds); center.grow(bounds.center2()); @@ -423,22 +388,6 @@ BVHNode *BVHBuild::run() } spatial_min_overlap = root.bounds().safe_area() * params.spatial_split_alpha; - if (params.use_spatial_split) { - /* NOTE: The API here tries to be as much ready for multi-threaded build - * as possible, but at the same time it tries not to introduce any - * changes in behavior for until all refactoring needed for threading is - * finished. - * - * So we currently allocate single storage for now, which is only used by - * the only thread working on the spatial BVH build. - */ - spatial_storage.resize(TaskScheduler::num_threads() + 1); - size_t num_bins = max(root.size(), (int)BVHParams::NUM_SPATIAL_BINS) - 1; - foreach (BVHSpatialStorage &storage, spatial_storage) { - storage.right_bounds.clear(); - } - spatial_storage[0].right_bounds.resize(num_bins); - } spatial_free_index = 0; need_prim_time = params.num_motion_curve_steps > 0 || params.num_motion_triangle_steps > 0; @@ -465,7 +414,8 @@ BVHNode *BVHBuild::run() if (params.use_spatial_split) { /* Perform multithreaded spatial split build. */ - rootnode = build_node(root, &references, 0, 0); + BVHSpatialStorage *local_storage = &spatial_storage.local(); + rootnode = build_node(root, references, 0, local_storage); task_pool.wait_work(); } else { @@ -475,6 +425,9 @@ BVHNode *BVHBuild::run() task_pool.wait_work(); } + /* clean up temporary memory usage by threads */ + spatial_storage.clear(); + /* delete if we canceled */ if (rootnode) { if (progress.get_cancel()) { @@ -529,41 +482,46 @@ void BVHBuild::progress_update() progress_start_time = time_dt(); } -void BVHBuild::thread_build_node(InnerNode *inner, int child, BVHObjectBinning *range, int level) +void BVHBuild::thread_build_node(InnerNode *inner, + int child, + const BVHObjectBinning &range, + int level) { if (progress.get_cancel()) return; /* build nodes */ - BVHNode *node = build_node(*range, level); + BVHNode *node = build_node(range, level); /* set child in inner node */ inner->children[child] = node; /* update progress */ - if (range->size() < THREAD_TASK_SIZE) { + if (range.size() < THREAD_TASK_SIZE) { /*rotate(node, INT_MAX, 5);*/ thread_scoped_lock lock(build_mutex); - progress_count += range->size(); + progress_count += range.size(); progress_update(); } } void BVHBuild::thread_build_spatial_split_node(InnerNode *inner, int child, - BVHRange *range, - vector<BVHReference> *references, - int level, - int thread_id) + const BVHRange &range, + vector<BVHReference> &references, + int level) { if (progress.get_cancel()) { return; } + /* Get per-thread memory for spatial split. */ + BVHSpatialStorage *local_storage = &spatial_storage.local(); + /* build nodes */ - BVHNode *node = build_node(*range, references, level, thread_id); + BVHNode *node = build_node(range, references, level, local_storage); /* set child in inner node */ inner->children[child] = node; @@ -586,14 +544,22 @@ bool BVHBuild::range_within_max_leaf_size(const BVHRange &range, for (int i = 0; i < size; i++) { const BVHReference &ref = references[range.start() + i]; - if (ref.prim_type() & PRIMITIVE_CURVE) - num_curves++; - if (ref.prim_type() & PRIMITIVE_MOTION_CURVE) - num_motion_curves++; - else if (ref.prim_type() & PRIMITIVE_TRIANGLE) - num_triangles++; - else if (ref.prim_type() & PRIMITIVE_MOTION_TRIANGLE) - num_motion_triangles++; + if (ref.prim_type() & PRIMITIVE_ALL_CURVE) { + if (ref.prim_type() & PRIMITIVE_ALL_MOTION) { + num_motion_curves++; + } + else { + num_curves++; + } + } + else if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { + if (ref.prim_type() & PRIMITIVE_ALL_MOTION) { + num_motion_triangles++; + } + else { + num_triangles++; + } + } } return (num_triangles <= params.max_triangle_leaf_size) && @@ -675,8 +641,8 @@ BVHNode *BVHBuild::build_node(const BVHObjectBinning &range, int level) /* Threaded build */ inner = new InnerNode(bounds); - task_pool.push(new BVHBuildTask(this, inner, 0, left, level + 1), true); - task_pool.push(new BVHBuildTask(this, inner, 1, right, level + 1), true); + task_pool.push([=] { thread_build_node(inner, 0, left, level + 1); }); + task_pool.push([=] { thread_build_node(inner, 1, right, level + 1); }); } if (do_unalinged_split) { @@ -688,9 +654,9 @@ BVHNode *BVHBuild::build_node(const BVHObjectBinning &range, int level) /* multithreaded spatial split builder */ BVHNode *BVHBuild::build_node(const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, int level, - int thread_id) + BVHSpatialStorage *storage) { /* Update progress. * @@ -707,18 +673,17 @@ BVHNode *BVHBuild::build_node(const BVHRange &range, if (!(range.size() > 0 && params.top_level && level == 0)) { if (params.small_enough_for_leaf(range.size(), level)) { progress_count += range.size(); - return create_leaf_node(range, *references); + return create_leaf_node(range, references); } } /* Perform splitting test. */ - BVHSpatialStorage *storage = &spatial_storage[thread_id]; BVHMixedSplit split(this, storage, range, references, level); if (!(range.size() > 0 && params.top_level && level == 0)) { if (split.no_split) { progress_count += range.size(); - return create_leaf_node(range, *references); + return create_leaf_node(range, references); } } float leafSAH = params.sah_primitive_cost * split.leafSAH; @@ -731,7 +696,7 @@ BVHNode *BVHBuild::build_node(const BVHRange &range, Transform aligned_space; bool do_unalinged_split = false; if (params.use_unaligned_nodes && splitSAH > params.unaligned_split_threshold * leafSAH) { - aligned_space = unaligned_heuristic.compute_aligned_space(range, &references->at(0)); + aligned_space = unaligned_heuristic.compute_aligned_space(range, &references.at(0)); unaligned_split = BVHMixedSplit( this, storage, range, references, level, &unaligned_heuristic, &aligned_space); /* unalignedLeafSAH = params.sah_primitive_cost * split.leafSAH; */ @@ -757,8 +722,7 @@ BVHNode *BVHBuild::build_node(const BVHRange &range, BoundBox bounds; if (do_unalinged_split) { - bounds = unaligned_heuristic.compute_aligned_boundbox( - range, &references->at(0), aligned_space); + bounds = unaligned_heuristic.compute_aligned_boundbox(range, &references.at(0), aligned_space); } else { bounds = range.bounds(); @@ -770,24 +734,35 @@ BVHNode *BVHBuild::build_node(const BVHRange &range, /* Local build. */ /* Build left node. */ - vector<BVHReference> copy(references->begin() + right.start(), - references->begin() + right.end()); + vector<BVHReference> right_references(references.begin() + right.start(), + references.begin() + right.end()); right.set_start(0); - BVHNode *leftnode = build_node(left, references, level + 1, thread_id); + BVHNode *leftnode = build_node(left, references, level + 1, storage); /* Build right node. */ - BVHNode *rightnode = build_node(right, ©, level + 1, thread_id); + BVHNode *rightnode = build_node(right, right_references, level + 1, storage); inner = new InnerNode(bounds, leftnode, rightnode); } else { /* Threaded build. */ inner = new InnerNode(bounds); - task_pool.push(new BVHSpatialSplitBuildTask(this, inner, 0, left, *references, level + 1), - true); - task_pool.push(new BVHSpatialSplitBuildTask(this, inner, 1, right, *references, level + 1), - true); + + vector<BVHReference> left_references(references.begin() + left.start(), + references.begin() + left.end()); + vector<BVHReference> right_references(references.begin() + right.start(), + references.begin() + right.end()); + right.set_start(0); + + /* Create tasks for left and right nodes, using copy for most arguments and + * move for reference to avoid memory copies. */ + task_pool.push([=, refs = std::move(left_references)]() mutable { + thread_build_spatial_split_node(inner, 0, left, refs, level + 1); + }); + task_pool.push([=, refs = std::move(right_references)]() mutable { + thread_build_spatial_split_node(inner, 1, right, refs, level + 1); + }); } if (do_unalinged_split) { diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 3fe4c3799e2..c35af083fbd 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -74,9 +74,9 @@ class BVHBuild { /* Building. */ BVHNode *build_node(const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, int level, - int thread_id); + BVHSpatialStorage *storage); BVHNode *build_node(const BVHObjectBinning &range, int level); BVHNode *create_leaf_node(const BVHRange &range, const vector<BVHReference> &references); BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num); @@ -86,13 +86,12 @@ class BVHBuild { /* Threads. */ enum { THREAD_TASK_SIZE = 4096 }; - void thread_build_node(InnerNode *node, int child, BVHObjectBinning *range, int level); + void thread_build_node(InnerNode *node, int child, const BVHObjectBinning &range, int level); void thread_build_spatial_split_node(InnerNode *node, int child, - BVHRange *range, - vector<BVHReference> *references, - int level, - int thread_id); + const BVHRange &range, + vector<BVHReference> &references, + int level); thread_mutex build_mutex; /* Progress. */ @@ -127,7 +126,7 @@ class BVHBuild { /* Spatial splitting. */ float spatial_min_overlap; - vector<BVHSpatialStorage> spatial_storage; + enumerable_thread_specific<BVHSpatialStorage> spatial_storage; size_t spatial_free_index; thread_spin_lock spatial_spin_lock; diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 6735202835b..17e1f86a589 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -47,9 +47,11 @@ # include "render/hair.h" # include "render/mesh.h" # include "render/object.h" + # include "util/util_foreach.h" # include "util/util_logging.h" # include "util/util_progress.h" +# include "util/util_stats.h" CCL_NAMESPACE_BEGIN @@ -65,30 +67,9 @@ static_assert(Object::MAX_MOTION_STEPS == Geometry::MAX_MOTION_STEPS, * as well as filtering for volume objects happen here. * Cycles' own BVH does that directly inside the traversal calls. */ -static void rtc_filter_func(const RTCFilterFunctionNArguments *args) -{ - /* Current implementation in Cycles assumes only single-ray intersection queries. */ - assert(args->N == 1); - - const RTCRay *ray = (RTCRay *)args->ray; - const RTCHit *hit = (RTCHit *)args->hit; - CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; - KernelGlobals *kg = ctx->kg; - - /* Check if there is backfacing hair to ignore. */ - if (IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) && - !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) && - !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) { - if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z), - make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) { - *args->valid = 0; - return; - } - } -} - static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) { + /* Current implementation in Cycles assumes only single-ray intersection queries. */ assert(args->N == 1); const RTCRay *ray = (RTCRay *)args->ray; @@ -96,17 +77,6 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) CCLIntersectContext *ctx = ((IntersectContext *)args->context)->userRayExt; KernelGlobals *kg = ctx->kg; - /* For all ray types: Check if there is backfacing hair to ignore */ - if (IS_HAIR(hit->geomID) && (kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) && - !(kernel_data.curve.curveflags & CURVE_KN_BACKFACING) && - !(kernel_data.curve.curveflags & CURVE_KN_RIBBONS)) { - if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z), - make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) { - *args->valid = 0; - return; - } - } - switch (ctx->type) { case CCLIntersectContext::RAY_SHADOW_ALL: { /* Append the intersection to the end of the array. */ @@ -168,7 +138,7 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) } /* Ignore curves. */ - if (hit->geomID & 1) { + if (IS_HAIR(hit->geomID)) { /* This tells Embree to continue tracing. */ *args->valid = 0; break; @@ -249,6 +219,34 @@ static void rtc_filter_occluded_func(const RTCFilterFunctionNArguments *args) } } +static void rtc_filter_func_thick_curve(const RTCFilterFunctionNArguments *args) +{ + const RTCRay *ray = (RTCRay *)args->ray; + RTCHit *hit = (RTCHit *)args->hit; + + /* Always ignore backfacing intersections. */ + if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z), + make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) { + *args->valid = 0; + return; + } +} + +static void rtc_filter_occluded_func_thick_curve(const RTCFilterFunctionNArguments *args) +{ + const RTCRay *ray = (RTCRay *)args->ray; + RTCHit *hit = (RTCHit *)args->hit; + + /* Always ignore backfacing intersections. */ + if (dot(make_float3(ray->dir_x, ray->dir_y, ray->dir_z), + make_float3(hit->Ng_x, hit->Ng_y, hit->Ng_z)) > 0.0f) { + *args->valid = 0; + return; + } + + rtc_filter_occluded_func(args); +} + static size_t unaccounted_mem = 0; static bool rtc_memory_monitor_func(void *userPtr, const ssize_t bytes, const bool) @@ -326,8 +324,6 @@ BVHEmbree::BVHEmbree(const BVHParams ¶ms_, stats(NULL), curve_subdivisions(params.curve_subdivisions), build_quality(RTC_BUILD_QUALITY_REFIT), - use_curves(params_.curve_flags & CURVE_KN_INTERPOLATE), - use_ribbons(params.curve_flags & CURVE_KN_RIBBONS), dynamic_scene(true) { _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); @@ -653,7 +649,6 @@ void BVHEmbree::add_triangles(const Object *ob, const Mesh *mesh, int i) } rtcSetGeometryUserData(geom_id, (void *)prim_offset); - rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func); rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); @@ -724,9 +719,7 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair /* Catmull-Rom splines need extra CVs at the beginning and end of each curve. */ size_t num_keys_embree = num_keys; - if (use_curves) { - num_keys_embree += num_curves * 2; - } + num_keys_embree += num_curves * 2; /* Copy the CV data to Embree */ const int t_mid = (num_motion_steps - 1) / 2; @@ -746,45 +739,22 @@ void BVHEmbree::update_curve_vertex_buffer(RTCGeometry geom_id, const Hair *hair assert(rtc_verts); if (rtc_verts) { - if (use_curves) { - const size_t num_curves = hair->num_curves(); - for (size_t j = 0; j < num_curves; ++j) { - Hair::Curve c = hair->get_curve(j); - int fk = c.first_key; - int k = 1; - for (; k < c.num_keys + 1; ++k, ++fk) { - rtc_verts[k] = float3_to_float4(verts[fk]); - rtc_verts[k].w = curve_radius[fk]; - } - /* Duplicate Embree's Catmull-Rom spline CVs at the start and end of each curve. */ - rtc_verts[0] = rtc_verts[1]; - rtc_verts[k] = rtc_verts[k - 1]; - rtc_verts += c.num_keys + 2; - } - } - else { - for (size_t j = 0; j < num_keys_embree; ++j) { - rtc_verts[j] = float3_to_float4(verts[j]); - rtc_verts[j].w = curve_radius[j]; + const size_t num_curves = hair->num_curves(); + for (size_t j = 0; j < num_curves; ++j) { + Hair::Curve c = hair->get_curve(j); + int fk = c.first_key; + int k = 1; + for (; k < c.num_keys + 1; ++k, ++fk) { + rtc_verts[k] = float3_to_float4(verts[fk]); + rtc_verts[k].w = curve_radius[fk]; } + /* Duplicate Embree's Catmull-Rom spline CVs at the start and end of each curve. */ + rtc_verts[0] = rtc_verts[1]; + rtc_verts[k] = rtc_verts[k - 1]; + rtc_verts += c.num_keys + 2; } } } -# if RTC_VERSION >= 30900 - if (!use_curves) { - unsigned char *flags = (unsigned char *)rtcSetNewGeometryBuffer(geom_id, - RTC_BUFFER_TYPE_FLAGS, - 0, - RTC_FORMAT_UCHAR, - sizeof(unsigned char), - num_keys_embree); - flags[0] = RTC_CURVE_FLAG_NEIGHBOR_RIGHT; - ::memset(flags + 1, - RTC_CURVE_FLAG_NEIGHBOR_RIGHT | RTC_CURVE_FLAG_NEIGHBOR_RIGHT, - num_keys_embree - 2); - flags[num_keys_embree - 1] = RTC_CURVE_FLAG_NEIGHBOR_LEFT; - } -# endif } void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) @@ -800,6 +770,12 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) } const size_t num_motion_steps = min(num_geometry_motion_steps, RTC_MAX_TIME_STEP_COUNT); + const PrimitiveType primitive_type = + (num_motion_steps > 1) ? + ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : + PRIMITIVE_MOTION_CURVE_THICK) : + ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : PRIMITIVE_CURVE_THICK); + assert(num_geometry_motion_steps <= RTC_MAX_TIME_STEP_COUNT); const size_t num_curves = hair->num_curves(); @@ -820,21 +796,12 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) size_t prim_tri_index_size = pack.prim_index.size(); pack.prim_tri_index.resize(prim_tri_index_size + num_segments); -# if RTC_VERSION >= 30900 - enum RTCGeometryType type = (!use_curves) ? - (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE : - RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE) : - (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : - RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); -# else - enum RTCGeometryType type = (!use_curves) ? - RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE : - (use_ribbons ? RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : - RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); -# endif + enum RTCGeometryType type = (hair->curve_shape == CURVE_RIBBON ? + RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE : + RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE); RTCGeometry geom_id = rtcNewGeometry(rtc_shared_device, type); - rtcSetGeometryTessellationRate(geom_id, curve_subdivisions); + rtcSetGeometryTessellationRate(geom_id, curve_subdivisions + 1); unsigned *rtc_indices = (unsigned *)rtcSetNewGeometryBuffer( geom_id, RTC_BUFFER_TYPE_INDEX, 0, RTC_FORMAT_UINT, sizeof(int), num_segments); size_t rtc_index = 0; @@ -842,14 +809,11 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) Hair::Curve c = hair->get_curve(j); for (size_t k = 0; k < c.num_segments(); ++k) { rtc_indices[rtc_index] = c.first_key + k; - if (use_curves) { - /* Room for extra CVs at Catmull-Rom splines. */ - rtc_indices[rtc_index] += j * 2; - } + /* Room for extra CVs at Catmull-Rom splines. */ + rtc_indices[rtc_index] += j * 2; /* Cycles specific data. */ pack.prim_object[prim_object_size + rtc_index] = i; - pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT( - num_motion_steps > 1 ? PRIMITIVE_MOTION_CURVE : PRIMITIVE_CURVE, k)); + pack.prim_type[prim_type_size + rtc_index] = (PRIMITIVE_PACK_SEGMENT(primitive_type, k)); pack.prim_index[prim_index_size + rtc_index] = j; pack.prim_tri_index[prim_tri_index_size + rtc_index] = rtc_index; @@ -863,8 +827,13 @@ void BVHEmbree::add_curves(const Object *ob, const Hair *hair, int i) update_curve_vertex_buffer(geom_id, hair); rtcSetGeometryUserData(geom_id, (void *)prim_offset); - rtcSetGeometryIntersectFilterFunction(geom_id, rtc_filter_func); - rtcSetGeometryOccludedFilterFunction(geom_id, rtc_filter_occluded_func); + if (hair->curve_shape == CURVE_RIBBON) { + 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); + } rtcSetGeometryMask(geom_id, ob->visibility_for_tracing()); rtcCommitGeometry(geom_id); diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h index eb121d060b7..f60a1ca0102 100644 --- a/intern/cycles/bvh/bvh_embree.h +++ b/intern/cycles/bvh/bvh_embree.h @@ -81,7 +81,7 @@ class BVHEmbree : public BVH { vector<RTCScene> delayed_delete_scenes; int curve_subdivisions; enum RTCBuildQuality build_quality; - bool use_curves, use_ribbons, dynamic_scene; + bool dynamic_scene; }; CCL_NAMESPACE_END diff --git a/intern/cycles/bvh/bvh_optix.cpp b/intern/cycles/bvh/bvh_optix.cpp index 740994b2ebc..ccb7ae08625 100644 --- a/intern/cycles/bvh/bvh_optix.cpp +++ b/intern/cycles/bvh/bvh_optix.cpp @@ -18,10 +18,14 @@ #ifdef WITH_OPTIX # include "bvh/bvh_optix.h" + +# include "device/device.h" + # include "render/geometry.h" # include "render/hair.h" # include "render/mesh.h" # include "render/object.h" + # include "util/util_foreach.h" # include "util/util_logging.h" # include "util/util_progress.h" @@ -73,9 +77,12 @@ void BVHOptiX::pack_blas() // 'pack.prim_time' is only used in geom_curve_intersect.h // It is not needed because of OPTIX_MOTION_FLAG_[START|END]_VANISH - uint type = PRIMITIVE_CURVE; - if (hair->use_motion_blur && hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) - type = PRIMITIVE_MOTION_CURVE; + uint type = (hair->use_motion_blur && + hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)) ? + ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_MOTION_CURVE_RIBBON : + PRIMITIVE_MOTION_CURVE_THICK) : + ((hair->curve_shape == CURVE_RIBBON) ? PRIMITIVE_CURVE_RIBBON : + PRIMITIVE_CURVE_THICK); for (size_t j = 0; j < num_curves; ++j) { const Hair::Curve curve = hair->get_curve(j); diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 5e2c4b63f1b..1a50742dc33 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -89,7 +89,6 @@ class BVHParams { int bvh_type; /* These are needed for Embree. */ - int curve_flags; int curve_subdivisions; /* fixed parameters */ @@ -122,7 +121,6 @@ class BVHParams { bvh_type = 0; - curve_flags = 0; curve_subdivisions = 4; } diff --git a/intern/cycles/bvh/bvh_sort.cpp b/intern/cycles/bvh/bvh_sort.cpp index 4498a759c08..b01785b547a 100644 --- a/intern/cycles/bvh/bvh_sort.cpp +++ b/intern/cycles/bvh/bvh_sort.cpp @@ -88,18 +88,6 @@ static void bvh_reference_sort_threaded(TaskPool *task_pool, const int job_end, const BVHReferenceCompare &compare); -class BVHSortTask : public Task { - public: - BVHSortTask(TaskPool *task_pool, - BVHReference *data, - const int job_start, - const int job_end, - const BVHReferenceCompare &compare) - { - run = function_bind(bvh_reference_sort_threaded, task_pool, data, job_start, job_end, compare); - } -}; - /* Multi-threaded reference sort. */ static void bvh_reference_sort_threaded(TaskPool *task_pool, BVHReference *data, @@ -158,7 +146,8 @@ static void bvh_reference_sort_threaded(TaskPool *task_pool, have_work = false; if (left < end) { if (start < right) { - task_pool->push(new BVHSortTask(task_pool, data, left, end, compare), true); + task_pool->push( + function_bind(bvh_reference_sort_threaded, task_pool, data, left, end, compare)); } else { start = left; diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index acdca0f13ad..4b21f852d7a 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -33,7 +33,7 @@ CCL_NAMESPACE_BEGIN BVHObjectSplit::BVHObjectSplit(BVHBuild *builder, BVHSpatialStorage *storage, const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, float nodeSAH, const BVHUnaligned *unaligned_heuristic, const Transform *aligned_space) @@ -43,7 +43,7 @@ BVHObjectSplit::BVHObjectSplit(BVHBuild *builder, left_bounds(BoundBox::empty), right_bounds(BoundBox::empty), storage_(storage), - references_(references), + references_(&references), unaligned_heuristic_(unaligned_heuristic), aligned_space_(aligned_space) { @@ -133,7 +133,7 @@ void BVHObjectSplit::split(BVHRange &left, BVHRange &right, const BVHRange &rang BVHSpatialSplit::BVHSpatialSplit(const BVHBuild &builder, BVHSpatialStorage *storage, const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, float nodeSAH, const BVHUnaligned *unaligned_heuristic, const Transform *aligned_space) @@ -141,7 +141,7 @@ BVHSpatialSplit::BVHSpatialSplit(const BVHBuild &builder, dim(0), pos(0.0f), storage_(storage), - references_(references), + references_(&references), unaligned_heuristic_(unaligned_heuristic), aligned_space_(aligned_space) { @@ -152,7 +152,7 @@ BVHSpatialSplit::BVHSpatialSplit(const BVHBuild &builder, } else { range_bounds = unaligned_heuristic->compute_aligned_boundbox( - range, &references->at(0), *aligned_space); + range, &references_->at(0), *aligned_space); } float3 origin = range_bounds.min; diff --git a/intern/cycles/bvh/bvh_split.h b/intern/cycles/bvh/bvh_split.h index 5f2e41cf343..28ff0e05fc3 100644 --- a/intern/cycles/bvh/bvh_split.h +++ b/intern/cycles/bvh/bvh_split.h @@ -44,7 +44,7 @@ class BVHObjectSplit { BVHObjectSplit(BVHBuild *builder, BVHSpatialStorage *storage, const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, float nodeSAH, const BVHUnaligned *unaligned_heuristic = NULL, const Transform *aligned_space = NULL); @@ -82,7 +82,7 @@ class BVHSpatialSplit { BVHSpatialSplit(const BVHBuild &builder, BVHSpatialStorage *storage, const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, float nodeSAH, const BVHUnaligned *unaligned_heuristic = NULL, const Transform *aligned_space = NULL); @@ -187,7 +187,7 @@ class BVHMixedSplit { __forceinline BVHMixedSplit(BVHBuild *builder, BVHSpatialStorage *storage, const BVHRange &range, - vector<BVHReference> *references, + vector<BVHReference> &references, int level, const BVHUnaligned *unaligned_heuristic = NULL, const Transform *aligned_space = NULL) @@ -197,7 +197,7 @@ class BVHMixedSplit { } else { bounds = unaligned_heuristic->compute_aligned_boundbox( - range, &references->at(0), *aligned_space); + range, &references.at(0), *aligned_space); } /* find split candidates. */ float area = bounds.safe_area(); @@ -220,7 +220,7 @@ class BVHMixedSplit { /* leaf SAH is the lowest => create leaf. */ minSAH = min(min(leafSAH, object.sah), spatial.sah); - no_split = (minSAH == leafSAH && builder->range_within_max_leaf_size(range, *references)); + no_split = (minSAH == leafSAH && builder->range_within_max_leaf_size(range, references)); } __forceinline void split(BVHBuild *builder, diff --git a/intern/cycles/bvh/bvh_unaligned.cpp b/intern/cycles/bvh/bvh_unaligned.cpp index f0995f343fe..c969b361643 100644 --- a/intern/cycles/bvh/bvh_unaligned.cpp +++ b/intern/cycles/bvh/bvh_unaligned.cpp @@ -68,7 +68,8 @@ bool BVHUnaligned::compute_aligned_space(const BVHReference &ref, Transform *ali const Object *object = objects_[ref.prim_object()]; const int packed_type = ref.prim_type(); const int type = (packed_type & PRIMITIVE_ALL); - if (type & PRIMITIVE_CURVE) { + /* No motion blur curves here, we can't fit them to aligned boxes well. */ + if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) { const int curve_index = ref.prim_index(); const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); const Hair *hair = static_cast<const Hair *>(object->geometry); @@ -93,7 +94,8 @@ BoundBox BVHUnaligned::compute_aligned_prim_boundbox(const BVHReference &prim, const Object *object = objects_[prim.prim_object()]; const int packed_type = prim.prim_type(); const int type = (packed_type & PRIMITIVE_ALL); - if (type & PRIMITIVE_CURVE) { + /* No motion blur curves here, we can't fit them to aligned boxes well. */ + if (type & (PRIMITIVE_CURVE_RIBBON | PRIMITIVE_CURVE_THICK)) { const int curve_index = prim.prim_index(); const int segment = PRIMITIVE_UNPACK_SEGMENT(packed_type); const Hair *hair = static_cast<const Hair *>(object->geometry); |