[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