diff options
author | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-01-09 14:56:50 +0300 |
---|---|---|
committer | Sergey Sharybin <sergey.vfx@gmail.com> | 2019-01-09 14:56:50 +0300 |
commit | ddabad2410c166d909f512c751235031805da33e (patch) | |
tree | a369f76fe259d2d2d89d8bcba9ecca266c6f0f19 /intern | |
parent | ff6ff90cbec72dea41f1a0f638d2334185095514 (diff) | |
parent | 1a6a80270dae82d5ce9bf1266476f7bf0fe1d714 (diff) |
Merge branch 'blender2.7'
Diffstat (limited to 'intern')
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 51 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.h | 4 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh2.cpp | 14 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh2.h | 3 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh4.cpp | 105 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh4.h | 3 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh8.cpp | 164 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh8.h | 3 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_embree.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_embree.h | 4 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_node.cpp | 149 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_node.h | 132 | ||||
-rw-r--r-- | intern/cycles/kernel/kernel_volume.h | 12 | ||||
-rw-r--r-- | intern/cycles/kernel/split/kernel_subsurface_scatter.h | 9 |
14 files changed, 397 insertions, 262 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index ac0614e3659..af012bbf3ac 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -127,10 +127,26 @@ void BVH::build(Progress& progress, Stats*) pack.prim_time, params, progress); - BVHNode *root = bvh_build.run(); + BVHNode *bvh2_root = bvh_build.run(); if(progress.get_cancel()) { - if(root) root->deleteSubtree(); + if(bvh2_root != NULL) { + bvh2_root->deleteSubtree(); + } + return; + } + + /* BVH builder returns tree in a binary mode (with two children per inner + * node. Need to adopt that for a wider BVH implementations. */ + BVHNode *root = widen_children_nodes(bvh2_root); + if(root != bvh2_root) { + bvh2_root->deleteSubtree(); + } + + if(progress.get_cancel()) { + if(root != NULL) { + root->deleteSubtree(); + } return; } @@ -232,37 +248,6 @@ void BVH::refit_primitives(int start, int end, BoundBox& bbox, uint& visibility) } } -bool BVH::leaf_check(const BVHNode *node, BVH_TYPE bvh) -{ - if(node->is_leaf()) { - return node->is_unaligned; - } - else { - return node_is_unaligned(node, bvh); - } -} - -bool BVH::node_is_unaligned(const BVHNode *node, BVH_TYPE bvh) -{ - const BVHNode *node0 = node->get_child(0); - const BVHNode *node1 = node->get_child(1); - - switch(bvh) { - case bvh2: - return node0->is_unaligned || node1->is_unaligned; - break; - case bvh4: - return leaf_check(node0, bvh2) || leaf_check(node1, bvh2); - break; - case bvh8: - return leaf_check(node0, bvh4) || leaf_check(node1, bvh4); - break; - default: - assert(0); - return false; - } -} - /* Triangles */ void BVH::pack_triangle(int idx, float4 tri_verts[3]) diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index c8ad29004d7..33a069eeaf5 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -99,8 +99,6 @@ protected: /* Refit range of primitives. */ void refit_primitives(int start, int end, BoundBox& bbox, uint& visibility); - static __forceinline bool leaf_check(const BVHNode *node, BVH_TYPE bvh); - static bool node_is_unaligned(const BVHNode *node, BVH_TYPE bvh); /* triangles and strands */ void pack_primitives(); @@ -112,6 +110,8 @@ protected: /* for subclasses to implement */ virtual void pack_nodes(const BVHNode *root) = 0; virtual void refit_nodes() = 0; + + virtual BVHNode *widen_children_nodes(const BVHNode *root) = 0; }; /* Pack Utility */ diff --git a/intern/cycles/bvh/bvh2.cpp b/intern/cycles/bvh/bvh2.cpp index 4a423c16559..e5dc4e6b1a8 100644 --- a/intern/cycles/bvh/bvh2.cpp +++ b/intern/cycles/bvh/bvh2.cpp @@ -30,6 +30,11 @@ BVH2::BVH2(const BVHParams& params_, const vector<Object*>& objects_) { } +BVHNode *BVH2::widen_children_nodes(const BVHNode *root) +{ + return const_cast<BVHNode *>(root); +} + void BVH2::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { @@ -188,9 +193,8 @@ void BVH2::pack_nodes(const BVHNode *root) } else { stack.push_back(BVHStackEntry(root, nextNodeIdx)); - nextNodeIdx += node_is_unaligned(root, bvh2) - ? BVH_UNALIGNED_NODE_SIZE - : BVH_NODE_SIZE; + nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_NODE_SIZE + : BVH_NODE_SIZE; } while(stack.size()) { @@ -203,7 +207,7 @@ void BVH2::pack_nodes(const BVHNode *root) pack_leaf(e, leaf); } else { - /* innner node */ + /* inner node */ int idx[2]; for(int i = 0; i < 2; ++i) { if(e.node->get_child(i)->is_leaf()) { @@ -211,7 +215,7 @@ void BVH2::pack_nodes(const BVHNode *root) } else { idx[i] = nextNodeIdx; - nextNodeIdx += node_is_unaligned(e.node->get_child(i), bvh2) + nextNodeIdx += e.node->get_child(i)->has_unaligned() ? BVH_UNALIGNED_NODE_SIZE : BVH_NODE_SIZE; } diff --git a/intern/cycles/bvh/bvh2.h b/intern/cycles/bvh/bvh2.h index ecc697567bb..f38cdf5aca9 100644 --- a/intern/cycles/bvh/bvh2.h +++ b/intern/cycles/bvh/bvh2.h @@ -48,6 +48,9 @@ protected: friend class BVH; BVH2(const BVHParams& params, const vector<Object*>& objects); + /* Building process. */ + virtual BVHNode *widen_children_nodes(const BVHNode *root) override; + /* pack */ void pack_nodes(const BVHNode *root); diff --git a/intern/cycles/bvh/bvh4.cpp b/intern/cycles/bvh/bvh4.cpp index a449587e607..a7c4cea85ce 100644 --- a/intern/cycles/bvh/bvh4.cpp +++ b/intern/cycles/bvh/bvh4.cpp @@ -37,6 +37,68 @@ BVH4::BVH4(const BVHParams& params_, const vector<Object*>& objects_) params.bvh_layout = BVH_LAYOUT_BVH4; } +namespace { + +BVHNode *bvh_node_merge_children_recursively(const BVHNode *node) +{ + if(node->is_leaf()) { + return new LeafNode(*reinterpret_cast<const LeafNode *>(node)); + } + /* Collect nodes of one layer deeper, allowing us to have more childrem in + * an inner layer. */ + assert(node->num_children() <= 2); + const BVHNode *children[4]; + const BVHNode *child0 = node->get_child(0); + const BVHNode *child1 = node->get_child(1); + int num_children = 0; + if(child0->is_leaf()) { + children[num_children++] = child0; + } + else { + children[num_children++] = child0->get_child(0); + children[num_children++] = child0->get_child(1); + } + if(child1->is_leaf()) { + children[num_children++] = child1; + } + else { + children[num_children++] = child1->get_child(0); + children[num_children++] = child1->get_child(1); + } + /* Merge children in subtrees. */ + BVHNode *children4[4]; + for(int i = 0; i < num_children; ++i) { + children4[i] = bvh_node_merge_children_recursively(children[i]); + } + /* Allocate new node. */ + BVHNode *node4 = new InnerNode(node->bounds, children4, num_children); + /* TODO(sergey): Consider doing this from the InnerNode() constructor. + * But in order to do this nicely need to think of how to pass all the + * parameters there. */ + if(node->is_unaligned) { + node4->is_unaligned = true; + node4->aligned_space = new Transform(); + *node4->aligned_space = *node->aligned_space; + } + return node4; +} + +} // namespace + +BVHNode *BVH4::widen_children_nodes(const BVHNode *root) +{ + if(root == NULL) { + return NULL; + } + if(root->is_leaf()) { + return const_cast<BVHNode *>(root); + } + BVHNode *root4 = bvh_node_merge_children_recursively(root); + /* TODO(sergey): Pack children nodes to parents which has less that 4 + * children. */ + return root4; +} + void BVH4::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { float4 data[BVH_QNODE_LEAF_SIZE]; @@ -248,14 +310,14 @@ void BVH4::pack_unaligned_node(int idx, void BVH4::pack_nodes(const BVHNode *root) { /* Calculate size of the arrays required. */ - const size_t num_nodes = root->getSubtreeSize(BVH_STAT_QNODE_COUNT); + const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT); const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); assert(num_leaf_nodes <= num_nodes); const size_t num_inner_nodes = num_nodes - num_leaf_nodes; size_t node_size; if(params.use_unaligned_nodes) { const size_t num_unaligned_nodes = - root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_QNODE_COUNT); + root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT); node_size = (num_unaligned_nodes * BVH_UNALIGNED_QNODE_SIZE) + (num_inner_nodes - num_unaligned_nodes) * BVH_QNODE_SIZE; } @@ -283,9 +345,8 @@ void BVH4::pack_nodes(const BVHNode *root) } else { stack.push_back(BVHStackEntry(root, nextNodeIdx)); - nextNodeIdx += node_is_unaligned(root, bvh4) - ? BVH_UNALIGNED_QNODE_SIZE - : BVH_QNODE_SIZE; + nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE + : BVH_QNODE_SIZE; } while(stack.size()) { @@ -299,44 +360,30 @@ void BVH4::pack_nodes(const BVHNode *root) } else { /* Inner node. */ - const BVHNode *node = e.node; - const BVHNode *node0 = node->get_child(0); - const BVHNode *node1 = node->get_child(1); /* Collect nodes. */ - const BVHNode *nodes[4]; - int numnodes = 0; - if(node0->is_leaf()) { - nodes[numnodes++] = node0; - } - else { - nodes[numnodes++] = node0->get_child(0); - nodes[numnodes++] = node0->get_child(1); - } - if(node1->is_leaf()) { - nodes[numnodes++] = node1; - } - else { - nodes[numnodes++] = node1->get_child(0); - nodes[numnodes++] = node1->get_child(1); - } + const BVHNode *children[4]; + const int num_children = e.node->num_children(); /* Push entries on the stack. */ - for(int i = 0; i < numnodes; ++i) { + for(int i = 0; i < num_children; ++i) { int idx; - if(nodes[i]->is_leaf()) { + children[i] = e.node->get_child(i); + assert(children[i] != NULL); + if(children[i]->is_leaf()) { idx = nextLeafNodeIdx++; } else { idx = nextNodeIdx; - nextNodeIdx += node_is_unaligned(nodes[i], bvh4) + nextNodeIdx += children[i]->has_unaligned() ? BVH_UNALIGNED_QNODE_SIZE : BVH_QNODE_SIZE; } - stack.push_back(BVHStackEntry(nodes[i], idx)); + stack.push_back(BVHStackEntry(children[i], idx)); } /* Set node. */ - pack_inner(e, &stack[stack.size()-numnodes], numnodes); + pack_inner(e, &stack[stack.size() - num_children], num_children); } } + assert(node_size == nextNodeIdx); /* Root index to start traversal at, to handle case of single leaf node. */ pack.root_index = (root->is_leaf())? -1: 0; diff --git a/intern/cycles/bvh/bvh4.h b/intern/cycles/bvh/bvh4.h index 28bab2fe327..2a2a466c767 100644 --- a/intern/cycles/bvh/bvh4.h +++ b/intern/cycles/bvh/bvh4.h @@ -48,6 +48,9 @@ protected: friend class BVH; BVH4(const BVHParams& params, const vector<Object*>& objects); + /* Building process. */ + virtual BVHNode *widen_children_nodes(const BVHNode *root) override; + /* pack */ void pack_nodes(const BVHNode *root); diff --git a/intern/cycles/bvh/bvh8.cpp b/intern/cycles/bvh/bvh8.cpp index b95fe572e27..af930b2f2df 100644 --- a/intern/cycles/bvh/bvh8.cpp +++ b/intern/cycles/bvh/bvh8.cpp @@ -41,6 +41,96 @@ BVH8::BVH8(const BVHParams& params_, const vector<Object*>& objects_) { } +namespace { + +BVHNode *bvh_node_merge_children_recursively(const BVHNode *node) +{ + if(node->is_leaf()) { + return new LeafNode(*reinterpret_cast<const LeafNode *>(node)); + } + /* Collect nodes of two layer deeper, allowing us to have more childrem in + * an inner layer. */ + assert(node->num_children() <= 2); + const BVHNode *children[8]; + const BVHNode *child0 = node->get_child(0); + const BVHNode *child1 = node->get_child(1); + int num_children = 0; + if(child0->is_leaf()) { + children[num_children++] = child0; + } + else { + const BVHNode *child00 = child0->get_child(0), + *child01 = child0->get_child(1); + if(child00->is_leaf()) { + children[num_children++] = child00; + } + else { + children[num_children++] = child00->get_child(0); + children[num_children++] = child00->get_child(1); + } + if(child01->is_leaf()) { + children[num_children++] = child01; + } + else { + children[num_children++] = child01->get_child(0); + children[num_children++] = child01->get_child(1); + } + } + if(child1->is_leaf()) { + children[num_children++] = child1; + } + else { + const BVHNode *child10 = child1->get_child(0), + *child11 = child1->get_child(1); + if(child10->is_leaf()) { + children[num_children++] = child10; + } + else { + children[num_children++] = child10->get_child(0); + children[num_children++] = child10->get_child(1); + } + if(child11->is_leaf()) { + children[num_children++] = child11; + } + else { + children[num_children++] = child11->get_child(0); + children[num_children++] = child11->get_child(1); + } + } + /* Merge children in subtrees. */ + BVHNode *children4[8]; + for(int i = 0; i < num_children; ++i) { + children4[i] = bvh_node_merge_children_recursively(children[i]); + } + /* Allocate new node. */ + BVHNode *node8 = new InnerNode(node->bounds, children4, num_children); + /* TODO(sergey): Consider doing this from the InnerNode() constructor. + * But in order to do this nicely need to think of how to pass all the + * parameters there. */ + if(node->is_unaligned) { + node8->is_unaligned = true; + node8->aligned_space = new Transform(); + *node8->aligned_space = *node->aligned_space; + } + return node8; +} + +} // namespace + +BVHNode *BVH8::widen_children_nodes(const BVHNode *root) +{ + if(root == NULL) { + return NULL; + } + if(root->is_leaf()) { + return const_cast<BVHNode *>(root); + } + BVHNode *root8 = bvh_node_merge_children_recursively(root); + /* TODO(sergey): Pack children nodes to parents which has less that 4 + * children. */ + return root8; +} + void BVH8::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { float4 data[BVH_ONODE_LEAF_SIZE]; @@ -252,14 +342,14 @@ void BVH8::pack_unaligned_node(int idx, void BVH8::pack_nodes(const BVHNode *root) { /* Calculate size of the arrays required. */ - const size_t num_nodes = root->getSubtreeSize(BVH_STAT_ONODE_COUNT); + const size_t num_nodes = root->getSubtreeSize(BVH_STAT_NODE_COUNT); const size_t num_leaf_nodes = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); assert(num_leaf_nodes <= num_nodes); const size_t num_inner_nodes = num_nodes - num_leaf_nodes; size_t node_size; if(params.use_unaligned_nodes) { const size_t num_unaligned_nodes = - root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_ONODE_COUNT); + root->getSubtreeSize(BVH_STAT_UNALIGNED_INNER_COUNT); node_size = (num_unaligned_nodes * BVH_UNALIGNED_ONODE_SIZE) + (num_inner_nodes - num_unaligned_nodes) * BVH_ONODE_SIZE; } @@ -287,9 +377,8 @@ void BVH8::pack_nodes(const BVHNode *root) } else { stack.push_back(BVHStackEntry(root, nextNodeIdx)); - nextNodeIdx += node_is_unaligned(root, bvh8) - ? BVH_UNALIGNED_ONODE_SIZE - : BVH_ONODE_SIZE; + nextNodeIdx += root->has_unaligned() ? BVH_UNALIGNED_ONODE_SIZE + : BVH_ONODE_SIZE; } while(stack.size()) { @@ -303,72 +392,29 @@ void BVH8::pack_nodes(const BVHNode *root) } else { /* Inner node. */ - const BVHNode *node = e.node; - const BVHNode *node0 = node->get_child(0); - const BVHNode *node1 = node->get_child(1); /* Collect nodes. */ - const BVHNode *nodes[8]; - int numnodes = 0; - if(node0->is_leaf()) { - nodes[numnodes++] = node0; - } - else { - const BVHNode *node00 = node0->get_child(0), - *node01 = node0->get_child(1); - if(node00->is_leaf()) { - nodes[numnodes++] = node00; - } - else { - nodes[numnodes++] = node00->get_child(0); - nodes[numnodes++] = node00->get_child(1); - } - if(node01->is_leaf()) { - nodes[numnodes++] = node01; - } - else { - nodes[numnodes++] = node01->get_child(0); - nodes[numnodes++] = node01->get_child(1); - } - } - if(node1->is_leaf()) { - nodes[numnodes++] = node1; - } - else { - const BVHNode *node10 = node1->get_child(0), - *node11 = node1->get_child(1); - if(node10->is_leaf()) { - nodes[numnodes++] = node10; - } - else { - nodes[numnodes++] = node10->get_child(0); - nodes[numnodes++] = node10->get_child(1); - } - if(node11->is_leaf()) { - nodes[numnodes++] = node11; - } - else { - nodes[numnodes++] = node11->get_child(0); - nodes[numnodes++] = node11->get_child(1); - } - } + const BVHNode *children[8]; + int num_children = e.node->num_children(); /* Push entries on the stack. */ - for(int i = 0; i < numnodes; ++i) { + for(int i = 0; i < num_children; ++i) { int idx; - if(nodes[i]->is_leaf()) { + children[i] = e.node->get_child(i); + if(children[i]->is_leaf()) { idx = nextLeafNodeIdx++; } else { idx = nextNodeIdx; - nextNodeIdx += node_is_unaligned(nodes[i], bvh8) - ? BVH_UNALIGNED_ONODE_SIZE - : BVH_ONODE_SIZE; + nextNodeIdx += children[i]->has_unaligned() + ? BVH_UNALIGNED_ONODE_SIZE + : BVH_ONODE_SIZE; } - stack.push_back(BVHStackEntry(nodes[i], idx)); + stack.push_back(BVHStackEntry(children[i], idx)); } /* Set node. */ - pack_inner(e, &stack[stack.size() - numnodes], numnodes); + pack_inner(e, &stack[stack.size() - num_children], num_children); } } + assert(node_size == nextNodeIdx); /* Root index to start traversal at, to handle case of single leaf node. */ pack.root_index = (root->is_leaf()) ? -1 : 0; diff --git a/intern/cycles/bvh/bvh8.h b/intern/cycles/bvh/bvh8.h index 834daf3abce..84f82538c0f 100644 --- a/intern/cycles/bvh/bvh8.h +++ b/intern/cycles/bvh/bvh8.h @@ -59,6 +59,9 @@ protected: friend class BVH; BVH8(const BVHParams& params, const vector<Object*>& objects); + /* Building process. */ + virtual BVHNode *widen_children_nodes(const BVHNode *root) override; + /* pack */ void pack_nodes(const BVHNode *root); diff --git a/intern/cycles/bvh/bvh_embree.cpp b/intern/cycles/bvh/bvh_embree.cpp index 2d6efe8dad5..8415d80c4a8 100644 --- a/intern/cycles/bvh/bvh_embree.cpp +++ b/intern/cycles/bvh/bvh_embree.cpp @@ -436,6 +436,12 @@ void BVHEmbree::build(Progress& progress, Stats *stats_) stats = NULL; } +BVHNode *BVHEmbree::widen_children_nodes(const BVHNode * /*root*/) +{ + assert(!"Must not be called."); + return NULL; +} + void BVHEmbree::add_object(Object *ob, int i) { Mesh *mesh = ob->mesh; diff --git a/intern/cycles/bvh/bvh_embree.h b/intern/cycles/bvh/bvh_embree.h index 9990826ba98..983b6dc07da 100644 --- a/intern/cycles/bvh/bvh_embree.h +++ b/intern/cycles/bvh/bvh_embree.h @@ -40,6 +40,10 @@ public: virtual ~BVHEmbree(); RTCScene scene; static void destroy(RTCScene); + + /* Building process. */ + virtual BVHNode *widen_children_nodes(const BVHNode *root) override; + protected: friend class BVH; BVHEmbree(const BVHParams& params, const vector<Object*>& objects); diff --git a/intern/cycles/bvh/bvh_node.cpp b/intern/cycles/bvh/bvh_node.cpp index fd8b4977699..614fb6be88a 100644 --- a/intern/cycles/bvh/bvh_node.cpp +++ b/intern/cycles/bvh/bvh_node.cpp @@ -47,69 +47,6 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const case BVH_STAT_CHILDNODE_COUNT: cnt = num_children(); break; - case BVH_STAT_QNODE_COUNT: - cnt = 1; - for(int i = 0; i < num_children(); i++) { - BVHNode *node = get_child(i); - if(node->is_leaf()) { - cnt += 1; - } - else { - for(int j = 0; j < node->num_children(); j++) { - cnt += node->get_child(j)->getSubtreeSize(stat); - } - } - } - return cnt; - case BVH_STAT_ONODE_COUNT: - cnt = 1; - for(int i = 0; i < num_children(); i++) { - BVHNode *node = get_child(i); - if(node->is_leaf()) { - cnt += 1; - } - else { - for(int j = 0; j < node->num_children(); j++) - { - BVHNode *node_next = node->get_child(j); - if(node_next->is_leaf()) { - cnt += 1; - } - else { - for(int k = 0; k < node_next->num_children(); k++) { - cnt += node_next->get_child(k)->getSubtreeSize(stat); - } - } - } - } - } - return cnt; - case BVH_STAT_UNALIGNED_INNER_ONODE_COUNT: - { - bool has_unaligned = false; - for(int i = 0; i < num_children(); i++) { - BVHNode *node = get_child(i); - if(node->is_leaf()) { - has_unaligned |= node->is_unaligned; - } - else { - for(int j = 0; j < node->num_children(); j++) { - BVHNode *node_next = node->get_child(j); - if(node_next->is_leaf()) { - has_unaligned |= node_next->is_unaligned; - } - else { - for(int k = 0; k < node_next->num_children(); k++) { - cnt += node_next->get_child(k)->getSubtreeSize(stat); - has_unaligned |= node_next->get_child(k)->is_unaligned; - } - } - } - } - } - cnt += has_unaligned? 1: 0; - } - return cnt; case BVH_STAT_ALIGNED_COUNT: if(!is_unaligned) { cnt = 1; @@ -138,42 +75,6 @@ int BVHNode::getSubtreeSize(BVH_STAT stat) const cnt += has_unaligned? 1: 0; } break; - case BVH_STAT_ALIGNED_INNER_QNODE_COUNT: - { - bool has_unaligned = false; - for(int i = 0; i < num_children(); i++) { - BVHNode *node = get_child(i); - if(node->is_leaf()) { - has_unaligned |= node->is_unaligned; - } - else { - for(int j = 0; j < node->num_children(); j++) { - cnt += node->get_child(j)->getSubtreeSize(stat); - has_unaligned |= node->get_child(j)->is_unaligned; - } - } - } - cnt += has_unaligned? 0: 1; - } - return cnt; - case BVH_STAT_UNALIGNED_INNER_QNODE_COUNT: - { - bool has_unaligned = false; - for(int i = 0; i < num_children(); i++) { - BVHNode *node = get_child(i); - if(node->is_leaf()) { - has_unaligned |= node->is_unaligned; - } - else { - for(int j = 0; j < node->num_children(); j++) { - cnt += node->get_child(j)->getSubtreeSize(stat); - has_unaligned |= node->get_child(j)->is_unaligned; - } - } - } - cnt += has_unaligned? 1: 0; - } - return cnt; case BVH_STAT_ALIGNED_LEAF_COUNT: cnt = (is_leaf() && !is_unaligned) ? 1 : 0; break; @@ -249,6 +150,56 @@ void BVHNode::update_time() } } +namespace { + +struct DumpTraversalContext { + /* Descriptor of wile where writing is happening. */ + FILE *stream; + /* Unique identifier of the node current. */ + int id; +}; + +void dump_subtree(DumpTraversalContext *context, + const BVHNode *node, + const BVHNode *parent = NULL) +{ + if(node->is_leaf()) { + fprintf(context->stream, + " node_%p [label=\"%d\",fillcolor=\"#ccccee\",style=filled]\n", + node, + context->id); + } + else { + fprintf(context->stream, + " node_%p [label=\"%d\",fillcolor=\"#cceecc\",style=filled]\n", + node, + context->id); + } + if(parent != NULL) { + fprintf(context->stream, " node_%p -> node_%p;\n", parent, node); + } + context->id += 1; + for(int i = 0; i < node->num_children(); ++i) { + dump_subtree(context, node->get_child(i), node); + } +} + +} // namespace + +void BVHNode::dump_graph(const char *filename) +{ + DumpTraversalContext context; + context.stream = fopen(filename, "w"); + if(context.stream == NULL) { + return; + } + context.id = 0; + fprintf(context.stream, "digraph BVH {\n"); + dump_subtree(&context, this); + fprintf(context.stream, "}\n"); + fclose(context.stream); +} + /* Inner Node */ void InnerNode::print(int depth) const diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h index 65d5df01158..d9105d69739 100644 --- a/intern/cycles/bvh/bvh_node.h +++ b/intern/cycles/bvh/bvh_node.h @@ -29,18 +29,13 @@ enum BVH_STAT { BVH_STAT_LEAF_COUNT, BVH_STAT_TRIANGLE_COUNT, BVH_STAT_CHILDNODE_COUNT, - BVH_STAT_QNODE_COUNT, BVH_STAT_ALIGNED_COUNT, BVH_STAT_UNALIGNED_COUNT, BVH_STAT_ALIGNED_INNER_COUNT, BVH_STAT_UNALIGNED_INNER_COUNT, - BVH_STAT_ALIGNED_INNER_QNODE_COUNT, - BVH_STAT_UNALIGNED_INNER_QNODE_COUNT, BVH_STAT_ALIGNED_LEAF_COUNT, BVH_STAT_UNALIGNED_LEAF_COUNT, BVH_STAT_DEPTH, - BVH_STAT_ONODE_COUNT, - BVH_STAT_UNALIGNED_INNER_ONODE_COUNT, }; class BVHParams; @@ -48,13 +43,6 @@ class BVHParams; class BVHNode { public: - BVHNode() : is_unaligned(false), - aligned_space(NULL), - time_from(0.0f), - time_to(1.0f) - { - } - virtual ~BVHNode() { delete aligned_space; @@ -85,6 +73,19 @@ public: return *aligned_space; } + inline bool has_unaligned() const + { + if(is_leaf()) { + return false; + } + for(int i = 0; i < num_children(); ++i) { + if(get_child(i)->is_unaligned) { + return true; + } + } + return false; + } + // Subtree functions int getSubtreeSize(BVH_STAT stat=BVH_STAT_NODE_COUNT) const; float computeSubtreeSAHCost(const BVHParams& p, float probability = 1.0f) const; @@ -93,6 +94,9 @@ public: uint update_visibility(); void update_time(); + /* Dump the content of the tree as a graphviz file. */ + void dump_graph(const char *filename); + // Properties. BoundBox bounds; uint visibility; @@ -105,56 +109,130 @@ public: Transform *aligned_space; float time_from, time_to; + +protected: + explicit BVHNode(const BoundBox& bounds) + : bounds(bounds), + visibility(0), + is_unaligned(false), + aligned_space(NULL), + time_from(0.0f), + time_to(1.0f) + { + } + + explicit BVHNode(const BVHNode& other) + : bounds(other.bounds), + visibility(other.visibility), + is_unaligned(other.is_unaligned), + aligned_space(NULL), + time_from(other.time_from), + time_to(other.time_to) + { + if(other.aligned_space != NULL) { + assert(other.is_unaligned); + aligned_space = new Transform(); + *aligned_space = *other.aligned_space; + } + else { + assert(!other.is_unaligned); + } + } }; class InnerNode : public BVHNode { public: + static constexpr int kNumMaxChildren = 8; + InnerNode(const BoundBox& bounds, BVHNode* child0, BVHNode* child1) + : BVHNode(bounds), + num_children_(2) { - this->bounds = bounds; children[0] = child0; children[1] = child1; + reset_unused_children(); - if(child0 && child1) - visibility = child0->visibility|child1->visibility; - else - visibility = 0; /* happens on build cancel */ + if(child0 && child1) { + visibility = child0->visibility | child1->visibility; + } + else { + /* Happens on build cancel. */ + visibility = 0; + } + } + + InnerNode(const BoundBox& bounds, + BVHNode** children, + const int num_children) + : BVHNode(bounds), + num_children_(num_children) + { + visibility = 0; + time_from = FLT_MAX; + time_to = -FLT_MAX; + for(int i = 0; i < num_children; ++i) { + assert(children[i] != NULL); + visibility |= children[i]->visibility; + this->children[i] = children[i]; + time_from = min(time_from, children[i]->time_from); + time_to = max(time_to, children[i]->time_to); + } + reset_unused_children(); } + /* NOTE: This function is only used during binary BVH builder, and it + * supposed to be configured to have 2 children which will be filled in in a + * bit. But this is important to have children reset to NULL. */ explicit InnerNode(const BoundBox& bounds) + : BVHNode(bounds), + num_children_(0) { - this->bounds = bounds; + reset_unused_children(); visibility = 0; - children[0] = NULL; - children[1] = NULL; + num_children_ = 2; } bool is_leaf() const { return false; } - int num_children() const { return 2; } - BVHNode *get_child(int i) const{ assert(i>=0 && i<2); return children[i]; } + int num_children() const { return num_children_; } + BVHNode *get_child(int i) const + { + assert(i >= 0 && i < num_children_); + return children[i]; + } void print(int depth) const; - BVHNode *children[2]; + int num_children_; + BVHNode *children[kNumMaxChildren]; + +protected: + void reset_unused_children() + { + for(int i = num_children_; i < kNumMaxChildren; ++i) { + children[i] = NULL; + } + } }; class LeafNode : public BVHNode { public: LeafNode(const BoundBox& bounds, uint visibility, int lo, int hi) - : lo(lo), + : BVHNode(bounds), + lo(lo), hi(hi) { this->bounds = bounds; this->visibility = visibility; } - LeafNode(const LeafNode& s) - : BVHNode() + LeafNode(const LeafNode& other) + : BVHNode(other), + lo(other.lo), + hi(other.hi) { - *this = s; } bool is_leaf() const { return true; } diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h index d6d283c42c5..1df50504434 100644 --- a/intern/cycles/kernel/kernel_volume.h +++ b/intern/cycles/kernel/kernel_volume.h @@ -383,18 +383,22 @@ ccl_device int kernel_volume_sample_channel(float3 albedo, float3 throughput, fl * Tracing". Matt Jen-Yuan Chiang, Peter Kutz, Brent Burley. SIGGRAPH 2016. */ float3 weights = fabs(throughput * albedo); float sum_weights = weights.x + weights.y + weights.z; + float3 weights_pdf; if(sum_weights > 0.0f) { - *pdf = weights/sum_weights; + weights_pdf = weights/sum_weights; } else { - *pdf = make_float3(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f); + weights_pdf = make_float3(1.0f/3.0f, 1.0f/3.0f, 1.0f/3.0f); } - if(rand < pdf->x) { + *pdf = weights_pdf; + + /* OpenCL does not support -> on float3, so don't use pdf->x. */ + if(rand < weights_pdf.x) { return 0; } - else if(rand < pdf->x + pdf->y) { + else if(rand < weights_pdf.x + weights_pdf.y) { return 1; } else { diff --git a/intern/cycles/kernel/split/kernel_subsurface_scatter.h b/intern/cycles/kernel/split/kernel_subsurface_scatter.h index c51246fbc90..08769fe303b 100644 --- a/intern/cycles/kernel/split/kernel_subsurface_scatter.h +++ b/intern/cycles/kernel/split/kernel_subsurface_scatter.h @@ -47,6 +47,11 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it if(!CLOSURE_IS_BSSRDF(sc->type)) continue; + /* Closure memory will be overwritten, so read required variables now. */ + Bssrdf *bssrdf = (Bssrdf *)sc; + ClosureType bssrdf_type = sc->type; + float bssrdf_roughness = bssrdf->roughness; + /* set up random number generator */ if(branched_state->ss_next_sample == 0 && branched_state->next_hit == 0 && branched_state->next_closure == 0 && branched_state->next_sample == 0) @@ -110,10 +115,6 @@ ccl_device_noinline bool kernel_split_branched_path_subsurface_indirect_light_it *bssrdf_sd = *sd; /* note: copy happens each iteration of inner loop, this is * important as the indirect path will write into bssrdf_sd */ - Bssrdf *bssrdf = (Bssrdf *)sc; - ClosureType bssrdf_type = sc->type; - float bssrdf_roughness = bssrdf->roughness; - LocalIntersection ss_isect_private = *ss_isect; subsurface_scatter_multi_setup(kg, &ss_isect_private, |