Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/bvh/bvh.cpp20
-rw-r--r--intern/cycles/bvh/bvh_build.cpp120
-rw-r--r--intern/cycles/bvh/bvh_build.h10
-rw-r--r--intern/cycles/bvh/bvh_params.h7
-rw-r--r--intern/cycles/kernel/kernel_types.h7
5 files changed, 151 insertions, 13 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index ac2762b80bd..38773bfbc4e 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -504,12 +504,19 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_
void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
{
- if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1)
+ if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) {
/* object */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility);
- else
- /* triangle */
- pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility);
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0,
+ leaf->m_visibility, leaf->m_visibility);
+ }
+ else {
+ /* Triangle/curve primitive leaf. */
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds,
+ leaf->m_lo, leaf->m_hi,
+ leaf->m_visibility,
+ pack.prim_type[leaf->m_lo]);
+ }
+
}
void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
@@ -657,7 +664,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
visibility |= ob->visibility;
}
- pack_node(idx, bbox, bbox, c0, c1, visibility, visibility);
+ pack_node(idx, bbox, bbox, c0, c1, visibility, data[3].w);
}
else {
/* refit inner node, set bbox from children */
@@ -700,6 +707,7 @@ void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
data[6].y = __int_as_float(leaf->m_hi);
}
data[6].z = __uint_as_float(leaf->m_visibility);
+ data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]);
memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE);
}
diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp
index 5547229a910..f4368a84482 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -449,8 +449,123 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
}
}
+BVHNode *BVHBuild::create_primitive_leaf_node(const vector<int>& p_type,
+ const vector<int>& p_index,
+ const vector<int>& p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start)
+{
+ assert(p_type.size() == p_index.size());
+ assert(p_index.size() == p_object.size());
+ for(int i = 0; i < p_type.size(); ++i) {
+ if(start + i == prim_index.size()) {
+ assert(params.use_spatial_split);
+ prim_type.push_back(p_type[i]);
+ prim_index.push_back(p_index[i]);
+ prim_object.push_back(p_object[i]);
+ }
+ else {
+ prim_type[start + i] = p_type[i];
+ prim_index[start + i] = p_index[i];
+ prim_object[start + i] = p_object[i];
+ }
+ }
+ return new LeafNode(bounds, visibility, start, start + p_type.size());
+}
+
+BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range)
+{
+ /* TODO(sergey): Reserve some elementsin arrays by default. */
+ vector<int> p_type[PRIMITIVE_NUM_TOTAL];
+ vector<int> p_index[PRIMITIVE_NUM_TOTAL];
+ vector<int> p_object[PRIMITIVE_NUM_TOTAL];
+ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ int ob_num = 0;
+ uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
+
+ /* Fill in per-type type/index array. */
+ for(int i = 0; i < range.size(); i++) {
+ BVHReference& ref = references[range.start() + i];
+ if(ref.prim_index() != -1) {
+ int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
+ p_type[type_index].push_back(ref.prim_type());
+ p_index[type_index].push_back(ref.prim_index());
+ p_object[type_index].push_back(ref.prim_object());
+
+ bounds[type_index].grow(ref.bounds());
+ visibility[type_index] |= objects[ref.prim_object()]->visibility;
+ }
+ else {
+ if(ob_num < i) {
+ references[range.start() + ob_num] = ref;
+ }
+ ob_num++;
+ }
+ }
+
+ /* Create leaf nodes for every existing primitive. */
+ BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL};
+ int num_leaves = 0;
+ int start = range.start();
+ for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) {
+ if(p_type[i].size()) {
+ leaves[num_leaves] = create_primitive_leaf_node(p_type[i],
+ p_index[i],
+ p_object[i],
+ bounds[i],
+ visibility[i],
+ start);
+ ++num_leaves;
+ start += p_type[i].size();
+ }
+ }
+
+ /* Create leaf node for object. */
+ if(num_leaves == 0 || ob_num) {
+ /* Only create object leaf nodes if there are objects or no other
+ * nodes created.
+ */
+ const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
+ leaves[num_leaves] = create_object_leaf_nodes(ref, start, ob_num);
+ ++num_leaves;
+ }
+
+ if(num_leaves == 1) {
+ /* Simplest case: single leaf, just return it.
+ * In all the rest cases we'll be creating intermediate inner node with
+ * an appropriate bounding box.
+ */
+ return leaves[0];
+ }
+ else if(num_leaves == 2) {
+ return new InnerNode(range.bounds(), leaves[0], leaves[1]);
+ }
+ else if(num_leaves == 3) {
+ BoundBox inner_bounds = merge(bounds[1], bounds[2]);
+ BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]);
+ return new InnerNode(range.bounds(), leaves[0], inner);
+ } else /*if(num_leaves == 4)*/ {
+ /* Shpuld be doing more branches if more primitive types added. */
+ assert(num_leaves == 4);
+ BoundBox inner_bounds_a = merge(bounds[0], bounds[1]);
+ BoundBox inner_bounds_b = merge(bounds[2], bounds[3]);
+ BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]);
+ BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]);
+ return new InnerNode(range.bounds(), inner_a, inner_b);
+ }
+}
+
BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
{
+ if(params.use_split_leaf_types) {
+ /* Need to ensure leaf nodes has single primitive type only. */
+ return create_leaf_node_split(range);
+ }
+
vector<int>& p_type = prim_type;
vector<int>& p_index = prim_index;
vector<int>& p_object = prim_object;
@@ -487,7 +602,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
}
BVHNode *leaf = NULL;
-
+
if(num > 0) {
leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num);
@@ -499,7 +614,7 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
* we want there to be the only one, so we keep splitting */
const BVHReference *ref = (ob_num)? &references[range.start()]: NULL;
BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num);
-
+
if(leaf)
return new InnerNode(range.bounds(), leaf, oleaf);
else
@@ -588,4 +703,3 @@ void BVHBuild::rotate(BVHNode *node, int max_depth)
}
CCL_NAMESPACE_END
-
diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h
index a6b9916de9b..75c64be6eab 100644
--- a/intern/cycles/bvh/bvh_build.h
+++ b/intern/cycles/bvh/bvh_build.h
@@ -70,6 +70,15 @@ protected:
BVHNode *create_leaf_node(const BVHRange& range);
BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num);
+ /* Leaf node type splitting. */
+ BVHNode *create_leaf_node_split(const BVHRange& range);
+ BVHNode *create_primitive_leaf_node(const vector<int>& p_type,
+ const vector<int>& p_index,
+ const vector<int>& p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start);
+
bool range_within_max_leaf_size(const BVHRange& range);
/* threads */
@@ -116,4 +125,3 @@ protected:
CCL_NAMESPACE_END
#endif /* __BVH_BUILD_H__ */
-
diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h
index 43c2d9b2683..c4dc14710e3 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -49,7 +49,10 @@ public:
/* QBVH */
int use_qbvh;
- int pad;
+ /* Split leaf nodes by primitive types,
+ * leaving node containing primitives of single type only.
+ */
+ int use_split_leaf_types;
/* fixed parameters */
enum {
@@ -75,7 +78,7 @@ public:
top_level = false;
use_cache = false;
use_qbvh = false;
- pad = false;
+ use_split_leaf_types = false;
}
/* SAH costs */
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index aff9a001061..82619b3f854 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -481,7 +481,12 @@ typedef enum PrimitiveType {
PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE),
PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE),
PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE),
- PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE)
+ PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE),
+
+ /* Total number of different primitives.
+ * NOTE: This is an actual value, not a bitflag.
+ */
+ PRIMITIVE_NUM_TOTAL = 4,
} PrimitiveType;
#define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type)