Cycles: Replace use_qbvh boolean flag with an enum-based property
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 19 Jan 2018 09:59:58 +0000 (10:59 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Mon, 22 Jan 2018 16:19:20 +0000 (17:19 +0100)
This was we can introduce other types of BVH, for example, wider ones, without
causing too much mess around boolean flags.

Thoughs:

- Ideally device info should probably return bitflag of what BVH types it
  supports.

  It is possible to implement based on simple logic in device/ and mesh.cpp,
  rest of the changes will stay the same.

- Not happy with workarounds in util_debug and duplicated enum in kernel.
  Maybe enbum should be stores in kernel, but then it's kind of weird to include
  kernel types from utils. Soudns some cyclkic dependency.

Reviewers: brecht, maxim_d33

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D3011

23 files changed:
intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_python.cpp
intern/cycles/blender/blender_sync.cpp
intern/cycles/bvh/bvh.cpp
intern/cycles/bvh/bvh4.cpp
intern/cycles/bvh/bvh_params.h
intern/cycles/device/device.cpp
intern/cycles/device/device.h
intern/cycles/device/device_cpu.cpp
intern/cycles/device/device_cuda.cpp
intern/cycles/device/device_network.cpp
intern/cycles/device/device_opencl.cpp
intern/cycles/kernel/bvh/bvh_local.h
intern/cycles/kernel/bvh/bvh_shadow_all.h
intern/cycles/kernel/bvh/bvh_traversal.h
intern/cycles/kernel/bvh/bvh_volume.h
intern/cycles/kernel/bvh/bvh_volume_all.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/mesh.cpp
intern/cycles/render/scene.h
intern/cycles/util/util_debug.cpp
intern/cycles/util/util_debug.h

index 7410cc3234299184750efbd6fe34865b9ecacc4b..a63d84f2da68ba57723939d5c12235d77ea152a5 100644 (file)
@@ -47,6 +47,11 @@ enum_displacement_methods = (
     ('BOTH', "Both", "Combination of displacement and bump mapping"),
     )
 
+enum_bvh_layouts = (
+    ('BVH2', "BVH2", "", 1),
+    ('BVH4', "BVH4", "", 2),
+    )
+
 enum_bvh_types = (
     ('DYNAMIC_BVH', "Dynamic BVH", "Objects can be individually updated, at the cost of slower render time"),
     ('STATIC_BVH', "Static BVH", "Any object modification requires a complete BVH rebuild, but renders faster"),
@@ -670,7 +675,11 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
         cls.debug_use_cpu_sse41 = BoolProperty(name="SSE41", default=True)
         cls.debug_use_cpu_sse3 = BoolProperty(name="SSE3", default=True)
         cls.debug_use_cpu_sse2 = BoolProperty(name="SSE2", default=True)
-        cls.debug_use_qbvh = BoolProperty(name="QBVH", default=True)
+        cls.debug_bvh_layout = EnumProperty(
+                name="BVH Layout",
+                items=enum_bvh_layouts,
+                default='BVH4',
+                )
         cls.debug_use_cpu_split_kernel = BoolProperty(name="Split Kernel", default=False)
 
         cls.debug_use_cuda_adaptive_compile = BoolProperty(name="Adaptive Compile", default=False)
index 5d58ecc99ebfb2c49849ca54528499918db2a31f..543ba7c6d4dc753e5983fc0da3e90b0b45aa6ddf 100644 (file)
@@ -1609,7 +1609,7 @@ class CYCLES_RENDER_PT_debug(CyclesButtonsPanel, Panel):
         row.prop(cscene, "debug_use_cpu_sse41", toggle=True)
         row.prop(cscene, "debug_use_cpu_avx", toggle=True)
         row.prop(cscene, "debug_use_cpu_avx2", toggle=True)
-        col.prop(cscene, "debug_use_qbvh")
+        col.prop(cscene, "debug_bvh_layout")
         col.prop(cscene, "debug_use_cpu_split_kernel")
 
         col.separator()
index 687ddd9e7c3230b3b425577a1714d8cfce264012..792597cbad5a2e2738c094a9e2381f2c5783bba7 100644 (file)
@@ -69,7 +69,7 @@ bool debug_flags_sync_from_scene(BL::Scene b_scene)
        flags.cpu.sse41 = get_boolean(cscene, "debug_use_cpu_sse41");
        flags.cpu.sse3 = get_boolean(cscene, "debug_use_cpu_sse3");
        flags.cpu.sse2 = get_boolean(cscene, "debug_use_cpu_sse2");
-       flags.cpu.qbvh = get_boolean(cscene, "debug_use_qbvh");
+       flags.cpu.bvh_layout = (BVHLayout)get_enum(cscene, "debug_bvh_layout");
        flags.cpu.split_kernel = get_boolean(cscene, "debug_use_cpu_split_kernel");
        /* Synchronize CUDA flags. */
        flags.cuda.adaptive_compile = get_boolean(cscene, "debug_use_cuda_adaptive_compile");
index b7c6fbc9d29b462141d822e559559283811d2daf..283aa5600fd24d027f4c50eb767a4e41261398ee 100644 (file)
@@ -662,7 +662,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene& b_scene,
                params.texture_limit = 0;
        }
 
-       params.use_qbvh = DebugFlags().cpu.qbvh;
+       params.bvh_layout = DebugFlags().cpu.bvh_layout;
 
        return params;
 }
