[Bf-blender-cvs] [b2172a53c0d] soc-2022-many-lights-sampling: Cycles: add light bvh for access through device kernel
Jeffrey Liu
noreply at git.blender.org
Tue Jun 14 08:13:59 CEST 2022
Commit: b2172a53c0d12a454b51f62811c59bf4d474d8da
Author: Jeffrey Liu
Date: Fri Jun 10 19:41:59 2022 -0400
Branches: soc-2022-many-lights-sampling
https://developer.blender.org/rBb2172a53c0d12a454b51f62811c59bf4d474d8da
Cycles: add light bvh for access through device kernel
===================================================================
M intern/cycles/kernel/textures.h
M intern/cycles/scene/light.cpp
M intern/cycles/scene/light.h
M intern/cycles/scene/light_tree.cpp
M intern/cycles/scene/light_tree.h
===================================================================
diff --git a/intern/cycles/kernel/textures.h b/intern/cycles/kernel/textures.h
index 7deb589a0a9..e15e7cbf01e 100644
--- a/intern/cycles/kernel/textures.h
+++ b/intern/cycles/kernel/textures.h
@@ -1,82 +1,85 @@
-/* SPDX-License-Identifier: Apache-2.0
- * Copyright 2011-2022 Blender Foundation */
-
-#ifndef KERNEL_TEX
-# define KERNEL_TEX(type, name)
-#endif
-
-/* BVH2, not used for OptiX or Embree. */
-KERNEL_TEX(float4, __bvh_nodes)
-KERNEL_TEX(float4, __bvh_leaf_nodes)
-KERNEL_TEX(uint, __prim_type)
-KERNEL_TEX(uint, __prim_visibility)
-KERNEL_TEX(uint, __prim_index)
-KERNEL_TEX(uint, __prim_object)
-KERNEL_TEX(uint, __object_node)
-KERNEL_TEX(float2, __prim_time)
-
-/* objects */
-KERNEL_TEX(KernelObject, __objects)
-KERNEL_TEX(Transform, __object_motion_pass)
-KERNEL_TEX(DecomposedTransform, __object_motion)
-KERNEL_TEX(uint, __object_flag)
-KERNEL_TEX(float, __object_volume_step)
-KERNEL_TEX(uint, __object_prim_offset)
-
-/* cameras */
-KERNEL_TEX(DecomposedTransform, __camera_motion)
-
-/* triangles */
-KERNEL_TEX(uint, __tri_shader)
-KERNEL_TEX(packed_float3, __tri_vnormal)
-KERNEL_TEX(uint4, __tri_vindex)
-KERNEL_TEX(uint, __tri_patch)
-KERNEL_TEX(float2, __tri_patch_uv)
-KERNEL_TEX(packed_float3, __tri_verts)
-
-/* curves */
-KERNEL_TEX(KernelCurve, __curves)
-KERNEL_TEX(float4, __curve_keys)
-KERNEL_TEX(KernelCurveSegment, __curve_segments)
-
-/* patches */
-KERNEL_TEX(uint, __patches)
-
-/* pointclouds */
-KERNEL_TEX(float4, __points)
-KERNEL_TEX(uint, __points_shader)
-
-/* attributes */
-KERNEL_TEX(uint4, __attributes_map)
-KERNEL_TEX(float, __attributes_float)
-KERNEL_TEX(float2, __attributes_float2)
-KERNEL_TEX(packed_float3, __attributes_float3)
-KERNEL_TEX(float4, __attributes_float4)
-KERNEL_TEX(uchar4, __attributes_uchar4)
-
-/* lights */
-KERNEL_TEX(KernelLightDistribution, __light_distribution)
-KERNEL_TEX(KernelLight, __lights)
-KERNEL_TEX(float2, __light_background_marginal_cdf)
-KERNEL_TEX(float2, __light_background_conditional_cdf)
-
-/* particles */
-KERNEL_TEX(KernelParticle, __particles)
-
-/* shaders */
-KERNEL_TEX(uint4, __svm_nodes)
-KERNEL_TEX(KernelShader, __shaders)
-
-/* lookup tables */
-KERNEL_TEX(float, __lookup_table)
-
-/* sobol */
-KERNEL_TEX(float, __sample_pattern_lut)
-
-/* image textures */
-KERNEL_TEX(TextureInfo, __texture_info)
-
-/* ies lights */
-KERNEL_TEX(float, __ies)
-
-#undef KERNEL_TEX
+/* SPDX-License-Identifier: Apache-2.0
+ * Copyright 2011-2022 Blender Foundation */
+
+#ifndef KERNEL_TEX
+# define KERNEL_TEX(type, name)
+#endif
+
+/* BVH2, not used for OptiX or Embree. */
+KERNEL_TEX(float4, __bvh_nodes)
+KERNEL_TEX(float4, __bvh_leaf_nodes)
+KERNEL_TEX(uint, __prim_type)
+KERNEL_TEX(uint, __prim_visibility)
+KERNEL_TEX(uint, __prim_index)
+KERNEL_TEX(uint, __prim_object)
+KERNEL_TEX(uint, __object_node)
+KERNEL_TEX(float2, __prim_time)
+
+/* objects */
+KERNEL_TEX(KernelObject, __objects)
+KERNEL_TEX(Transform, __object_motion_pass)
+KERNEL_TEX(DecomposedTransform, __object_motion)
+KERNEL_TEX(uint, __object_flag)
+KERNEL_TEX(float, __object_volume_step)
+KERNEL_TEX(uint, __object_prim_offset)
+
+/* cameras */
+KERNEL_TEX(DecomposedTransform, __camera_motion)
+
+/* triangles */
+KERNEL_TEX(uint, __tri_shader)
+KERNEL_TEX(packed_float3, __tri_vnormal)
+KERNEL_TEX(uint4, __tri_vindex)
+KERNEL_TEX(uint, __tri_patch)
+KERNEL_TEX(float2, __tri_patch_uv)
+KERNEL_TEX(packed_float3, __tri_verts)
+
+/* curves */
+KERNEL_TEX(KernelCurve, __curves)
+KERNEL_TEX(float4, __curve_keys)
+KERNEL_TEX(KernelCurveSegment, __curve_segments)
+
+/* patches */
+KERNEL_TEX(uint, __patches)
+
+/* pointclouds */
+KERNEL_TEX(float4, __points)
+KERNEL_TEX(uint, __points_shader)
+
+/* attributes */
+KERNEL_TEX(uint4, __attributes_map)
+KERNEL_TEX(float, __attributes_float)
+KERNEL_TEX(float2, __attributes_float2)
+KERNEL_TEX(packed_float3, __attributes_float3)
+KERNEL_TEX(float4, __attributes_float4)
+KERNEL_TEX(uchar4, __attributes_uchar4)
+
+/* lights */
+KERNEL_TEX(KernelLightDistribution, __light_distribution)
+KERNEL_TEX(KernelLight, __lights)
+KERNEL_TEX(float2, __light_background_marginal_cdf)
+KERNEL_TEX(float2, __light_background_conditional_cdf)
+
+/* light tree */
+KERNEL_TEX(KernelLightTreeNode, __light_tree_nodes)
+
+/* particles */
+KERNEL_TEX(KernelParticle, __particles)
+
+/* shaders */
+KERNEL_TEX(uint4, __svm_nodes)
+KERNEL_TEX(KernelShader, __shaders)
+
+/* lookup tables */
+KERNEL_TEX(float, __lookup_table)
+
+/* sobol */
+KERNEL_TEX(float, __sample_pattern_lut)
+
+/* image textures */
+KERNEL_TEX(TextureInfo, __texture_info)
+
+/* ies lights */
+KERNEL_TEX(float, __ies)
+
+#undef KERNEL_TEX
diff --git a/intern/cycles/scene/light.cpp b/intern/cycles/scene/light.cpp
index 402fca968ac..3a6d43aa8e9 100644
--- a/intern/cycles/scene/light.cpp
+++ b/intern/cycles/scene/light.cpp
@@ -24,8 +24,6 @@
#include "util/progress.h"
#include "util/task.h"
-#include <iostream>
-
CCL_NAMESPACE_BEGIN
static void shade_background_pixels(Device *device,
@@ -278,15 +276,33 @@ void LightManager::device_update_distribution(Device *,
bool background_mis = false;
+ /* We want to add both lights and emissive triangles to this vector for light tree construction. */
+ vector<LightTreePrimitive> light_prims;
+
+ /* When we keep track of the light index, only contributing lights will be added to the device.
+ * Therefore, we want to keep track of the light's index on the device.
+ * However, we also need the light's index in the scene when we're constructing the tree. */
+ int device_light_index = 0;
+ int scene_light_index = 0;
foreach (Light *light, scene->lights) {
if (light->is_enabled) {
+ LightTreePrimitive light_prim;
+ light_prim.prim_id = ~device_light_index; /* -prim_id - 1 is a light source index. */
+ light_prim.lamp_id = scene_light_index;
+ light_prims.push_back(light_prim);
+
num_lights++;
+ device_light_index++;
}
if (light->is_portal) {
num_portals++;
}
+
+ scene_light_index++;
}
+ /* Similarly, we also want to keep track of the index of triangles that are emissive. */
+ int device_triangle_index = 0;
foreach (Object *object, scene->objects) {
if (progress.get_cancel())
return;
@@ -295,7 +311,7 @@ void LightManager::device_update_distribution(Device *,
continue;
}
- /* Count triangles. */
+ /* Count emissive triangles. */
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
size_t mesh_num_triangles = mesh->num_triangles();
for (size_t i = 0; i < mesh_num_triangles; i++) {
@@ -305,9 +321,17 @@ void LightManager::device_update_distribution(Device *,
scene->default_surface;
if (shader->get_use_mis() && shader->has_surface_emission) {
+ /* to-do: for the light tree implementation, we eventually want to include emissive triangles.
+ * Right now, point lights are the main concern. */
+ LightTreePrimitive light_prim;
+ light_prim.prim_id = i + mesh->prim_offset;
+ light_prim.object_id = device_triangle_index;
+ light_prims.push_back(light_prim);
num_triangles++;
}
}
+
+ device_triangle_index++;
}
size_t num_distribution = num_triangles + num_lights;
@@ -317,23 +341,65 @@ void LightManager::device_update_distribution(Device *,
KernelLightDistribution *distribution = dscene->light_distribution.alloc(num_distribution + 1);
float totarea = 0.0f;
+ if (scene->integrator->get_use_light_tree()) {
+ /* 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();
+
+ const vector<PackedLightTreeNode> &linearized_bvh = light_tree.get_nodes();
+ KernelLightTreeNode *light_tree_nodes = dscene->light_tree_nodes.alloc(linearized_bvh.size());
+ for (int index = 0; index < linearized_bvh.size(); index++) {
+ const PackedLightTreeNode &node = linearized_bvh[index];
+
+ for (int i = 0; i < 3; i++) {
+ light_tree_nodes[index].bounding_box_min[i] = node.bbox.min[i];
+ light_tree_nodes[index].bounding_box_max[i] = node.bbox.max[i];
+ light_tree_nodes[index].bounding_cone_axis[i] = node.bcone.axis[i];
+ }
+ light_tree_nodes[index].theta_o = node.bcone.theta_o;
+ light_tree_nodes[index].theta_e = node.bcone.theta_e;
+
+ /* 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;
+ light_tree_nodes[index].child_index = -node.first_prim_index;
+ }
+ else {
+ light_tree_nodes[index].energy_variance = node.energy_variance;
+ light_tree_nodes[index].child_index = node.second_child_index;
+ }
+ }
+
+ dscene->light_tree_nodes.copy_to_device();
+ }
+
/* triangles */
size_t offset = 0;
- int j = 0;
- foreach (Object *object, scene->objects) {
+ /* Since the LightTree construction will re-order the primitives such that
+ * light primitives in the same cluster will be adjacent to one another.
+ * Just to be safe, we iterate through the light_prims array in case they've been reordered. */
+ foreach (LightTreePrimitive prim, light_prims) {
if (progress.get_cancel())
return;
+ /* Since we're now iterating through all emissive primitives, we need
+ * to first check if the primitive is actually a triangle. */
+ if (prim.prim_id < 0) {
+ offset++;
+ continue;
+ }
+
+ Object *object = scene->objects[prim.object_id];
+
if (!object_usable_as_light(object)) {
- j++;
continue;
}
/* Sum area. */
Mesh *mesh = static_cast<Mesh *>(object->get_geometry());
bool transform_applied = mesh->transform_applied;
Transform tfm = object->get_tfm();
- int object_id = j;
int shader_flag = 0;
if (!(object->get_visibility() & PATH_RAY_CAMERA)) {
@@ -364,9 +430,9 @@ void LightManager::device_update_distribution(Device *,
if (shader->get_use_mis() && shader->has_surface_emission) {
distribution[off
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list