Page MenuHome

Cycles: Add half precision float support to NanoVDB
ClosedPublic

Authored by Patrick Mours (pmoursnv) on Jan 6 2021, 8:15 PM.

Details

Summary

This patch makes it possible to change the precision with which to store volume data in the NanoVDB data structure (float, half, or variable bit quantization) using a new render option called "Precision" in the Cycles "Volumes" properties panel. It allows a reduction in memory usage, with a slight cost to the visual detail of the volume.

Diff Detail

Repository
rB Blender
Branch
cycles_nanovdb_half4 (branched from master)
Build Status
Buildable 22197
Build 22197: arc lint + arc unit

Event Timeline

Patrick Mours (pmoursnv) requested review of this revision.Jan 6 2021, 8:15 PM
Patrick Mours (pmoursnv) created this revision.

I guess ideally this can be contributed upstream? I imagine this would also benefit other renderers using NanoVDB.

The rest of the implementation looks straightforward,

Yeah, it's on the upstream's TODO list. Probably would be nicer to wait for that to happen instead of doing it with a patch, so I'll put some pressure on it.

Reworked to use the new quantization data types in NanoVDB (nanovdb::Fp16, nanovdb::FpN), now that NanoVDB was updated.

Brecht Van Lommel (brecht) requested changes to this revision.May 18 2022, 6:43 PM

Can we make half precision a setting on the Volume datablock? Having to switch it for the entire scene for just one volume requiring additional precision is not ideal.

I think we can also enable this by default? Not sure if F16 or FPN would be best.

This revision now requires changes to proceed.May 18 2022, 6:43 PM

There are some build errors with Clang (P2958) and GCC (P2957).

Can we make half precision a setting on the Volume datablock? Having to switch it for the entire scene for just one volume requiring additional precision is not ideal.

I wasn't entirely sure how, since there are no other Cycles settings in Volume and VolumeRender data blocks currently, other volume related settings are either in the material (e.g. material.cycles.volume_step_rate) or global render settings (e.g. scene.cycles.volume_step_rate). So not sure if it makes more sense to add to Volume/VolumeRender data block add add a new UI panel, or add it to the material and leverage the existing panel.

I think we can also enable this by default? Not sure if F16 or FPN would be best.

If the default should not be full float, then probably FPN, since it does automatically decide between 1-,2-,4-,8- or 16-bit quantization, per leaf, based on some heuristic on the values there. So is a good trade-off between all FP1 and all FP16.

I wasn't entirely sure how, since there are no other Cycles settings in Volume and VolumeRender data blocks currently, other volume related settings are either in the material (e.g. material.cycles.volume_step_rate) or global render settings (e.g. scene.cycles.volume_step_rate). So not sure if it makes more sense to add to Volume/VolumeRender data block add add a new UI panel, or add it to the material and leverage the existing panel.

I think the required precision mostly depends on the VDB file, not so much the material using it. The new property can be a native Blender property, that we only use for Cycles now but use for Eevee/Viewport later. It can go into the existing render panel, along with settings like step size and clipping.

If the default should not be full float, then probably FPN, since it does automatically decide between 1-,2-,4-,8- or 16-bit quantization, per leaf, based on some heuristic on the values there. So is a good trade-off between all FP1 and all FP16.

Makes sense.

Moved precision property into volume render data block.

Turns out there already existed a precision field in the VolumeRender DNA data block, but it was unused (and looking through Git history apparently was never used). So just gave that meaning now and added it to RNA as well.

Fixed build failure with Clang/GCC

Since VolumeRender.precision already existed, existing files will have that set to zero (as it was never set to something else). I therefore defined VOLUME_PRECISION_VARIABLE as zero, so that the default for all files is to use variable bit quantization now. This could be changed to VOLUME_PRECISION_FULL being zero instead, so that existing files will use full precision like before and only new files will use variable bit quantization (because _DNA_DEFAULT_VolumeRender sets it to VOLUME_PRECISION_VARIABLE now).

Brecht Van Lommel (brecht) requested changes to this revision.May 20 2022, 5:35 PM

The openvdb_smoke regression test is failing with some differences, and when you render that at higher resolution you can see some pretty noticeable gaps in the volume.

Setting the precision to Half on the other hand looks identical and passes the tests, so I think we can make that the default instead? I guess variable precision could also cause problems in animation.

I needed to add typename to fix a build error with CUDA 11.4 on Linux:

diff --git a/intern/cycles/kernel/device/gpu/image.h b/intern/cycles/kernel/device/gpu/image.h
index 574bc8a..29d851a 100644
--- a/intern/cycles/kernel/device/gpu/image.h
+++ b/intern/cycles/kernel/device/gpu/image.h
@@ -125,10 +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 nanovdb::NanoGrid<T>::ValueType 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);
@@ -160,7 +158,7 @@ ccl_device nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_tricubic_nano
 }
 
 template<typename T>
-ccl_device_noinline nanovdb::NanoGrid<T>::ValueType 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;
This revision now requires changes to proceed.May 20 2022, 5:35 PM

Sounds good, changed default volume precision to half and added the missing typenames.
Has the added benefit that there is now a nice correlation in the enum values between VDB_PRECISION_HALF/FULL/MINI_FLOAT from the fluid data block and VOLUME_PRECISION_HALF/FULL/VARIABLE.

This revision is now accepted and ready to land.May 23 2022, 4:56 PM