From b56f5900dc776c45d83c99334473d1cb3874feaf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Jan 2015 03:41:04 +0500 Subject: Cycles: BVH params option to split leaf node by primitive types The idea of this change is make it possible to split leaf nodes by primitive type, making leaf containing primitives of the same type. This would become handy when working on a single ray to multiple triangles intersection code, plus with careful implementation it might give some extra benefits on BVH traversal code by avoiding primitive type fetch and check for each primitive in the node. But that's a bit tricky to have benefits on this change only because depth of BVH increases. This option is not exposed to the interface at all and not used even secretly, the commit is only needed to help working further in this direction without messing around with local patches and worrying of them running out of date. --- intern/cycles/bvh/bvh.cpp | 20 ++++-- intern/cycles/bvh/bvh_build.cpp | 120 +++++++++++++++++++++++++++++++++++- intern/cycles/bvh/bvh_build.h | 10 ++- intern/cycles/bvh/bvh_params.h | 7 ++- intern/cycles/kernel/kernel_types.h | 7 ++- 5 files changed, 151 insertions(+), 13 deletions(-) (limited to 'intern') 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& 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& p_type, + const vector& p_index, + const vector& 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 p_type[PRIMITIVE_NUM_TOTAL]; + vector p_index[PRIMITIVE_NUM_TOTAL]; + vector 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& p_type = prim_type; vector& p_index = prim_index; vector& 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& p_type, + const vector& p_index, + const vector& 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) -- cgit v1.2.3 From c707b91ce6b14182a3a579b645cfd832fc1ae658 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Jan 2015 22:32:44 +0500 Subject: Cycles: Optimize leaf splitting code by avoid vector allocation Use variables allocated in the stack and avoid heap allocation which should make leaf splitting code a bit faster. --- intern/cycles/bvh/bvh_build.cpp | 43 +++++++++++++++++++++++------------------ intern/cycles/bvh/bvh_build.h | 9 +++++---- 2 files changed, 29 insertions(+), 23 deletions(-) (limited to 'intern') diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index f4368a84482..d0542f064a3 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -449,16 +449,15 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, } } -BVHNode *BVHBuild::create_primitive_leaf_node(const vector& p_type, - const vector& p_index, - const vector& p_object, +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 start, + int num) { - assert(p_type.size() == p_index.size()); - assert(p_index.size() == p_object.size()); - for(int i = 0; i < p_type.size(); ++i) { + 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]); @@ -471,30 +470,34 @@ BVHNode *BVHBuild::create_primitive_leaf_node(const vector& p_type, prim_object[start + i] = p_object[i]; } } - return new LeafNode(bounds, visibility, start, start + p_type.size()); + return new LeafNode(bounds, visibility, start, start + num); } BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range) { - /* TODO(sergey): Reserve some elementsin arrays by default. */ - vector p_type[PRIMITIVE_NUM_TOTAL]; - vector p_index[PRIMITIVE_NUM_TOTAL]; - vector p_object[PRIMITIVE_NUM_TOTAL]; +#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; - 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()); + 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; @@ -512,15 +515,16 @@ BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range) int num_leaves = 0; int start = range.start(); for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) { - if(p_type[i].size()) { + 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); + start, + p_num[i]); ++num_leaves; - start += p_type[i].size(); + start += p_num[i]; } } @@ -557,6 +561,7 @@ BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range) 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 } BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 75c64be6eab..1e629fb5eb2 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -72,12 +72,13 @@ protected: /* Leaf node type splitting. */ BVHNode *create_leaf_node_split(const BVHRange& range); - BVHNode *create_primitive_leaf_node(const vector& p_type, - const vector& p_index, - const vector& p_object, + 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 start, + int nun); bool range_within_max_leaf_size(const BVHRange& range); -- cgit v1.2.3 From bc7ff3c2b44e9cd8f3aea1a3943b787deede2838 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Jan 2015 22:41:49 +0500 Subject: Cycles: Enable leaf split by primitive type and adopt BVH traversal for this This commit enables BVH leaf nodes split by the primitive type and makes it so BVH traversal code is now aware and benefits from this. As was mentioned in original commit, this change is crucial to be able to do single ray to multiple triangle intersection. But it also appears to give barely visible speedup in some scene. In any case there should be no noticeable slowdown, and this change is what we need to have anyway. --- intern/cycles/bvh/bvh_build.cpp | 64 +--------------- intern/cycles/bvh/bvh_build.h | 1 - intern/cycles/bvh/bvh_params.h | 6 -- intern/cycles/kernel/geom/geom_bvh_shadow.h | 7 +- intern/cycles/kernel/geom/geom_bvh_subsurface.h | 42 +++++----- intern/cycles/kernel/geom/geom_bvh_traversal.h | 98 ++++++++++++++---------- intern/cycles/kernel/geom/geom_bvh_volume.h | 65 ++++++++++------ intern/cycles/kernel/geom/geom_qbvh_shadow.h | 5 +- intern/cycles/kernel/geom/geom_qbvh_subsurface.h | 43 ++++++----- intern/cycles/kernel/geom/geom_qbvh_traversal.h | 79 +++++++++++-------- intern/cycles/kernel/geom/geom_qbvh_volume.h | 63 +++++++++------ 11 files changed, 237 insertions(+), 236 deletions(-) (limited to 'intern') diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index d0542f064a3..23c696ea6b2 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -473,7 +473,7 @@ BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type, return new LeafNode(bounds, visibility, start, start + num); } -BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range) +BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) { #define MAX_LEAF_SIZE 8 int p_num[PRIMITIVE_NUM_TOTAL] = {0}; @@ -564,68 +564,6 @@ BVHNode* BVHBuild::create_leaf_node_split(const BVHRange& range) #undef AMX_LEAF_SIZE } -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& p_type = prim_type; - vector& p_index = prim_index; - vector& p_object = prim_object; - BoundBox bounds = BoundBox::empty; - int num = 0, ob_num = 0; - uint visibility = 0; - - 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++; - } - else { - 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); - - if(num == range.size()) - return leaf; - } - - /* 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; -} - /* Tree Rotations */ void BVHBuild::rotate(BVHNode *node, int max_depth, int iterations) diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 1e629fb5eb2..294c5a1758d 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -71,7 +71,6 @@ protected: 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 int *p_type, const int *p_index, const int *p_object, diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index c4dc14710e3..3fa6ebd75af 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -49,11 +49,6 @@ public: /* QBVH */ int use_qbvh; - /* Split leaf nodes by primitive types, - * leaving node containing primitives of single type only. - */ - int use_split_leaf_types; - /* fixed parameters */ enum { MAX_DEPTH = 64, @@ -78,7 +73,6 @@ public: top_level = false; use_cache = false; use_qbvh = false; - use_split_leaf_types = 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..5c87fe83172 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]; @@ -215,13 +217,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, /* primitive intersection */ while(primAddr < primAddr2) { 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..2f078d51985 100644 --- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h @@ -193,37 +193,41 @@ 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++) { + /* 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++) { + /* 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..da3e7fa963d 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -254,62 +254,82 @@ 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 + 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; - } + 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 */ + 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..cf4221fb715 100644 --- a/intern/cycles/kernel/geom/geom_bvh_volume.h +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -194,49 +194,64 @@ 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++) { + /* 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++) { + /* 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++) { + /* 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..f43ced8f8f0 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; @@ -224,13 +226,12 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* Primitive intersection. */ while(primAddr < primAddr2) { 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..7d049e4941d 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h @@ -203,37 +203,42 @@ 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++) { + /* 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++) { + /* 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..4bc9e50d5df 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,59 @@ 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: { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + for(; primAddr < primAddr2; primAddr++) { + 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 + 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 + 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..8d4523c3486 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h @@ -209,49 +209,62 @@ 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++) { + /* 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++) { + /* 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++) { + /* 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) -- cgit v1.2.3 From 5719ed122517d3d053b3c7c89a62c4f6b8eb8057 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 12 Jan 2015 02:04:35 +0500 Subject: Cycles: Add leaf primitives sanity check asserts to the kernel This way we'll notice that leaf splitting didn't happen correct pretty easily in debug builds. There'll be absolutely no impact on release builds. --- intern/cycles/kernel/geom/geom_bvh_shadow.h | 2 ++ intern/cycles/kernel/geom/geom_bvh_subsurface.h | 2 ++ intern/cycles/kernel/geom/geom_bvh_traversal.h | 3 +++ intern/cycles/kernel/geom/geom_bvh_volume.h | 3 +++ intern/cycles/kernel/geom/geom_qbvh_shadow.h | 2 ++ intern/cycles/kernel/geom/geom_qbvh_subsurface.h | 2 ++ intern/cycles/kernel/geom/geom_qbvh_traversal.h | 7 +++++-- intern/cycles/kernel/geom/geom_qbvh_volume.h | 3 +++ 8 files changed, 22 insertions(+), 2 deletions(-) (limited to 'intern') diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index 5c87fe83172..193f49074a3 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -216,6 +216,8 @@ 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; /* todo: specialized intersect functions which don't fill in diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h index 2f078d51985..290297ef5c5 100644 --- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h @@ -205,6 +205,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, 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) @@ -217,6 +218,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, 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) diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h index da3e7fa963d..0298e687de2 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -268,6 +268,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #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__) @@ -288,6 +289,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #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)) { /* shadow ray early termination */ #if defined(__KERNEL_SSE2__) @@ -310,6 +312,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #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); diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h index cf4221fb715..0862812a170 100644 --- a/intern/cycles/kernel/geom/geom_bvh_volume.h +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -206,6 +206,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, 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); @@ -220,6 +221,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, 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); @@ -236,6 +238,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, 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); diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index f43ced8f8f0..e77e220c919 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -225,6 +225,8 @@ 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; /* todo: specialized intersect functions which don't fill in diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h index 7d049e4941d..ef1754e711c 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h @@ -214,6 +214,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, 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) { @@ -227,6 +228,7 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, 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) { diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h index 4bc9e50d5df..64da51360de 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h @@ -285,10 +285,11 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* Primitive intersection. */ switch(type & PRIMITIVE_ALL) { case PRIMITIVE_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { #if defined(__KERNEL_DEBUG__) - isect->num_traversal_steps++; + isect->num_traversal_steps++; #endif - for(; primAddr < primAddr2; primAddr++) { + 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. */ @@ -304,6 +305,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, #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. */ @@ -321,6 +323,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, #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); diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h index 8d4523c3486..a2a8d1a20ab 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h @@ -220,6 +220,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, 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); @@ -234,6 +235,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_MOTION) 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); @@ -250,6 +252,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, 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); -- cgit v1.2.3 From e8730af87f3a105c07be7e19c09a85d7b9fd2fba Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 12 Jan 2015 17:13:50 +0500 Subject: Cycles: Fix compilation error on platforms without SSE support Overview this in one of the previous BVH commits. --- intern/cycles/bvh/bvh_build.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'intern') diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 23c696ea6b2..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 { -- cgit v1.2.3 From 51779d9407a307475c72f0df7ec012fea8ab1d76 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Mon, 12 Jan 2015 19:11:32 +0500 Subject: Cycles: Fix crash after recent BVH changes on empty BVH trees It's apparently not nice to access 0th element of zero-size vector in C++. --- intern/cycles/bvh/bvh.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'intern') diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 38773bfbc4e..5fc4ddb3a0e 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -510,11 +510,12 @@ void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) 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, - pack.prim_type[leaf->m_lo]); + prim_type); } } @@ -707,7 +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); - data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]); + 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); } -- cgit v1.2.3 From 301433fe9d3864a454f0d27b9e3809e8e2c76da6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 12 Jan 2015 22:02:06 +1100 Subject: Fix OpenGL Context freeing --- intern/ghost/intern/GHOST_ContextCGL.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'intern') diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 37fd4a36ea4..0b290c617a5 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -75,9 +75,10 @@ GHOST_ContextCGL::GHOST_ContextCGL( GHOST_ContextCGL::~GHOST_ContextCGL() { if (m_openGLContext != nil) { - if (m_openGLContext == [NSOpenGLContext currentContext]) + if (m_openGLContext == [NSOpenGLContext currentContext]) { [NSOpenGLContext clearCurrentContext]; [m_openGLView clearGLContext]; + } if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) { assert(s_sharedCount > 0); -- cgit v1.2.3