index 6531ca50d9a65ff11c98bca19052ca7cd4f1e2e3..5bfe9d4ed1a136d7c63a2a14d6ae626f4ab694ba 100644 (file)
 #include "bvh/bvh_node.h"
 
 #include "util/util_foreach.h"
+#include "util/util_logging.h"
 #include "util/util_progress.h"
 
 CCL_NAMESPACE_BEGIN
 
+/* BVH Parameters. */
+
+const char *bvh_layout_name(BVHLayout layout)
+{
+       switch(layout) {
+               case BVH_LAYOUT_BVH2: return "BVH2";
+               case BVH_LAYOUT_BVH4: return "BVH4";
+               case BVH_LAYOUT_NONE: return "NONE";
+               case BVH_LAYOUT_ALL:  return "ALL";
+       }
+       LOG(DFATAL) << "Unsupported BVH layout was passed.";
+       return "";
+}
+
+BVHLayout BVHParams::best_bvh_layout(BVHLayout requested_layout,
+                                     BVHLayoutMask supported_layouts)
+{
+       const BVHLayoutMask requested_layout_mask = (BVHLayoutMask)requested_layout;
+       /* Check whether requested layout is supported, if so -- no need to do
+        * any extra computation.
+        */
+       if(supported_layouts & requested_layout_mask) {
+               return requested_layout;
+       }
+       /* Some bit magic to get widest supported BVH layout. */
+       /* This is a mask of supported BVH layouts which are narrower than the
+        * requested one.
+        */
+       const BVHLayoutMask allowed_layouts_mask =
+               (supported_layouts & (requested_layout_mask - 1));
+       /* We get widest from allowed ones and convert mask to actual layout. */
+       const BVHLayoutMask widest_allowed_layout_mask = __bsr(allowed_layouts_mask);
+       return (BVHLayout)widest_allowed_layout_mask;
+}
+
 /* Pack Utility */
 
 BVHStackEntry::BVHStackEntry(const BVHNode *n, int i)
@@ -51,10 +87,17 @@ BVH::BVH(const BVHParams& params_, const vector<Object*>& objects_)
 
 BVH *BVH::create(const BVHParams& params, const vector<Object*>& objects)
 {
-       if(params.use_qbvh)
-               return new BVH4(params, objects);
-       else
-               return new BVH2(params, objects);
+       switch(params.bvh_layout) {
+               case BVH_LAYOUT_BVH2:
+                       return new BVH2(params, objects);
+               case BVH_LAYOUT_BVH4:
+                       return new BVH4(params, objects);
+               case BVH_LAYOUT_NONE:
+               case BVH_LAYOUT_ALL:
+                       break;
+       }
+       LOG(DFATAL) << "Requested unsupported BVH layout.";
+       return NULL;
 }
 
 /* Building */
@@ -248,7 +291,8 @@ void BVH::pack_instances(size_t nodes_size, size_t leaf_nodes_size)
         * BVH's are stored in global arrays. This function merges them into the
         * top level BVH, adjusting indexes and offsets where appropriate.
         */
-       const bool use_qbvh = params.use_qbvh;
+       /* TODO(sergey): This code needs adjustment for wider BVH than 4. */
+       const bool use_qbvh = (params.bvh_layout == BVH_LAYOUT_BVH4);
 
        /* Adjust primitive index to point to the triangle in the global array, for
         * meshes with transform applied and already in the top level BVH.
index b910feccec853cf4e30e6b07bd51e3cc00b39fad..4faf47af7bb5d2d8a800ecc9997ff798bbaafb19 100644 (file)
@@ -55,7 +55,7 @@ static bool node_qbvh_is_unaligned(const BVHNode *node)
 BVH4::BVH4(const BVHParams& params_, const vector<Object*>& objects_)
 : BVH(params_, objects_)
 {
-       params.use_qbvh = true;
+       params.bvh_layout = BVH_LAYOUT_BVH4;
 }
 
 void BVH4::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf)
index 7dd699b33a42b8c9e536729d18737449f2ac39b4..89a379cf3561a48fc690ff7046adf6cc722bb3d9 100644 (file)
 
 CCL_NAMESPACE_BEGIN
 
+/* Layout of BVH tree.
+ *
+ * For example, how wide BVH tree is, in terms of number of children
+ * per node.
+ */
+typedef KernelBVHLayout BVHLayout;
+
+/* Names bitflag type to denote which BVH layouts are supported by
+ * particular area.
+ *
+ * Bitflags are the BVH_LAYOUT_* values.
+ */
+typedef int BVHLayoutMask;
+
+/* Get human readable name of BVH layout. */
+const char *bvh_layout_name(BVHLayout layout);
+
 /* BVH Parameters */
 
 class BVHParams
 {
 public:
+
        /* spatial split area threshold */
        bool use_spatial_split;
        float spatial_split_alpha;
@@ -50,8 +68,8 @@ public:
        /* object or mesh level bvh */
        bool top_level;
 
-       /* QBVH */
-       bool use_qbvh;
+       /* BVH layout to be built. */
+       BVHLayout bvh_layout;
 
        /* Mask of primitives to be included into the BVH. */
        int primitive_mask;
@@ -98,7 +116,7 @@ public:
                max_motion_curve_leaf_size = 4;
 
                top_level = false;
-               use_qbvh = false;
+               bvh_layout = BVH_LAYOUT_BVH2;
                use_unaligned_nodes = false;
 
                primitive_mask = PRIMITIVE_ALL;
@@ -119,6 +137,14 @@ public:
 
        __forceinline bool small_enough_for_leaf(int size, int level)
        { return (size <= min_leaf_size || level >= MAX_DEPTH); }
+
+       /* Gets best matching BVH.
+        *
+        * If the requested layout is supported by the device, it will be used.
+        * Otherwise, widest supported layout below that will be used.
+        */
+       static BVHLayout best_bvh_layout(BVHLayout requested_layout,
+                                        BVHLayoutMask supported_layouts);
 };
 
 /* BVH Reference
index d55a999c454e2f187b2ccc3a42b96b4e8b75118f..1ec0bc3e1c6a0ca4cb91f73ea0a2c1dfd5ba7ae3 100644 (file)
@@ -362,7 +362,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int th
        info.has_fermi_limits = false;
        info.has_half_images = true;
        info.has_volume_decoupled = true;
-       info.has_qbvh = true;
+       info.bvh_layout_mask = BVH_LAYOUT_ALL;
        info.has_osl = true;
 
        foreach(const DeviceInfo &device, subdevices) {
@@ -399,7 +399,7 @@ DeviceInfo Device::get_multi_device(const vector<DeviceInfo>& subdevices, int th
                                        device.has_fermi_limits;
                info.has_half_images &= device.has_half_images;
                info.has_volume_decoupled &= device.has_volume_decoupled;
-               info.has_qbvh &= device.has_qbvh;
+               info.bvh_layout_mask = device.bvh_layout_mask & info.bvh_layout_mask;
                info.has_osl &= device.has_osl;
        }
 
index 528a6dc10f6c1ad2bd042a73dedc81c7e638eaac..99e80d104245d1ed5fb8687ed94674339afdd93d 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <stdlib.h>
 
+#include "bvh/bvh_params.h"
+
 #include "device/device_memory.h"
 #include "device/device_task.h"
 
@@ -52,14 +54,14 @@ public:
        string description;
        string id; /* used for user preferences, should stay fixed with changing hardware config */
        int num;
