Commit: 9a0e08c828aa4714c20974559e0f1c055bfbf284 Author: Weizhen Huang Date: Mon Nov 21 19:23:02 2022 +0100 Branches: soc-2022-many-lights-sampling https://developer.blender.org/rB9a0e08c828aa4714c20974559e0f1c055bfbf284
Refactor: merge `PackedLightTreeNode` and `LightTreeBuildNode` to `LightTreeNode` `flatten_tree()` is not needed for sequential build, might need to be added back if converting to parallel build in the future =================================================================== M intern/cycles/scene/light.cpp M intern/cycles/scene/light_tree.cpp M intern/cycles/scene/light_tree.h =================================================================== diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp index cf5019aa664..de133d03939 100644 --- a/intern/cycles/scene/light.cpp +++ b/intern/cycles/scene/light.cpp @@ -569,8 +569,7 @@ void LightManager::device_update_tree(Device *device, /* For now, we'll start with a smaller number of max lights in a node. * More benchmarking is needed to determine what number works best. */ - LightTree light_tree(light_prims, scene, 8); - light_prims = light_tree.get_prims(); + LightTree light_tree(light_prims, 8); /* We want to create separate arrays corresponding to triangles and lights, * which will be used to index back into the light tree for PDF calculations. */ @@ -584,12 +583,12 @@ void LightManager::device_update_tree(Device *device, } /* First initialize the light tree's nodes. */ - const vector<PackedLightTreeNode> &linearized_bvh = light_tree.get_nodes(); + const vector<LightTreeNode> &linearized_bvh = light_tree.get_nodes(); KernelLightTreeNode *light_tree_nodes = dscene->light_tree_nodes.alloc(linearized_bvh.size()); KernelLightTreeEmitter *light_tree_emitters = dscene->light_tree_emitters.alloc( light_prims.size()); for (int index = 0; index < linearized_bvh.size(); index++) { - const PackedLightTreeNode &node = linearized_bvh[index]; + const LightTreeNode &node = linearized_bvh[index]; light_tree_nodes[index].energy = node.energy; @@ -604,11 +603,11 @@ void LightManager::device_update_tree(Device *device, light_tree_nodes[index].bit_trail = node.bit_trail; /* Here we need to make a distinction between interior and leaf nodes. */ - if (node.is_leaf_node) { - light_tree_nodes[index].num_prims = node.num_lights; + if (node.is_leaf()) { + light_tree_nodes[index].num_prims = node.num_prims; light_tree_nodes[index].child_index = -node.first_prim_index; - for (int i = 0; i < node.num_lights; i++) { + for (int i = 0; i < node.num_prims; i++) { int emitter_index = i + node.first_prim_index; LightTreePrimitive &prim = light_prims[emitter_index]; @@ -661,7 +660,7 @@ void LightManager::device_update_tree(Device *device, } } else { - light_tree_nodes[index].child_index = node.second_child_index; + light_tree_nodes[index].child_index = node.right_child_index; } } diff --git a/intern/cycles/scene/light_tree.cpp b/intern/cycles/scene/light_tree.cpp index fca8345150f..f051f30a5fe 100644 --- a/intern/cycles/scene/light_tree.cpp +++ b/intern/cycles/scene/light_tree.cpp @@ -185,103 +185,59 @@ LightTreePrimitive::LightTreePrimitive(Scene *scene, int prim_id, int object_id) } } -void LightTreeBuildNode::init_leaf(const uint &offset, - const uint &n, - const BoundBox &b, - const OrientationBounds &c, - const float &e, - const uint &bits) -{ - bbox = b; - bcone = c; - energy = e; - first_prim_index = offset; - num_lights = n; - - children[0] = children[1] = nullptr; - bit_trail = bits; - is_leaf = true; -} - -void LightTreeBuildNode::init_interior(LightTreeBuildNode *c0, - LightTreeBuildNode *c1, - const BoundBox &b, - const OrientationBounds &c, - const float &e, - const uint &bits) -{ - bbox = b; - bcone = c; - energy = e; - first_prim_index = 0; - num_lights = 0; - - children[0] = c0; - children[1] = c1; - bit_trail = bits; - is_leaf = false; -} - -LightTree::LightTree(const vector<LightTreePrimitive> &prims, - Scene *scene, - uint max_lights_in_leaf) +LightTree::LightTree(vector<LightTreePrimitive> &prims, uint max_lights_in_leaf) { if (prims.empty()) { return; } - prims_ = prims; - scene_ = scene; max_lights_in_leaf_ = max_lights_in_leaf; for (int i = 0; i < prims.size(); i++) { - prims_[i].prim_num = i; + prims[i].prim_num = i; } - int total_nodes = 0; vector<LightTreePrimitive> ordered_prims; - LightTreeBuildNode *root = recursive_build(0, prims.size(), total_nodes, ordered_prims, 0, 0); - prims_ = ordered_prims; - - int offset = 0; - nodes_.resize(total_nodes); - flatten_tree(root, offset); + int num_prims = prims.size(); + ordered_prims.reserve(num_prims); + /* The amount of nodes is estimated to be twice the amount of primitives */ + nodes_.reserve(2 * num_prims); + recursive_build(0, num_prims, prims, ordered_prims, 0, 0); + prims = std::move(ordered_prims); + + nodes_.shrink_to_fit(); } -const vector<LightTreePrimitive> &LightTree::get_prims() const -{ - return prims_; -} - -const vector<PackedLightTreeNode> &LightTree::get_nodes() const +const vector<LightTreeNode> &LightTree::get_nodes() const { return nodes_; } -LightTreeBuildNode *LightTree::recursive_build(int start, - int end, - int &total_nodes, - vector<LightTreePrimitive> &ordered_prims, - uint bit_trail, - int depth) +int LightTree::recursive_build(int start, + int end, + vector<LightTreePrimitive> &prims, + vector<LightTreePrimitive> &ordered_prims, + uint bit_trail, + int depth) { - LightTreeBuildNode *node = new LightTreeBuildNode(); - total_nodes++; - BoundBox node_bbox = BoundBox::empty; - OrientationBounds node_bcone = OrientationBounds::empty; + BoundBox bbox = BoundBox::empty; + OrientationBounds bcone = OrientationBounds::empty; BoundBox centroid_bounds = BoundBox::empty; float energy_total = 0.0; int num_prims = end - start; + int current_index = nodes_.size(); for (int i = start; i < end; i++) { - const LightTreePrimitive &prim = prims_.at(i); - node_bbox.grow(prim.bbox); - node_bcone = merge(node_bcone, prim.bcone); + const LightTreePrimitive &prim = prims.at(i); + bbox.grow(prim.bbox); + bcone = merge(bcone, prim.bcone); centroid_bounds.grow(prim.centroid); energy_total += prim.energy; } + nodes_.emplace_back(bbox, bcone, energy_total, bit_trail); + bool try_splitting = num_prims > 1 && len(centroid_bounds.size()) > 0.0f; int min_dim = -1, min_bucket = 0; bool should_split = false; @@ -289,9 +245,8 @@ LightTreeBuildNode *LightTree::recursive_build(int start, /* Find the best place to split the primitives into 2 nodes. * If the best split cost is no better than making a leaf node, make a leaf instead.*/ float min_cost = min_split_saoh( - centroid_bounds, start, end, node_bbox, node_bcone, min_dim, min_bucket); - should_split = (num_prims > max_lights_in_leaf_ || min_cost < energy_total) && - energy_total > 1e-3f; + centroid_bounds, start, end, bbox, bcone, min_dim, min_bucket, prims); + should_split = num_prims > max_lights_in_leaf_ || min_cost < energy_total; } if (should_split) { int middle; @@ -306,17 +261,17 @@ LightTreeBuildNode *LightTree::recursive_build(int start, LightTreeBucketInfo::num_buckets) + centroid_bounds.min[min_dim]; while (left < right) { - while (prims_[left].centroid[min_dim] <= bounding_dimension && left < end) { + while (prims[left].centroid[min_dim] <= bounding_dimension && left < end) { left++; } - while (prims_[right].centroid[min_dim] > bounding_dimension && right >= start) { + while (prims[right].centroid[min_dim] > bounding_dimension && right >= start) { right--; } if (left < right) { - std::swap(prims_[left].prim_num, prims_[right].prim_num); - std::swap(prims_[left], prims_[right]); + std::swap(prims[left].prim_num, prims[right].prim_num); + std::swap(prims[left], prims[right]); } } @@ -327,23 +282,21 @@ LightTreeBuildNode *LightTree::recursive_build(int start, middle = (start + end) / 2; } - /* At this point, we should expect right to be just past left, - * where left points to the first element that belongs to the right node. */ - LightTreeBuildNode *left_node = recursive_build( - start, middle, total_nodes, ordered_prims, bit_trail, depth + 1); - LightTreeBuildNode *right_node = recursive_build( - middle, end, total_nodes, ordered_prims, bit_trail | (1u << depth), depth + 1); - node->init_interior(left_node, right_node, node_bbox, node_bcone, energy_total, bit_trail); + int left_index = recursive_build(start, middle, prims, ordered_prims, bit_trail, depth + 1); + int right_index = recursive_build( + middle, end, prims, ordered_prims, bit_trail | (1u << depth), depth + 1); + assert(left_index == current_index + 1); + nodes_[current_index].make_interior(right_index); } else { int first_prim_offset = ordered_prims.size(); for (int i = start; i < end; i++) { - int prim_num = prims_[i].prim_num; - ordered_prims.push_back(prims_[prim_num]); + int prim_num = prims[i].prim_num; + ordered_prims.push_back(prims[prim_num]); } - node->init_leaf(first_prim_offset, num_prims, node_bbox, node_bcone, energy_total, bit_trail); + nodes_[current_index].make_leaf(first_prim_offset, num_prims); } - return node; + return current_index; } float LightTree::min_split_saoh(const BoundBox ¢roid_bbox, @@ -352,7 +305,8 @@ float LightTree::min_split_saoh(const BoundBox ¢roid_bbox, const BoundBox &bbox, const OrientationBounds &bcone, int &min_dim, - @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs