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:
authorInes Almeida <britalmeida@gmail.com>2015-01-13 14:04:25 +0300
committerInes Almeida <britalmeida@gmail.com>2015-01-13 14:04:25 +0300
commitcb61c5aeee94af943b0306550daef45c2018126a (patch)
treedbb2a9b5600bc53de35162e79091772bff1b6f8b /intern/cycles
parentd7cabe7d6f4519856969137df415692e16a5372d (diff)
parent117edbbf881be1764db852d9805c523590a19f84 (diff)
Merge branch 'master' into soc-2014-bgesoc-2014-bge
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/bvh/bvh.cpp23
-rw-r--r--intern/cycles/bvh/bvh_build.cpp154
-rw-r--r--intern/cycles/bvh/bvh_build.h10
-rw-r--r--intern/cycles/bvh/bvh_params.h3
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_shadow.h9
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_subsurface.h44
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_traversal.h101
-rw-r--r--intern/cycles/kernel/geom/geom_bvh_volume.h68
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_shadow.h7
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_subsurface.h45
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_traversal.h82
-rw-r--r--intern/cycles/kernel/geom/geom_qbvh_volume.h66
-rw-r--r--intern/cycles/kernel/kernel_types.h7
13 files changed, 401 insertions, 218 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp
index ac2762b80bd..5fc4ddb3a0e 100644
--- a/intern/cycles/bvh/bvh.cpp
+++ b/intern/cycles/bvh/bvh.cpp
@@ -504,12 +504,20 @@ 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 {
+ int prim_type = leaf->num_triangles() ? pack.prim_type[leaf->m_lo] : 0;
+ /* Triangle/curve primitive leaf. */
+ pack_node(e.idx, leaf->m_bounds, leaf->m_bounds,
+ leaf->m_lo, leaf->m_hi,
+ leaf->m_visibility,
+ prim_type);
+ }
+
}
void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1)
@@ -657,7 +665,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 +708,9 @@ 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);
+ if(leaf->num_triangles() != 0) {
+ 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..da263c4945e 100644
--- a/intern/cycles/bvh/bvh_build.cpp
+++ b/intern/cycles/bvh/bvh_build.cpp
@@ -34,6 +34,21 @@
CCL_NAMESPACE_BEGIN
+#if !defined(__KERNEL_SSE2__)
+/* TODO(sergey): Move to some generic header so all code
+ * can use bitscan on non-SSE processors.
+ */
+ccl_device_inline int bitscan(int value)
+{
+ assert(value != 0);
+ int bit = 0;
+ while (value >>= 1) {
+ ++bit;
+ }
+ return bit;
+}
+#endif
+
/* BVH Build Task */
class BVHBuildTask : public Task {
@@ -449,61 +464,119 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start,
}
}
-BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int num)
{
- vector<int>& p_type = prim_type;
- vector<int>& p_index = prim_index;
- vector<int>& p_object = prim_object;
- BoundBox bounds = BoundBox::empty;
- int num = 0, ob_num = 0;
- uint visibility = 0;
+ for(int i = 0; i < num; ++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 + num);
+}
+BVHNode* BVHBuild::create_leaf_node(const BVHRange& range)
+{
+#define MAX_LEAF_SIZE 8
+ int p_num[PRIMITIVE_NUM_TOTAL] = {0};
+ int p_type[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ int p_index[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ int p_object[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE];
+ uint visibility[PRIMITIVE_NUM_TOTAL] = {0};
+ /* NOTE: Keep initializtion in sync with actual number of primitives. */
+ BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty,
+ BoundBox::empty};
+ int ob_num = 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) {
- if(range.start() + num == prim_index.size()) {
- assert(params.use_spatial_split);
-
- p_type.push_back(ref.prim_type());
- p_index.push_back(ref.prim_index());
- p_object.push_back(ref.prim_object());
- }
- else {
- p_type[range.start() + num] = ref.prim_type();
- p_index[range.start() + num] = ref.prim_index();
- p_object[range.start() + num] = ref.prim_object();
- }
-
- bounds.grow(ref.bounds());
- visibility |= objects[ref.prim_object()]->visibility;
- num++;
+ int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL);
+ int idx = p_num[type_index];
+ p_type[type_index][idx] = ref.prim_type();
+ p_index[type_index][idx] = ref.prim_index();
+ p_object[type_index][idx] = ref.prim_object();
+ ++p_num[type_index];
+
+ bounds[type_index].grow(ref.bounds());
+ visibility[type_index] |= objects[ref.prim_object()]->visibility;
}
else {
- if(ob_num < i)
+ if(ob_num < i) {
references[range.start() + ob_num] = ref;
+ }
ob_num++;
}
}
- BVHNode *leaf = NULL;
-
- if(num > 0) {
- leaf = new LeafNode(bounds, visibility, range.start(), range.start() + 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_num[i] != 0) {
+ leaves[num_leaves] = create_primitive_leaf_node(p_type[i],
+ p_index[i],
+ p_object[i],
+ bounds[i],
+ visibility[i],
+ start,
+ p_num[i]);
+ ++num_leaves;
+ start += p_num[i];
+ }
+ }
- if(num == range.size())
- return leaf;
+ /* 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;
}
- /* while there may be multiple triangles in a leaf, for object primitives
- * 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
- return oleaf;
+ 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);
+ }
+#undef AMX_LEAF_SIZE
}
/* Tree Rotations */
@@ -588,4 +661,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..294c5a1758d 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_primitive_leaf_node(const int *p_type,
+ const int *p_index,
+ const int *p_object,
+ const BoundBox& bounds,
+ uint visibility,
+ int start,
+ int nun);
+
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..3fa6ebd75af 100644
--- a/intern/cycles/bvh/bvh_params.h
+++ b/intern/cycles/bvh/bvh_params.h
@@ -49,8 +49,6 @@ public:
/* QBVH */
int use_qbvh;
- int pad;
-
/* fixed parameters */
enum {
MAX_DEPTH = 64,
@@ -75,7 +73,6 @@ public:
top_level = false;
use_cache = false;
use_qbvh = false;
- pad = false;
}
/* SAH costs */
diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h
index 6dafd2c9fdc..193f49074a3 100644
--- a/intern/cycles/kernel/geom/geom_bvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h
@@ -206,7 +206,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* pop */
nodeAddr = traversalStack[stackPtr];
@@ -214,14 +216,15 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* primitive intersection */
while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
/* todo: specialized intersect functions which don't fill in
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
* might give a few % performance improvement */
- switch(type & PRIMITIVE_ALL) {
+ switch(p_type) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
break;
diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
index ea9d7c07a72..290297ef5c5 100644
--- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h
@@ -193,37 +193,43 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from the same object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
-
- if(tri_object != subsurface_object)
- continue;
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from the same object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object)
+ continue;
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h
index b948ab8f5e4..0298e687de2 100644
--- a/intern/cycles/kernel/geom/geom_bvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h
@@ -254,62 +254,85 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- while(primAddr < primAddr2) {
- bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+#endif
+ }
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
#endif
-#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
- hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- else
- hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- break;
- }
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ /* shadow ray early termination */
+#if defined(__KERNEL_SSE2__)
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
+#else
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
- default: {
- hit = false;
- break;
+ }
}
+ break;
}
-
+#endif /* BVH_FEATURE(BVH_MOTION) */
+#if BVH_FEATURE(BVH_HAIR)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
+ isect->num_traversal_steps++;
#endif
-
- /* shadow ray early termination */
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ else
+ hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
+ if(hit) {
+ /* shadow ray early termination */
#if defined(__KERNEL_SSE2__)
- if(hit) {
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
-
- tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
- }
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t);
#else
- if(hit && visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
#endif
-
- primAddr++;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_HAIR) */
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h
index f1f2e6d1f46..0862812a170 100644
--- a/intern/cycles/kernel/geom/geom_bvh_volume.h
+++ b/intern/cycles/kernel/geom/geom_bvh_volume.h
@@ -194,49 +194,67 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
#if BVH_FEATURE(BVH_INSTANCING)
if(primAddr >= 0) {
#endif
- int primAddr2 = __float_as_int(leaf.y);
+ const int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* pop */
nodeAddr = traversalStack[stackPtr];
--stackPtr;
/* primitive intersection */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from volume object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
-
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
-
- /* intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
}
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ /* intersect ray against primitive */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* only primitives from volume object */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
else
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
- break;
}
+ break;
+ }
#endif
- default: {
- break;
- }
+ default: {
+ break;
}
}
}
diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
index e493a3f51bd..e77e220c919 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h
@@ -216,6 +216,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
@@ -223,14 +225,15 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Primitive intersection. */
while(primAddr < primAddr2) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+
bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
/* todo: specialized intersect functions which don't fill in
* isect unless needed and check SD_HAS_TRANSPARENT_SHADOW?
* might give a few % performance improvement */
- switch(type & PRIMITIVE_ALL) {
+ switch(p_type) {
case PRIMITIVE_TRIANGLE: {
hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr);
break;
diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
index 0154772988f..ef1754e711c 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h
@@ -203,37 +203,44 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
--stackPtr;
/* Primitive intersection. */
- for(; primAddr < primAddr2; primAddr++) {
- /* only primitives from the same object */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
-
- if(tri_object != subsurface_object)
- continue;
-
- /* Intersect ray against primitive */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ /* Intersect ray against primitive, */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ /* Intersect ray against primitive. */
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from the same object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ if(tri_object != subsurface_object) {
+ continue;
+ }
motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits);
- break;
- }
-#endif
- default: {
- break;
}
+ break;
}
+#endif
+ default:
+ break;
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
index 8d81f475848..64da51360de 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h
@@ -275,6 +275,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
@@ -282,49 +283,62 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
--stackPtr;
/* Primitive intersection. */
- while(primAddr < primAddr2) {
- bool hit;
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
- hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
+ switch(type & PRIMITIVE_ALL) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
- hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
- }
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
+ }
+ break;
+ }
+#endif /* BVH_FEATURE(BVH_MOTION) */
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+#if defined(__KERNEL_DEBUG__)
+ isect->num_traversal_steps++;
+#endif
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ bool hit;
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
else
hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
- break;
+ if(hit) {
+ tfar = ssef(isect->t);
+ /* Shadow ray early termination. */
+ if(visibility == PATH_RAY_SHADOW_OPAQUE)
+ return true;
+ }
}
-#endif
- default: {
- hit = false;
- break;
- }
- }
-
-#if defined(__KERNEL_DEBUG__)
- isect->num_traversal_steps++;
-#endif
-
- /* Shadow ray early termination. */
- if(hit) {
- tfar = ssef(isect->t);
- if(visibility == PATH_RAY_SHADOW_OPAQUE)
- return true;
+ break;
}
-
- primAddr++;
+#endif /* BVH_FEATURE(BVH_HAIR) */
}
}
#if BVH_FEATURE(BVH_INSTANCING)
diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h
index 9e6e7552b3f..a2a8d1a20ab 100644
--- a/intern/cycles/kernel/geom/geom_qbvh_volume.h
+++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h
@@ -209,49 +209,65 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
if(primAddr >= 0) {
#endif
int primAddr2 = __float_as_int(leaf.y);
+ const uint type = __float_as_int(leaf.w);
+ const uint p_type = type & PRIMITIVE_ALL;
/* Pop. */
nodeAddr = traversalStack[stackPtr].addr;
--stackPtr;
/* Primitive intersection. */
- for(; primAddr < primAddr2; primAddr++) {
- /* Only primitives from volume object. */
- uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
- int object_flag = kernel_tex_fetch(__object_flag, tri_object);
-
- if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
- continue;
- }
-
- /* Intersect ray against primitive. */
- uint type = kernel_tex_fetch(__prim_type, primAddr);
-
- switch(type & PRIMITIVE_ALL) {
- case PRIMITIVE_TRIANGLE: {
+ switch(p_type) {
+ case PRIMITIVE_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr);
- break;
}
+ break;
+ }
#if BVH_FEATURE(BVH_MOTION)
- case PRIMITIVE_MOTION_TRIANGLE: {
+ case PRIMITIVE_MOTION_TRIANGLE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr);
- break;
}
+ break;
+ }
#endif
#if BVH_FEATURE(BVH_HAIR)
- case PRIMITIVE_CURVE:
- case PRIMITIVE_MOTION_CURVE: {
- if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
+ case PRIMITIVE_CURVE:
+ case PRIMITIVE_MOTION_CURVE: {
+ for(; primAddr < primAddr2; primAddr++) {
+ kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type);
+ /* Only primitives from volume object. */
+ uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object;
+ int object_flag = kernel_tex_fetch(__object_flag, tri_object);
+ if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) {
+ continue;
+ }
+ /* Intersect ray against primitive. */
+ if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
else
bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0);
- break;
- }
-#endif
- default: {
- break;
}
+ break;
}
+#endif
}
}
#if BVH_FEATURE(BVH_INSTANCING)
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)