-       bool display_device;         /* GPU is used as a display device. */
-       bool advanced_shading;       /* Supports full shading system. */
-       bool has_fermi_limits;       /* Fixed number of textures limit. */
-       bool has_half_images;        /* Support half-float textures. */
-       bool has_volume_decoupled;   /* Decoupled volume shading. */
-       bool has_qbvh;               /* Supports both BVH2 and BVH4 raytracing. */
-       bool has_osl;                /* Support Open Shading Language. */
-       bool use_split_kernel;       /* Use split or mega kernel. */
+       bool display_device;            /* GPU is used as a display device. */
+       bool advanced_shading;          /* Supports full shading system. */
+       bool has_fermi_limits;          /* Fixed number of textures limit. */
+       bool has_half_images;           /* Support half-float textures. */
+       bool has_volume_decoupled;      /* Decoupled volume shading. */
+       BVHLayoutMask bvh_layout_mask;  /* Bitmask of supported BVH layouts. */
+       bool has_osl;                   /* Support Open Shading Language. */
+       bool use_split_kernel;          /* Use split or mega kernel. */
        int cpu_threads;
        vector<DeviceInfo> multi_devices;
 
@@ -74,7 +76,7 @@ public:
                has_fermi_limits = false;
                has_half_images = false;
                has_volume_decoupled = false;
-               has_qbvh = false;
+               bvh_layout_mask = BVH_LAYOUT_NONE;
                has_osl = false;
                use_split_kernel = false;
        }
index 6b6b3432446f046ada6e77ae69ee9cf6b7812299..fd55ec3687ae161171d4cec38260bff1fa8d1fff 100644 (file)
@@ -1046,7 +1046,10 @@ void device_cpu_info(vector<DeviceInfo>& devices)
        info.id = "CPU";
        info.num = 0;
        info.advanced_shading = true;
-       info.has_qbvh = system_cpu_support_sse2();
+       info.bvh_layout_mask = BVH_LAYOUT_BVH2;
+       if (system_cpu_support_sse2()) {
+               info.bvh_layout_mask |= BVH_LAYOUT_BVH4;
+       }
        info.has_volume_decoupled = true;
        info.has_osl = true;
        info.has_half_images = true;
index 116f4e2a452e421526b9d454e07b3d15387d9ad5..f3548640679482578ae9d8c8c84f0aa9e5eff1c3 100644 (file)
@@ -2551,7 +2551,7 @@ void device_cuda_info(vector<DeviceInfo>& devices)
                info.has_fermi_limits = !(major >= 3);
                info.has_half_images = (major >= 3);
                info.has_volume_decoupled = false;
-               info.has_qbvh = false;
+               info.bvh_layout_mask = BVH_LAYOUT_BVH2;
 
                int pci_location[3] = {0, 0, 0};
                cuDeviceGetAttribute(&pci_location[0], CU_DEVICE_ATTRIBUTE_PCI_DOMAIN_ID, num);
index 536d5ee08c08d994475673ac5ae018fcde8a1558..5ad4405366ee75ef25df1379b8b44b2034c8c9c5 100644 (file)
@@ -306,7 +306,7 @@ void device_network_info(vector<DeviceInfo>& devices)
        /* todo: get this info from device */
        info.advanced_shading = true;
        info.has_volume_decoupled = false;
-       info.has_qbvh = false;
+       info.bvh_layout_mask = BVH_LAYOUT_BVH2;
        info.has_osl = false;
 
        devices.push_back(info);
index d3eebb1002802d34d120161d66bcc0469784ccce..9d61bbdae5db2abcc70c822765f469682b409dcc 100644 (file)
@@ -135,7 +135,7 @@ void device_opencl_info(vector<DeviceInfo>& devices)
                info.use_split_kernel = OpenCLInfo::kernel_use_split(platform_name,
                                                                     device_type);
                info.has_volume_decoupled = false;
-               info.has_qbvh = false;
+               info.bvh_layout_mask = BVH_LAYOUT_BVH2;
                info.id = id;
                devices.push_back(info);
                num_devices++;
