[Bf-blender-cvs] [a8c81ffa831] master: Cycles: Add half precision float support for volumes with NanoVDB

Patrick Mours noreply at git.blender.org
Mon May 23 19:08:56 CEST 2022


Commit: a8c81ffa83122661b80e842ddd641e366b3d5c04
Author: Patrick Mours
Date:   Fri May 20 18:01:26 2022 +0200
Branches: master
https://developer.blender.org/rBa8c81ffa83122661b80e842ddd641e366b3d5c04

Cycles: Add half precision float support for volumes with NanoVDB

This patch makes it possible to change the precision with which to
store volume data in the NanoVDB data structure (as float, half, or
using variable bit quantization) via the previously unused precision
field in the volume data block.
It makes it possible to further reduce memory usage during
rendering, at a slight cost to the visual detail of a volume.

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

===================================================================

M	intern/cycles/blender/volume.cpp
M	intern/cycles/device/cuda/device_impl.cpp
M	intern/cycles/device/hip/device_impl.cpp
M	intern/cycles/device/memory.cpp
M	intern/cycles/kernel/device/cpu/image.h
M	intern/cycles/kernel/device/gpu/image.h
M	intern/cycles/scene/image.cpp
M	intern/cycles/scene/image_oiio.cpp
M	intern/cycles/scene/image_vdb.cpp
M	intern/cycles/scene/image_vdb.h
M	intern/cycles/scene/object.cpp
M	intern/cycles/util/texture.h
M	release/scripts/startup/bl_ui/properties_data_volume.py
M	source/blender/makesdna/DNA_volume_defaults.h
M	source/blender/makesdna/DNA_volume_types.h
M	source/blender/makesrna/intern/rna_volume.c

===================================================================

diff --git a/intern/cycles/blender/volume.cpp b/intern/cycles/blender/volume.cpp
index 8dd2d45c0b6..a9a2c474f40 100644
--- a/intern/cycles/blender/volume.cpp
+++ b/intern/cycles/blender/volume.cpp
@@ -219,7 +219,10 @@ static void sync_smoke_volume(
 
 class BlenderVolumeLoader : public VDBImageLoader {
  public:
-  BlenderVolumeLoader(BL::BlendData &b_data, BL::Volume &b_volume, const string &grid_name)
+  BlenderVolumeLoader(BL::BlendData &b_data,
+                      BL::Volume &b_volume,
+                      const string &grid_name,
+                      BL::VolumeRender::precision_enum precision_)
       : VDBImageLoader(grid_name), b_volume(b_volume)
   {
     b_volume.grids.load(b_data.ptr.data);
@@ -240,6 +243,20 @@ class BlenderVolumeLoader : public VDBImageLoader {
         break;
       }
     }
+#endif
+#ifdef WITH_NANOVDB
+    switch (precision_) {
+      case BL::VolumeRender::precision_FULL:
+        precision = 32;
+        break;
+      case BL::VolumeRender::precision_HALF:
+        precision = 16;
+        break;
+      default:
+      case BL::VolumeRender::precision_VARIABLE:
+        precision = 0;
+        break;
+    }
 #endif
   }
 
@@ -318,7 +335,8 @@ static void sync_volume_object(BL::BlendData &b_data,
                             volume->attributes.add(std) :
                             volume->attributes.add(name, TypeDesc::TypeFloat, ATTR_ELEMENT_VOXEL);
 
-      ImageLoader *loader = new BlenderVolumeLoader(b_data, b_volume, name.string());
+      ImageLoader *loader = new BlenderVolumeLoader(
+          b_data, b_volume, name.string(), b_render.precision());
       ImageParams params;
       params.frame = b_volume.grids.frame();
 
diff --git a/intern/cycles/device/cuda/device_impl.cpp b/intern/cycles/device/cuda/device_impl.cpp
index 6908ae5ead3..75177566901 100644
--- a/intern/cycles/device/cuda/device_impl.cpp
+++ b/intern/cycles/device/cuda/device_impl.cpp
@@ -1084,7 +1084,9 @@ void CUDADevice::tex_alloc(device_texture &mem)
   need_texture_info = true;
 
   if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
-      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
+      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3 &&
+      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FPN &&
+      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FP16) {
     CUDA_RESOURCE_DESC resDesc;
     memset(&resDesc, 0, sizeof(resDesc));
 
diff --git a/intern/cycles/device/hip/device_impl.cpp b/intern/cycles/device/hip/device_impl.cpp
index 7159277b325..f8fdb86ca29 100644
--- a/intern/cycles/device/hip/device_impl.cpp
+++ b/intern/cycles/device/hip/device_impl.cpp
@@ -1042,7 +1042,9 @@ void HIPDevice::tex_alloc(device_texture &mem)
   need_texture_info = true;
 
   if (mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT &&
-      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
+      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3 &&
+      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FPN &&
+      mem.info.data_type != IMAGE_DATA_TYPE_NANOVDB_FP16) {
     /* Bindless textures. */
     hipResourceDesc resDesc;
     memset(&resDesc, 0, sizeof(resDesc));
diff --git a/intern/cycles/device/memory.cpp b/intern/cycles/device/memory.cpp
index 4c068dbdd3e..40cf2573cfb 100644
--- a/intern/cycles/device/memory.cpp
+++ b/intern/cycles/device/memory.cpp
@@ -165,6 +165,8 @@ device_texture::device_texture(Device *device,
     case IMAGE_DATA_TYPE_BYTE:
     case IMAGE_DATA_TYPE_NANOVDB_FLOAT:
     case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
+    case IMAGE_DATA_TYPE_NANOVDB_FPN:
+    case IMAGE_DATA_TYPE_NANOVDB_FP16:
       data_type = TYPE_UCHAR;
       data_elements = 1;
       break;
diff --git a/intern/cycles/kernel/device/cpu/image.h b/intern/cycles/kernel/device/cpu/image.h
index 3b714a3e580..4963a732916 100644
--- a/intern/cycles/kernel/device/cpu/image.h
+++ b/intern/cycles/kernel/device/cpu/image.h
@@ -817,6 +817,14 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
     }
     case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
       return NanoVDBInterpolator<nanovdb::Vec3f>::interp_3d(info, P.x, P.y, P.z, interp);
+    case IMAGE_DATA_TYPE_NANOVDB_FPN: {
+      const float f = NanoVDBInterpolator<nanovdb::FpN, float>::interp_3d(info, P.x, P.y, P.z, interp);
+      return make_float4(f, f, f, 1.0f);
+    }
+    case IMAGE_DATA_TYPE_NANOVDB_FP16: {
+      const float f = NanoVDBInterpolator<nanovdb::Fp16, float>::interp_3d(info, P.x, P.y, P.z, interp);
+      return make_float4(f, f, f, 1.0f);
+    }
 #endif
     default:
       assert(0);
diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h
index c5bc7d88e02..29d851ae478 100644
--- a/intern/cycles/kernel/device/gpu/image.h
+++ b/intern/cycles/kernel/device/gpu/image.h
@@ -125,7 +125,8 @@ kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, fl
 
 #ifdef WITH_NANOVDB
 template<typename T, typename S>
-ccl_device T kernel_tex_image_interp_tricubic_nanovdb(S &s, float x, float y, float z)
+ccl_device typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_tricubic_nanovdb(
+    S &s, float x, float y, float z)
 {
   float px = floorf(x);
   float py = floorf(y);
@@ -157,7 +158,7 @@ ccl_device T kernel_tex_image_interp_tricubic_nanovdb(S &s, float x, float y, fl
 }
 
 template<typename T>
-ccl_device_noinline T kernel_tex_image_interp_nanovdb(
+ccl_device_noinline typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_nanovdb(
     ccl_global const TextureInfo &info, float x, float y, float z, uint interpolation)
 {
   using namespace nanovdb;
@@ -238,6 +239,14 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
         info, x, y, z, interpolation);
     return make_float4(f[0], f[1], f[2], 1.0f);
   }
+  if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FPN) {
+    float f = kernel_tex_image_interp_nanovdb<nanovdb::FpN>(info, x, y, z, interpolation);
+    return make_float4(f, f, f, 1.0f);
+  }
+  if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FP16) {
+    float f = kernel_tex_image_interp_nanovdb<nanovdb::Fp16>(info, x, y, z, interpolation);
+    return make_float4(f, f, f, 1.0f);
+  }
 #endif
   if (texture_type == IMAGE_DATA_TYPE_FLOAT4 || texture_type == IMAGE_DATA_TYPE_BYTE4 ||
       texture_type == IMAGE_DATA_TYPE_HALF4 || texture_type == IMAGE_DATA_TYPE_USHORT4) {
diff --git a/intern/cycles/scene/image.cpp b/intern/cycles/scene/image.cpp
index c61ad1f1d71..2aa9a6bc1a1 100644
--- a/intern/cycles/scene/image.cpp
+++ b/intern/cycles/scene/image.cpp
@@ -64,6 +64,10 @@ const char *name_from_type(ImageDataType type)
       return "nanovdb_float";
     case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
       return "nanovdb_float3";
+    case IMAGE_DATA_TYPE_NANOVDB_FPN:
+      return "nanovdb_fpn";
+    case IMAGE_DATA_TYPE_NANOVDB_FP16:
+      return "nanovdb_fp16";
     case IMAGE_DATA_NUM_TYPES:
       assert(!"System enumerator type, should never be used");
       return "";
@@ -378,7 +382,9 @@ void ImageManager::load_image_metadata(Image *img)
   metadata.detect_colorspace();
 
   assert(features.has_nanovdb || (metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
-                                  metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3));
+                                  metadata.type != IMAGE_DATA_TYPE_NANOVDB_FLOAT3 ||
+                                  metadata.type != IMAGE_DATA_TYPE_NANOVDB_FPN ||
+                                  metadata.type != IMAGE_DATA_TYPE_NANOVDB_FP16));
 
   img->need_metadata = false;
 }
@@ -796,7 +802,8 @@ void ImageManager::device_load_image(Device *device, Scene *scene, int slot, Pro
     }
   }
 #ifdef WITH_NANOVDB
-  else if (type == IMAGE_DATA_TYPE_NANOVDB_FLOAT || type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
+  else if (type == IMAGE_DATA_TYPE_NANOVDB_FLOAT || type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3 ||
+           type == IMAGE_DATA_TYPE_NANOVDB_FPN || type == IMAGE_DATA_TYPE_NANOVDB_FP16) {
     thread_scoped_lock device_lock(device_mutex);
     void *pixels = img->mem->alloc(img->metadata.byte_size, 0);
 
diff --git a/intern/cycles/scene/image_oiio.cpp b/intern/cycles/scene/image_oiio.cpp
index 3f825afbe90..1b7f8f49696 100644
--- a/intern/cycles/scene/image_oiio.cpp
+++ b/intern/cycles/scene/image_oiio.cpp
@@ -199,6 +199,8 @@ bool OIIOImageLoader::load_pixels(const ImageMetaData &metadata,
       break;
     case IMAGE_DATA_TYPE_NANOVDB_FLOAT:
     case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
+    case IMAGE_DATA_TYPE_NANOVDB_FPN:
+    case IMAGE_DATA_TYPE_NANOVDB_FP16:
     case IMAGE_DATA_NUM_TYPES:
       break;
   }
diff --git a/intern/cycles/scene/image_vdb.cpp b/intern/cycles/scene/image_vdb.cpp
index b6f0911fa2c..d0b41a239df 100644
--- a/intern/cycles/scene/image_vdb.cpp
+++ b/intern/cycles/scene/image_vdb.cpp
@@ -44,14 +44,30 @@ struct ToDenseOp {
 #  ifdef WITH_NANOVDB
 struct ToNanoOp {
   nanovdb::GridHandle<> nanogrid;
+  int precision;
 
   template<typename GridType, typename FloatGridType, typename FloatDataType, int channels>
   bool operator()(const openvdb::GridBase::ConstPtr &grid)
   {
     if constexpr (!std::is_same_v<GridType, openvdb::MaskGrid>) {
       try {
-        nanogrid = nanovdb::openToNanoVDB(
-            FloatGridType(*openvdb::gridConstPtrCast<GridType>(grid)));
+        FloatGridType floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
+        if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
+          if (precision == 0) {
+            nanogrid = nanovdb::openToNanoVDB<nanovdb::HostBuffer,
+                                              typename FloatGridType::TreeType,
+                                              nanovdb::FpN>(floatgrid);
+            return true;
+          }
+          else if (precision == 16) {
+            nanogrid = nanovdb::openToNanoVDB<nanovdb::HostBuffer,
+                                              typename FloatGridType::TreeType,
+                                              nanovdb::Fp16>(floatgrid);
+            return true;
+          }
+        }
+
+        nanogrid = nanovdb::openToNanoVDB(floatgrid);
       }
       catch (const std::exception &e) {
         VLOG(1) << "Error converting OpenVDB to NanoVDB grid: " << e.what();
@@ -102

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list