diff options
Diffstat (limited to 'intern/cycles/bvh')
-rw-r--r-- | intern/cycles/bvh/bvh.cpp | 238 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh.h | 11 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_binning.cpp | 8 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.cpp | 85 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_build.h | 19 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_node.h | 3 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_params.h | 4 | ||||
-rw-r--r-- | intern/cycles/bvh/bvh_split.cpp | 2 |
8 files changed, 209 insertions, 161 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 9fa602f0952..350ca16f6e2 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -28,6 +28,7 @@ #include "util_cache.h" #include "util_debug.h" #include "util_foreach.h" +#include "util_logging.h" #include "util_map.h" #include "util_progress.h" #include "util_system.h" @@ -106,25 +107,25 @@ bool BVH::cache_read(CacheData& key) if(!(value.read(pack.root_index) && value.read(pack.SAH) && value.read(pack.nodes) && + value.read(pack.leaf_nodes) && value.read(pack.object_node) && value.read(pack.tri_woop) && value.read(pack.prim_type) && value.read(pack.prim_visibility) && value.read(pack.prim_index) && - value.read(pack.prim_object) && - value.read(pack.is_leaf))) + value.read(pack.prim_object))) { /* Clear the pack if load failed. */ pack.root_index = 0; pack.SAH = 0.0f; pack.nodes.clear(); + pack.leaf_nodes.clear(); pack.object_node.clear(); pack.tri_woop.clear(); pack.prim_type.clear(); pack.prim_visibility.clear(); pack.prim_index.clear(); pack.prim_object.clear(); - pack.is_leaf.clear(); return false; } return true; @@ -141,13 +142,13 @@ void BVH::cache_write(CacheData& key) value.add(pack.SAH); value.add(pack.nodes); + value.add(pack.leaf_nodes); value.add(pack.object_node); value.add(pack.tri_woop); value.add(pack.prim_type); value.add(pack.prim_visibility); value.add(pack.prim_index); value.add(pack.prim_object); - value.add(pack.is_leaf); Cache::global.insert(key, value); @@ -189,11 +190,12 @@ void BVH::build(Progress& progress) } /* build nodes */ - vector<int> prim_type; - vector<int> prim_index; - vector<int> prim_object; - - BVHBuild bvh_build(objects, prim_type, prim_index, prim_object, params, progress); + BVHBuild bvh_build(objects, + pack.prim_type, + pack.prim_index, + pack.prim_object, + params, + progress); BVHNode *root = bvh_build.run(); if(progress.get_cancel()) { @@ -201,14 +203,6 @@ void BVH::build(Progress& progress) return; } - /* todo: get rid of this copy */ - pack.prim_type = prim_type; - pack.prim_index = prim_index; - pack.prim_object = prim_object; - prim_type.free_memory(); - prim_index.free_memory(); - prim_object.free_memory(); - /* compute SAH */ if(!params.top_level) pack.SAH = root->computeSubtreeSAHCost(params); @@ -322,13 +316,14 @@ void BVH::pack_primitives() /* Pack Instances */ -void BVH::pack_instances(size_t nodes_size) +void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size) { /* The BVH's for instances are built separately, but for traversal all * BVH's are stored in global arrays. This function merges them into the * top level BVH, adjusting indexes and offsets where appropriate. */ bool use_qbvh = params.use_qbvh; size_t nsize = (use_qbvh)? BVH_QNODE_SIZE: BVH_NODE_SIZE; + size_t nsize_leaf = (use_qbvh)? BVH_QNODE_LEAF_SIZE: BVH_NODE_LEAF_SIZE; /* adjust primitive index to point to the triangle in the global array, for * meshes with transform applied and already in the top level BVH */ @@ -343,6 +338,7 @@ void BVH::pack_instances(size_t nodes_size) /* track offsets of instanced BVH data in global array */ size_t prim_offset = pack.prim_index.size(); size_t nodes_offset = nodes_size; + size_t nodes_leaf_offset = leaf_nodes_size; /* clear array that gives the node indexes for instanced objects */ pack.object_node.clear(); @@ -354,6 +350,7 @@ void BVH::pack_instances(size_t nodes_size) size_t pack_prim_index_offset = prim_index_size; size_t pack_tri_woop_offset = tri_woop_size; size_t pack_nodes_offset = nodes_size; + size_t pack_leaf_nodes_offset = leaf_nodes_size; size_t object_offset = 0; map<Mesh*, int> mesh_map; @@ -367,6 +364,7 @@ void BVH::pack_instances(size_t nodes_size) prim_index_size += bvh->pack.prim_index.size(); tri_woop_size += bvh->pack.tri_woop.size(); nodes_size += bvh->pack.nodes.size(); + leaf_nodes_size += bvh->pack.leaf_nodes.size(); mesh_map[mesh] = 1; } @@ -381,6 +379,7 @@ void BVH::pack_instances(size_t nodes_size) pack.prim_visibility.resize(prim_index_size); pack.tri_woop.resize(tri_woop_size); pack.nodes.resize(nodes_size); + pack.leaf_nodes.resize(leaf_nodes_size); pack.object_node.resize(objects.size()); int *pack_prim_index = (pack.prim_index.size())? &pack.prim_index[0]: NULL; @@ -389,6 +388,7 @@ void BVH::pack_instances(size_t nodes_size) uint *pack_prim_visibility = (pack.prim_visibility.size())? &pack.prim_visibility[0]: NULL; float4 *pack_tri_woop = (pack.tri_woop.size())? &pack.tri_woop[0]: NULL; int4 *pack_nodes = (pack.nodes.size())? &pack.nodes[0]: NULL; + int4 *pack_leaf_nodes = (pack.leaf_nodes.size())? &pack.leaf_nodes[0]: NULL; /* merge */ foreach(Object *ob, objects) { @@ -414,12 +414,13 @@ void BVH::pack_instances(size_t nodes_size) BVH *bvh = mesh->bvh; int noffset = nodes_offset/nsize; + int noffset_leaf = nodes_leaf_offset/nsize_leaf; int mesh_tri_offset = mesh->tri_offset; int mesh_curve_offset = mesh->curve_offset; /* fill in node indexes for instances */ - if((bvh->pack.is_leaf.size() != 0) && bvh->pack.is_leaf[0]) - pack.object_node[object_offset++] = -noffset-1; + if(bvh->pack.root_index == -1) + pack.object_node[object_offset++] = -noffset_leaf-1; else pack.object_node[object_offset++] = noffset; @@ -453,6 +454,18 @@ void BVH::pack_instances(size_t nodes_size) } /* merge nodes */ + if(bvh->pack.leaf_nodes.size()) { + int4 *leaf_nodes_offset = &bvh->pack.leaf_nodes[0]; + size_t leaf_nodes_offset_size = bvh->pack.leaf_nodes.size(); + for(size_t i = 0, j = 0; i < leaf_nodes_offset_size; i+=nsize_leaf, j++) { + int4 data = leaf_nodes_offset[i]; + data.x += prim_offset; + data.y += prim_offset; + pack_leaf_nodes[pack_leaf_nodes_offset] = data; + pack_leaf_nodes_offset += nsize_leaf; + } + } + if(bvh->pack.nodes.size()) { /* For QBVH we're packing a child bbox into 6 float4, * and for regular BVH they're packed into 3 float4. @@ -460,7 +473,6 @@ void BVH::pack_instances(size_t nodes_size) size_t nsize_bbox = (use_qbvh)? 6: 3; int4 *bvh_nodes = &bvh->pack.nodes[0]; size_t bvh_nodes_size = bvh->pack.nodes.size(); - bool *bvh_is_leaf = (bvh->pack.is_leaf.size() != 0) ? &bvh->pack.is_leaf[0] : NULL; for(size_t i = 0, j = 0; i < bvh_nodes_size; i+=nsize, j++) { memcpy(pack_nodes + pack_nodes_offset, bvh_nodes + i, nsize_bbox*sizeof(int4)); @@ -468,18 +480,12 @@ void BVH::pack_instances(size_t nodes_size) /* modify offsets into arrays */ int4 data = bvh_nodes[i + nsize_bbox]; - if(bvh_is_leaf && bvh_is_leaf[j]) { - data.x += prim_offset; - data.y += prim_offset; - } - else { - data.x += (data.x < 0)? -noffset: noffset; - data.y += (data.y < 0)? -noffset: noffset; + data.x += (data.x < 0)? -noffset_leaf: noffset; + data.y += (data.y < 0)? -noffset_leaf: noffset; - if(use_qbvh) { - data.z += (data.z < 0)? -noffset: noffset; - data.w += (data.w < 0)? -noffset: noffset; - } + if(use_qbvh) { + data.z += (data.z < 0)? -noffset_leaf: noffset; + data.w += (data.w < 0)? -noffset_leaf: noffset; } pack_nodes[pack_nodes_offset + nsize_bbox] = data; @@ -496,6 +502,7 @@ void BVH::pack_instances(size_t nodes_size) } nodes_offset += bvh->pack.nodes.size(); + nodes_leaf_offset += bvh->pack.leaf_nodes.size(); prim_offset += bvh->pack.prim_index.size(); } } @@ -509,20 +516,24 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_ void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { + float4 data[BVH_NODE_LEAF_SIZE]; + memset(data, 0, sizeof(data)); 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); + data[0].x = __int_as_float(~(leaf->m_lo)); + data[0].y = __int_as_float(0); } 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); + /* triangle */ + data[0].x = __int_as_float(leaf->m_lo); + data[0].y = __int_as_float(leaf->m_hi); + } + data[0].z = __uint_as_float(leaf->m_visibility); + if(leaf->num_triangles() != 0) { + data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]); } + memcpy(&pack.leaf_nodes[e.idx * BVH_NODE_LEAF_SIZE], data, sizeof(float4)*BVH_NODE_LEAF_SIZE); } void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1) @@ -545,31 +556,36 @@ void RegularBVH::pack_node(int idx, const BoundBox& b0, const BoundBox& b1, int void RegularBVH::pack_nodes(const BVHNode *root) { - size_t node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT); + size_t tot_node_size = root->getSubtreeSize(BVH_STAT_NODE_COUNT); + size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); + size_t node_size = tot_node_size - leaf_node_size; /* resize arrays */ pack.nodes.clear(); - pack.is_leaf.clear(); - pack.is_leaf.resize(node_size); /* for top level BVH, first merge existing BVH's so we know the offsets */ - if(params.top_level) - pack_instances(node_size*BVH_NODE_SIZE); - else + if(params.top_level) { + pack_instances(node_size*BVH_NODE_SIZE, + leaf_node_size*BVH_NODE_LEAF_SIZE); + } + else { pack.nodes.resize(node_size*BVH_NODE_SIZE); + pack.leaf_nodes.resize(leaf_node_size*BVH_NODE_LEAF_SIZE); + } - int nextNodeIdx = 0; + int nextNodeIdx = 0, nextLeafNodeIdx = 0; vector<BVHStackEntry> stack; stack.reserve(BVHParams::MAX_DEPTH*2); - stack.push_back(BVHStackEntry(root, nextNodeIdx++)); + if(root->is_leaf()) + stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); + else + stack.push_back(BVHStackEntry(root, nextNodeIdx++)); while(stack.size()) { BVHStackEntry e = stack.back(); stack.pop_back(); - pack.is_leaf[e.idx] = e.node->is_leaf(); - if(e.node->is_leaf()) { /* leaf node */ const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node); @@ -577,15 +593,17 @@ void RegularBVH::pack_nodes(const BVHNode *root) } else { /* innner node */ - stack.push_back(BVHStackEntry(e.node->get_child(0), nextNodeIdx++)); - stack.push_back(BVHStackEntry(e.node->get_child(1), nextNodeIdx++)); + int idx0 = (e.node->get_child(0)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++); + int idx1 = (e.node->get_child(1)->is_leaf())? (nextLeafNodeIdx++) : (nextNodeIdx++); + stack.push_back(BVHStackEntry(e.node->get_child(0), idx0)); + stack.push_back(BVHStackEntry(e.node->get_child(1), idx1)); pack_inner(e, stack[stack.size()-2], stack[stack.size()-1]); } } /* root index to start traversal at, to handle case of single leaf node */ - pack.root_index = (pack.is_leaf[0])? -1: 0; + pack.root_index = (root->is_leaf())? -1: 0; } void RegularBVH::refit_nodes() @@ -594,17 +612,15 @@ void RegularBVH::refit_nodes() BoundBox bbox = BoundBox::empty; uint visibility = 0; - refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility); + refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility); } void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) { - int4 *data = &pack.nodes[idx*BVH_NODE_SIZE]; - - int c0 = data[3].x; - int c1 = data[3].y; - if(leaf) { + int4 *data = &pack.leaf_nodes[idx*BVH_NODE_LEAF_SIZE]; + int c0 = data[0].x; + int c1 = data[0].y; /* refit leaf node */ for(int prim = c0; prim < c1; prim++) { int pidx = pack.prim_index[prim]; @@ -638,7 +654,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility size_t steps = mesh->motion_steps - 1; float4 *key_steps = attr->data_float4(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bbox); } } @@ -660,7 +676,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) triangle.bounds_grow(vert_steps + i*mesh_size, bbox); } } @@ -670,9 +686,20 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility visibility |= ob->visibility; } - pack_node(idx, bbox, bbox, c0, c1, visibility, data[3].w); + /* TODO(sergey): De-duplicate with pack_leaf(). */ + float4 leaf_data[BVH_NODE_LEAF_SIZE]; + leaf_data[0].x = __int_as_float(c0); + leaf_data[0].y = __int_as_float(c1); + leaf_data[0].z = __uint_as_float(visibility); + leaf_data[0].w = __uint_as_float(data[0].w); + memcpy(&pack.leaf_nodes[idx * BVH_NODE_LEAF_SIZE], + leaf_data, + sizeof(float4)*BVH_NODE_LEAF_SIZE); } else { + int4 *data = &pack.nodes[idx*BVH_NODE_SIZE]; + int c0 = data[3].x; + int c1 = data[3].y; /* refit inner node, set bbox from children */ BoundBox bbox0 = BoundBox::empty, bbox1 = BoundBox::empty; uint visibility0 = 0, visibility1 = 0; @@ -698,26 +725,24 @@ QBVH::QBVH(const BVHParams& params_, const vector<Object*>& objects_) void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { - float4 data[BVH_QNODE_SIZE]; - + float4 data[BVH_QNODE_LEAF_SIZE]; memset(data, 0, sizeof(data)); - if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) { /* object */ - data[6].x = __int_as_float(~(leaf->m_lo)); - data[6].y = __int_as_float(0); + data[0].x = __int_as_float(~(leaf->m_lo)); + data[0].y = __int_as_float(0); } else { /* triangle */ - data[6].x = __int_as_float(leaf->m_lo); - data[6].y = __int_as_float(leaf->m_hi); + data[0].x = __int_as_float(leaf->m_lo); + data[0].y = __int_as_float(leaf->m_hi); } - data[6].z = __uint_as_float(leaf->m_visibility); + data[0].z = __uint_as_float(leaf->m_visibility); if(leaf->num_triangles() != 0) { - data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]); + data[0].w = __uint_as_float(pack.prim_type[leaf->m_lo]); } - memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE); + memcpy(&pack.leaf_nodes[e.idx * BVH_QNODE_LEAF_SIZE], data, sizeof(float4)*BVH_QNODE_LEAF_SIZE); } void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num) @@ -761,31 +786,39 @@ void QBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry *en, int num) void QBVH::pack_nodes(const BVHNode *root) { - size_t node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT); + size_t tot_node_size = root->getSubtreeSize(BVH_STAT_QNODE_COUNT); + size_t leaf_node_size = root->getSubtreeSize(BVH_STAT_LEAF_COUNT); + size_t node_size = tot_node_size - leaf_node_size; /* resize arrays */ pack.nodes.clear(); - pack.is_leaf.clear(); - pack.is_leaf.resize(node_size); + pack.leaf_nodes.clear(); /* for top level BVH, first merge existing BVH's so we know the offsets */ - if(params.top_level) - pack_instances(node_size*BVH_QNODE_SIZE); - else + if(params.top_level) { + pack_instances(node_size*BVH_QNODE_SIZE, + leaf_node_size*BVH_QNODE_LEAF_SIZE); + } + else { pack.nodes.resize(node_size*BVH_QNODE_SIZE); + pack.leaf_nodes.resize(leaf_node_size*BVH_QNODE_LEAF_SIZE); + } - int nextNodeIdx = 0; + int nextNodeIdx = 0, nextLeafNodeIdx = 0; vector<BVHStackEntry> stack; stack.reserve(BVHParams::MAX_DEPTH*2); - stack.push_back(BVHStackEntry(root, nextNodeIdx++)); + if(root->is_leaf()) { + stack.push_back(BVHStackEntry(root, nextLeafNodeIdx++)); + } + else { + stack.push_back(BVHStackEntry(root, nextNodeIdx++)); + } while(stack.size()) { BVHStackEntry e = stack.back(); stack.pop_back(); - pack.is_leaf[e.idx] = e.node->is_leaf(); - if(e.node->is_leaf()) { /* leaf node */ const LeafNode* leaf = reinterpret_cast<const LeafNode*>(e.node); @@ -818,8 +851,16 @@ void QBVH::pack_nodes(const BVHNode *root) } /* push entries on the stack */ - for(int i = 0; i < numnodes; i++) - stack.push_back(BVHStackEntry(nodes[i], nextNodeIdx++)); + for(int i = 0; i < numnodes; i++) { + int idx; + if(nodes[i]->is_leaf()) { + idx = nextLeafNodeIdx++; + } + else { + idx = nextNodeIdx++; + } + stack.push_back(BVHStackEntry(nodes[i], idx)); + } /* set node */ pack_inner(e, &stack[stack.size()-numnodes], numnodes); @@ -827,7 +868,7 @@ void QBVH::pack_nodes(const BVHNode *root) } /* root index to start traversal at, to handle case of single leaf node */ - pack.root_index = (pack.is_leaf[0])? -1: 0; + pack.root_index = (root->is_leaf())? -1: 0; } void QBVH::refit_nodes() @@ -836,14 +877,14 @@ void QBVH::refit_nodes() BoundBox bbox = BoundBox::empty; uint visibility = 0; - refit_node(0, (pack.is_leaf[0])? true: false, bbox, visibility); + refit_node(0, (pack.root_index == -1)? true: false, bbox, visibility); } void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) { - int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE]; - int4 c = data[6]; if(leaf) { + int4 *data = &pack.leaf_nodes[idx*BVH_QNODE_LEAF_SIZE]; + int4 c = data[0]; /* Refit leaf node. */ for(int prim = c.x; prim < c.y; prim++) { int pidx = pack.prim_index[prim]; @@ -877,7 +918,7 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) size_t steps = mesh->motion_steps - 1; float4 *key_steps = attr->data_float4(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bbox); } } @@ -899,7 +940,7 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) size_t steps = mesh->motion_steps - 1; float3 *vert_steps = attr->data_float3(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) triangle.bounds_grow(vert_steps + i*mesh_size, bbox); } } @@ -919,17 +960,18 @@ void QBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility) * * Same applies to the inner nodes case below. */ - float4 leaf_data[BVH_QNODE_SIZE]; - memset(leaf_data, 0, sizeof(leaf_data)); - leaf_data[6].x = __int_as_float(c.x); - leaf_data[6].y = __int_as_float(c.y); - leaf_data[6].z = __uint_as_float(visibility); - leaf_data[6].w = __uint_as_float(c.w); - memcpy(&pack.nodes[idx * BVH_QNODE_SIZE], + float4 leaf_data[BVH_QNODE_LEAF_SIZE]; + leaf_data[0].x = __int_as_float(c.x); + leaf_data[0].y = __int_as_float(c.y); + leaf_data[0].z = __uint_as_float(visibility); + leaf_data[0].w = __uint_as_float(c.w); + memcpy(&pack.leaf_nodes[idx * BVH_QNODE_LEAF_SIZE], leaf_data, - sizeof(float4)*BVH_QNODE_SIZE); + sizeof(float4)*BVH_QNODE_LEAF_SIZE); } else { + int4 *data = &pack.nodes[idx*BVH_QNODE_SIZE]; + int4 c = data[6]; /* Refit inner node, set bbox from children. */ BoundBox child_bbox[4] = {BoundBox::empty, BoundBox::empty, diff --git a/intern/cycles/bvh/bvh.h b/intern/cycles/bvh/bvh.h index 40f039541eb..669d2ccdcd5 100644 --- a/intern/cycles/bvh/bvh.h +++ b/intern/cycles/bvh/bvh.h @@ -36,7 +36,9 @@ class Object; class Progress; #define BVH_NODE_SIZE 4 +#define BVH_NODE_LEAF_SIZE 1 #define BVH_QNODE_SIZE 7 +#define BVH_QNODE_LEAF_SIZE 1 #define BVH_ALIGN 4096 #define TRI_NODE_SIZE 3 @@ -47,7 +49,9 @@ class Progress; struct PackedBVH { /* BVH nodes storage, one node is 4x int4, and contains two bounding boxes, * and child, triangle or object indexes depending on the node type */ - array<int4> nodes; + array<int4> nodes; + /* BVH leaf nodes storage. */ + array<int4> leaf_nodes; /* object index to BVH node index mapping for instances */ array<int> object_node; /* precomputed triangle intersection data, one triangle is 4x float4 */ @@ -61,9 +65,6 @@ struct PackedBVH { array<int> prim_index; /* mapping from BVH primitive index, to the object id of that primitive. */ array<int> prim_object; - /* quick array to lookup if a node is a leaf, not used for traversal, only - * for instance BVH merging */ - array<bool> is_leaf; /* index of the root node. */ int root_index; @@ -108,7 +109,7 @@ protected: void pack_triangle(int idx, float4 woop[3]); /* merge instance BVH's */ - void pack_instances(size_t nodes_size); + void pack_instances(size_t nodes_size, size_t leaf_nodes_size); /* for subclasses to implement */ virtual void pack_nodes(const BVHNode *root) = 0; diff --git a/intern/cycles/bvh/bvh_binning.cpp b/intern/cycles/bvh/bvh_binning.cpp index bd37ffbcf38..db96490a36f 100644 --- a/intern/cycles/bvh/bvh_binning.cpp +++ b/intern/cycles/bvh/bvh_binning.cpp @@ -29,10 +29,10 @@ CCL_NAMESPACE_BEGIN /* SSE replacements */ -__forceinline void prefetch_L1 (const void* ptr) { } -__forceinline void prefetch_L2 (const void* ptr) { } -__forceinline void prefetch_L3 (const void* ptr) { } -__forceinline void prefetch_NTA(const void* ptr) { } +__forceinline void prefetch_L1 (const void* /*ptr*/) { } +__forceinline void prefetch_L2 (const void* /*ptr*/) { } +__forceinline void prefetch_L3 (const void* /*ptr*/) { } +__forceinline void prefetch_NTA(const void* /*ptr*/) { } template<size_t src> __forceinline float extract(const int4& b) { return b[src]; } diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 4ce8f787169..a44ad656316 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -42,7 +42,7 @@ ccl_device_inline int bitscan(int value) { assert(value != 0); int bit = 0; - while (value >>= 1) { + while(value >>= 1) { ++bit; } return bit; @@ -65,15 +65,18 @@ public: /* Constructor / Destructor */ BVHBuild::BVHBuild(const vector<Object*>& objects_, - vector<int>& prim_type_, vector<int>& prim_index_, vector<int>& prim_object_, - const BVHParams& params_, Progress& progress_) -: objects(objects_), - prim_type(prim_type_), - prim_index(prim_index_), - prim_object(prim_object_), - params(params_), - progress(progress_), - progress_start_time(0.0) + array<int>& prim_type_, + array<int>& prim_index_, + array<int>& prim_object_, + const BVHParams& params_, + Progress& progress_) + : objects(objects_), + prim_type(prim_type_), + prim_index(prim_index_), + prim_object(prim_object_), + params(params_), + progress(progress_), + progress_start_time(0.0) { spatial_min_overlap = 0.0f; } @@ -136,7 +139,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, size_t steps = mesh->motion_steps - 1; float4 *key_steps = curve_attr_mP->data_float4(); - for (size_t i = 0; i < steps; i++) + for(size_t i = 0; i < steps; i++) curve.bounds_grow(k, key_steps + i*mesh_size, bounds); type = PRIMITIVE_MOTION_CURVE; @@ -446,18 +449,10 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, return new LeafNode(bounds, 0, 0, 0); } else if(num == 1) { - if(start == prim_index.size()) { - assert(params.use_spatial_split); - - prim_type.push_back(ref->prim_type()); - prim_index.push_back(ref->prim_index()); - prim_object.push_back(ref->prim_object()); - } - else { - prim_type[start] = ref->prim_type(); - prim_index[start] = ref->prim_index(); - prim_object[start] = ref->prim_object(); - } + assert(start < prim_type.size()); + prim_type[start] = ref->prim_type(); + prim_index[start] = ref->prim_index(); + prim_object[start] = ref->prim_object(); uint visibility = objects[ref->prim_object()]->visibility; return new LeafNode(ref->bounds(), visibility, start, start+1); @@ -484,17 +479,9 @@ BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type, int num) { 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]; - } + 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); } @@ -535,6 +522,19 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) } } + /* Extend an array when needed. */ + if(prim_type.size() < range.end()) { + assert(params.use_spatial_split); + /* TODO(sergey): We might want to look into different policies of + * re-allocation here, so on the one hand we would not do as much + * re-allocations and on the other hand will have small memory + * overhead. + */ + prim_type.resize(range.end()); + prim_index.resize(range.end()); + prim_object.resize(range.end()); + } + /* Create leaf nodes for every existing primitive. */ BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL}; int num_leaves = 0; @@ -577,17 +577,22 @@ BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) return new InnerNode(range.bounds(), leaves[0], leaves[1]); } else if(num_leaves == 3) { - BoundBox inner_bounds = merge(bounds[1], bounds[2]); + BoundBox inner_bounds = merge(leaves[1]->m_bounds, leaves[2]->m_bounds); BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]); return new InnerNode(range.bounds(), leaves[0], inner); - } else /*if(num_leaves == 4)*/ { + } else { /* 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]); + assert(num_leaves <= 5); + BoundBox inner_bounds_a = merge(leaves[0]->m_bounds, leaves[1]->m_bounds); + BoundBox inner_bounds_b = merge(leaves[2]->m_bounds, leaves[3]->m_bounds); 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); + BoundBox inner_bounds_c = merge(inner_a->m_bounds, inner_b->m_bounds); + BVHNode *inner_c = new InnerNode(inner_bounds_c, inner_a, inner_b); + if(num_leaves == 5) { + return new InnerNode(range.bounds(), inner_c, leaves[4]); + } + return inner_c; } } diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index 294c5a1758d..eefb7b60f7c 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -42,13 +42,12 @@ class BVHBuild { public: /* Constructor/Destructor */ - BVHBuild( - const vector<Object*>& objects, - vector<int>& prim_type, - vector<int>& prim_index, - vector<int>& prim_object, - const BVHParams& params, - Progress& progress); + BVHBuild(const vector<Object*>& objects, + array<int>& prim_type, + array<int>& prim_index, + array<int>& prim_object, + const BVHParams& params, + Progress& progress); ~BVHBuild(); BVHNode *run(); @@ -99,9 +98,9 @@ protected: int num_original_references; /* output primitive indexes and objects */ - vector<int>& prim_type; - vector<int>& prim_index; - vector<int>& prim_object; + array<int>& prim_type; + array<int>& prim_index; + array<int>& prim_object; /* build parameters */ BVHParams params; diff --git a/intern/cycles/bvh/bvh_node.h b/intern/cycles/bvh/bvh_node.h index 1656bb367a4..44f5518229b 100644 --- a/intern/cycles/bvh/bvh_node.h +++ b/intern/cycles/bvh/bvh_node.h @@ -24,8 +24,7 @@ CCL_NAMESPACE_BEGIN -enum BVH_STAT -{ +enum BVH_STAT { BVH_STAT_NODE_COUNT, BVH_STAT_INNER_COUNT, BVH_STAT_LEAF_COUNT, diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 99bfd9449da..af8d8eeb3ee 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -113,7 +113,9 @@ public: __forceinline int prim_type() const { return type; } BVHReference& operator=(const BVHReference &arg) { - memcpy(this, &arg, sizeof(BVHReference)); + if(&arg != this) { + memcpy(this, &arg, sizeof(BVHReference)); + } return *this; } diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 07c35c08c18..2290c4143ad 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -253,7 +253,7 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH Object *ob = builder->objects[ref.prim_object()]; const Mesh *mesh = ob->mesh; - if (ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { + if(ref.prim_type() & PRIMITIVE_ALL_TRIANGLE) { const int *inds = mesh->triangles[ref.prim_index()].v; const float3 *verts = &mesh->verts[0]; const float3* v1 = &verts[inds[2]]; |