index 12d14428d6df06b3c134143d3159c5ce9a9965c6..9292cc76a5cc81030e73d04cdf3ba6344bd2f265 100644 (file)
@@ -243,26 +243,25 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
                                          uint *lcg_state,
                                          int max_hits)
 {
+       switch(kernel_data.bvh.bvh_layout) {
 #ifdef __QBVH__
-       if(kernel_data.bvh.use_qbvh) {
-               return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
-                                                   ray,
-                                                   local_isect,
-                                                   local_object,
-                                                   lcg_state,
-                                                   max_hits);
-       }
-       else
+               case BVH_LAYOUT_BVH4:
+                       return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+                                                           ray,
+                                                           local_isect,
+                                                           local_object,
+                                                           lcg_state,
+                                                           max_hits);
 #endif
-       {
-               kernel_assert(kernel_data.bvh.use_qbvh == false);
-               return BVH_FUNCTION_FULL_NAME(BVH)(kg,
-                                                  ray,
-                                                  local_isect,
-                                                  local_object,
-                                                  lcg_state,
-                                                  max_hits);
+               case BVH_LAYOUT_BVH2:
+                       return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+                                                          ray,
+                                                          local_isect,
+                                                          local_object,
+                                                          lcg_state,
+                                                          max_hits);
        }
+       kernel_assert(!"Should not happen");
 }
 
 #undef BVH_FUNCTION_NAME
index a6a4353562cacc61b8fb71ba4ae7f2730575b02c..efd6798ca5180d27a6bca3c977ae8db763e93a9d 100644 (file)
@@ -395,26 +395,26 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
                                          const uint max_hits,
                                          uint *num_hits)
 {
+       switch(kernel_data.bvh.bvh_layout) {
 #ifdef __QBVH__
-       if(kernel_data.bvh.use_qbvh) {
-               return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
-                                                   ray,
-                                                   isect_array,
-                                                   visibility,
-                                                   max_hits,
-                                                   num_hits);
-       }
-       else
+               case BVH_LAYOUT_BVH4:
+                       return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+                                                           ray,
+                                                           isect_array,
+                                                           visibility,
+                                                           max_hits,
+                                                           num_hits);
 #endif
-       {
-               kernel_assert(kernel_data.bvh.use_qbvh == false);
-               return BVH_FUNCTION_FULL_NAME(BVH)(kg,
-                                                  ray,
-                                                  isect_array,
-                                                  visibility,
-                                                  max_hits,
-                                                  num_hits);
+               case BVH_LAYOUT_BVH2:
+                       return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+                                                          ray,
+                                                          isect_array,
+                                                          visibility,
+                                                          max_hits,
+                                                          num_hits);
        }
+       kernel_assert(!"Should not happen");
+       return false;
 }
 
 #undef BVH_FUNCTION_NAME
index ae8f54821f225c055bc5db2926fc01a98e30450d..551625eae7841137dc8578250939e2c2c9d02bf5 100644 (file)
@@ -426,34 +426,34 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
 #endif
                                          )
 {
+       switch(kernel_data.bvh.bvh_layout) {
 #ifdef __QBVH__
-       if(kernel_data.bvh.use_qbvh) {
-               return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
-                                                   ray,
-                                                   isect,
-                                                   visibility
-#if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
-                                                   , lcg_state,
-                                                   difl,
-                                                   extmax
-#endif
-                                                   );
-       }
-       else
-#endif
-       {
-               kernel_assert(kernel_data.bvh.use_qbvh == false);
-               return BVH_FUNCTION_FULL_NAME(BVH)(kg,
-                                                  ray,
-                                                  isect,
-                                                  visibility
+               case BVH_LAYOUT_BVH4:
+                       return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+                                                           ray,
+                                                           isect,
+                                                           visibility
+#  if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
+                                                           , lcg_state,
+                                                           difl,
+                                                           extmax
+#  endif
+                                                           );
+#endif  /* __QBVH__ */
+               case BVH_LAYOUT_BVH2:
+                       return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+                                                          ray,
+                                                          isect,
+                                                          visibility
 #if BVH_FEATURE(BVH_HAIR_MINIMUM_WIDTH)
-                                                  , lcg_state,
-                                                  difl,
-                                                  extmax
+                                                          , lcg_state,
+                                                          difl,
+                                                          extmax
 #endif
-                                                  );
+                                                          );
        }
