[Bf-blender-cvs] [9a0e08c828a] soc-2022-many-lights-sampling: 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
Weizhen Huang
noreply at git.blender.org
Mon Nov 21 19:25:52 CET 2022
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. @@
More information about the Bf-blender-cvs
mailing list