+       kernel_assert(!"Should not happen");
+       return false;
 }
 
 #undef BVH_FUNCTION_NAME
index 764aaee44a1b4c1178772190788b8125f235326e..ce5fc7be33d217d5274a5a577e5a3a4c15d1e142 100644 (file)
@@ -309,22 +309,22 @@ ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
                                          Intersection *isect,
                                          const uint visibility)
 {
+       switch(kernel_data.bvh.bvh_layout) {
 #ifdef __QBVH__
-       if(kernel_data.bvh.use_qbvh) {
-               return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
-                                                   ray,
-                                                   isect,
-                                                   visibility);
-       }
-       else
+               case BVH_LAYOUT_BVH4:
+                       return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+                                                           ray,
+                                                           isect,
+                                                           visibility);
 #endif
-       {
-               kernel_assert(kernel_data.bvh.use_qbvh == false);
-               return BVH_FUNCTION_FULL_NAME(BVH)(kg,
-                                                  ray,
-                                                  isect,
-                                                  visibility);
+               case BVH_LAYOUT_BVH2:
+                       return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+                                                          ray,
+                                                          isect,
+                                                          visibility);
        }
+       kernel_assert(!"Should not happen");
+       return false;
 }
 
 #undef BVH_FUNCTION_NAME
index 04ec334e54d41f3e82521ed757ba3531fb431435..f2379efc656034cd5acfb30668688c2cf7e1bba5 100644 (file)
@@ -381,24 +381,24 @@ ccl_device_inline uint BVH_FUNCTION_NAME(KernelGlobals *kg,
                                          const uint max_hits,
                                          const uint visibility)
 {
+       switch(kernel_data.bvh.bvh_layout) {
 #ifdef __QBVH__
-       if(kernel_data.bvh.use_qbvh) {
-               return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
-                                                   ray,
-                                                   isect_array,
-                                                   max_hits,
-                                                   visibility);
-       }
-       else
+               case BVH_LAYOUT_BVH4:
+                       return BVH_FUNCTION_FULL_NAME(QBVH)(kg,
+                                                           ray,
+                                                           isect_array,
+                                                           max_hits,
+                                                           visibility);
 #endif
-       {
-               kernel_assert(kernel_data.bvh.use_qbvh == false);
-               return BVH_FUNCTION_FULL_NAME(BVH)(kg,
-                                                  ray,
-                                                  isect_array,
-                                                  max_hits,
-                                                  visibility);
+               case BVH_LAYOUT_BVH2:
+                       return BVH_FUNCTION_FULL_NAME(BVH)(kg,
+                                                          ray,
+                                                          isect_array,
+                                                          max_hits,
+                                                          visibility);
        }
+       kernel_assert(!"Should not happen");
+       return 0;
 }
 
 #undef BVH_FUNCTION_NAME
index 4f6557840447c7b5882232c5ccb1bf8ccb122322..1e1a4f34650c046202d3401b4705232505654ec1 100644 (file)
@@ -1344,13 +1344,23 @@ typedef struct KernelIntegrator {
 } KernelIntegrator;
 static_assert_align(KernelIntegrator, 16);
 
+typedef enum KernelBVHLayout {
+       BVH_LAYOUT_NONE = 0,
+
+       BVH_LAYOUT_BVH2 = (1 << 0),
+       BVH_LAYOUT_BVH4 = (1 << 1),
+
+       BVH_LAYOUT_DEFAULT = BVH_LAYOUT_BVH4,
+       BVH_LAYOUT_ALL = (unsigned int)(-1),
+} KernelBVHLayout;
+
 typedef struct KernelBVH {
        /* root node */
        int root;
        int have_motion;
        int have_curves;
        int have_instancing;
-       int use_qbvh;
+       int bvh_layout;
        int use_bvh_steps;
        int pad1, pad2;
 } KernelBVH;
index 5d5a416e2937a4b6a78089acb8085f85bc1b73f2..4bf5b60a73766e01d7faefe6dd1d68745e9751fd 100644 (file)
@@ -1058,7 +1058,9 @@ void Mesh::compute_bvh(Device *device,
 
                        BVHParams bparams;
                        bparams.use_spatial_split = params->use_bvh_spatial_split;
-                       bparams.use_qbvh = params->use_qbvh && device->info.has_qbvh;
+                       bparams.bvh_layout = BVHParams::best_bvh_layout(
+                               params->bvh_layout,
+                               device->info.bvh_layout_mask);
                        bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
                                                      params->use_bvh_unaligned_nodes;
                        bparams.num_motion_triangle_steps = params->num_bvh_time_steps;
@@ -1817,15 +1819,17 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
 
        BVHParams bparams;
        bparams.top_level = true;
-       bparams.use_qbvh = scene->params.use_qbvh && device->info.has_qbvh;
+       bparams.bvh_layout = BVHParams::best_bvh_layout(
+               scene->params.bvh_layout,
+               device->info.bvh_layout_mask);
        bparams.use_spatial_split = scene->params.use_bvh_spatial_split;
        bparams.use_unaligned_nodes = dscene->data.bvh.have_curves &&
                                      scene->params.use_bvh_unaligned_nodes;
        bparams.num_motion_triangle_steps = scene->params.num_bvh_time_steps;
        bparams.num_motion_curve_steps = scene->params.num_bvh_time_steps;
 
-       VLOG(1) << (bparams.use_qbvh ? "Using QBVH optimization structure"
-                                    : "Using regular BVH optimization structure");
+       VLOG(1) << "Using " << bvh_layout_name(bparams.bvh_layout)
+               << " layout.";
 
        BVH *bvh = BVH::create(bparams, scene->objects);
        bvh->build(progress);
@@ -1882,7 +1886,7 @@ void MeshManager::device_update_bvh(Device *device, DeviceScene *dscene, Scene *
        }
 
        dscene->data.bvh.root = pack.root_index;
-       dscene->data.bvh.use_qbvh = bparams.use_qbvh;
+       dscene->data.bvh.bvh_layout = bparams.bvh_layout;
        dscene->data.bvh.use_bvh_steps = (scene->params.num_bvh_time_steps != 0);
 
        delete bvh;
index 5f717e93b43b879ceab8351dffea06d49e45c455..ea9485ff23064fd73660378117f654d2be98d5e7 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef __SCENE_H__
 #define __SCENE_H__
 
+#include "bvh/bvh_params.h"
+
 #include "render/image.h"
 #include "render/shader.h"
 
@@ -122,39 +124,63 @@ public:
 
 class SceneParams {
 public:
-       ShadingSystem shadingsystem;
+       /* Type of BVH, in terms whether it is supported dynamic updates of meshes
+        * or whether modifying geometry requires full BVH rebuild.
+        */
        enum BVHType {
+               /* BVH supports dynamic updates of geometry.
+                *
+                * Faster for updating BVH tree when doing modifications in viewport,
+                * but slower for rendering.
+                */
                BVH_DYNAMIC = 0,
+               /* BVH tree is calculated for specific scene, updates in geometry
+                * requires full tree rebuild.
+                *
+                * Slower to update BVH tree when modifying objects in viewport, also
+                * slower to build final BVH tree but gives best possible render speed.
+                */
                BVH_STATIC = 1,
 
                BVH_NUM_TYPES,
-       } bvh_type;
+       };
+
+       ShadingSystem shadingsystem;
+
+       /* Requested BVH layout.
+        *
+        * If it's not supported by the device, the widest one from supported ones
+        * will be used, but BVH wider than this one will never be used.
+        */
+       BVHLayout bvh_layout;
+
+       BVHType bvh_type;
        bool use_bvh_spatial_split;
        bool use_bvh_unaligned_nodes;
        int num_bvh_time_steps;
-       bool use_qbvh;
+
        bool persistent_data;
        int texture_limit;
 
        SceneParams()
        {
                shadingsystem = SHADINGSYSTEM_SVM;
+               bvh_layout = BVH_LAYOUT_BVH2;
                bvh_type = BVH_DYNAMIC;
                use_bvh_spatial_split = false;
                use_bvh_unaligned_nodes = true;
                num_bvh_time_steps = 0;
-               use_qbvh = true;
                persistent_data = false;
                texture_limit = 0;
        }
 
        bool modified(const SceneParams& params)
        { return !(shadingsystem == params.shadingsystem
+               && bvh_layout == params.bvh_layout
                && bvh_type == params.bvh_type
                && use_bvh_spatial_split == params.use_bvh_spatial_split
                && use_bvh_unaligned_nodes == params.use_bvh_unaligned_nodes
                && num_bvh_time_steps == params.num_bvh_time_steps
-               && use_qbvh == params.use_qbvh
                && persistent_data == params.persistent_data
                && texture_limit == params.texture_limit); }
 };
index eb078d692523706366cc402d176d95578826844d..9a66a3728220271b95dce485b5dfe44b91c4c9a1 100644 (file)
@@ -18,6 +18,8 @@
 
 #include <stdlib.h>
 
+#include "bvh/bvh_params.h"
+
 #include "util/util_logging.h"
 #include "util/util_string.h"
 
@@ -29,7 +31,7 @@ DebugFlags::CPU::CPU()
     sse41(true),
     sse3(true),
     sse2(true),
-    qbvh(true),
+    bvh_layout(BVH_LAYOUT_DEFAULT),
     split_kernel(false)
 {
        reset();
@@ -55,7 +57,7 @@ void DebugFlags::CPU::reset()
 #undef STRINGIFY
 #undef CHECK_CPU_FLAGS
 
-       qbvh = true;
+       bvh_layout = BVH_LAYOUT_DEFAULT;
        split_kernel = false;
 }
 
@@ -139,13 +141,13 @@ std::ostream& operator <<(std::ostream &os,
                           DebugFlagsConstRef debug_flags)
 {
        os << "CPU flags:\n"
-          << "  AVX2   : " << string_from_bool(debug_flags.cpu.avx2)  << "\n"
-          << "  AVX    : " << string_from_bool(debug_flags.cpu.avx)   << "\n"
-          << "  SSE4.1 : " << string_from_bool(debug_flags.cpu.sse41) << "\n"
-          << "  SSE3   : " << string_from_bool(debug_flags.cpu.sse3)  << "\n"
-          << "  SSE2   : " << string_from_bool(debug_flags.cpu.sse2)  << "\n"
-          << "  QBVH   : " << string_from_bool(debug_flags.cpu.qbvh)  << "\n"
-          << "  Split  : " << string_from_bool(debug_flags.cpu.split_kernel) << "\n";
+          << "  AVX2       : " << string_from_bool(debug_flags.cpu.avx2) << "\n"
+          << "  AVX        : " << string_from_bool(debug_flags.cpu.avx) << "\n"
+          << "  SSE4.1     : " << string_from_bool(debug_flags.cpu.sse41) << "\n"
+          << "  SSE3       : " << string_from_bool(debug_flags.cpu.sse3) << "\n"
+          << "  SSE2       : " << string_from_bool(debug_flags.cpu.sse2) << "\n"
+          << "  BVH layout : " << bvh_layout_name(debug_flags.cpu.bvh_layout) << "\n"
+          << "  Split      : " << string_from_bool(debug_flags.cpu.split_kernel) << "\n";
 
        os << "CUDA flags:\n"
           << " Adaptive Compile: " << string_from_bool(debug_flags.cuda.adaptive_compile) << "\n";
index ec38cd373ba932042e26d74636d959452ef3c8f9..f17f8a560ee41dc736efa43cdd8677aa2ac8bc24 100644 (file)
@@ -20,6 +20,8 @@
 #include <cassert>
 #include <iostream>
 
+#include "bvh/bvh_params.h"
+
 CCL_NAMESPACE_BEGIN
 
 /* Global storage for all sort of flags used to fine-tune behavior of particular
@@ -54,8 +56,12 @@ public:
                bool has_sse3()  { return has_sse2()  && sse3; }
                bool has_sse2()  { return sse2; }
 
-               /* Whether QBVH usage is allowed or not. */
-               bool qbvh;
+               /* Requested BVH size.
+                *
+                * Rendering will use widest possible BVH which is below or equal
+                * this one.
+                */
+               BVHLayout bvh_layout;
 
                /* Whether split kernel is used */
                bool split_kernel;