diff options
author | Patrick Mours <pmours@nvidia.com> | 2022-05-20 19:01:26 +0300 |
---|---|---|
committer | Patrick Mours <pmours@nvidia.com> | 2022-05-23 20:08:01 +0300 |
commit | a8c81ffa83122661b80e842ddd641e366b3d5c04 (patch) | |
tree | a366980386a9369edd4fda51d9d566fdf2d8743c /intern/cycles | |
parent | 14a5a91e0e033d712134c112a4778b495bd73ba1 (diff) |
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
Diffstat (limited to 'intern/cycles')
-rw-r--r-- | intern/cycles/blender/volume.cpp | 22 | ||||
-rw-r--r-- | intern/cycles/device/cuda/device_impl.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/device/hip/device_impl.cpp | 4 | ||||
-rw-r--r-- | intern/cycles/device/memory.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/kernel/device/cpu/image.h | 8 | ||||
-rw-r--r-- | intern/cycles/kernel/device/gpu/image.h | 13 | ||||
-rw-r--r-- | intern/cycles/scene/image.cpp | 11 | ||||
-rw-r--r-- | intern/cycles/scene/image_oiio.cpp | 2 | ||||
-rw-r--r-- | intern/cycles/scene/image_vdb.cpp | 31 | ||||
-rw-r--r-- | intern/cycles/scene/image_vdb.h | 1 | ||||
-rw-r--r-- | intern/cycles/scene/object.cpp | 6 | ||||
-rw-r--r-- | intern/cycles/util/texture.h | 2 |
12 files changed, 93 insertions, 13 deletions
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); @@ -241,6 +244,20 @@ class BlenderVolumeLoader : public VDBImageLoader { } } #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 } BL::Volume b_volume; @@ -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,6 +118,7 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet openvdb::tools::pruneInactive(pruned_grid.tree()); nanogrid = nanovdb::openToNanoVDB(pruned_grid);*/ ToNanoOp op; + op.precision = precision; if (!openvdb::grid_type_operation(grid, op)) { return false; } @@ -124,7 +141,15 @@ bool VDBImageLoader::load_metadata(const ImageDeviceFeatures &features, ImageMet if (nanogrid) { metadata.byte_size = nanogrid.size(); if (metadata.channels == 1) { - metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT; + if (precision == 0) { + metadata.type = IMAGE_DATA_TYPE_NANOVDB_FPN; + } + else if (precision == 16) { + metadata.type = IMAGE_DATA_TYPE_NANOVDB_FP16; + } + else { + metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT; + } } else { metadata.type = IMAGE_DATA_TYPE_NANOVDB_FLOAT3; diff --git a/intern/cycles/scene/image_vdb.h b/intern/cycles/scene/image_vdb.h index a5fd51915ef..ea5f6b0b3d9 100644 --- a/intern/cycles/scene/image_vdb.h +++ b/intern/cycles/scene/image_vdb.h @@ -51,6 +51,7 @@ class VDBImageLoader : public ImageLoader { #endif #ifdef WITH_NANOVDB nanovdb::GridHandle<> nanogrid; + int precision = 0; #endif }; diff --git a/intern/cycles/scene/object.cpp b/intern/cycles/scene/object.cpp index 8015be6393b..ddd89a16640 100644 --- a/intern/cycles/scene/object.cpp +++ b/intern/cycles/scene/object.cpp @@ -327,9 +327,11 @@ float Object::compute_volume_step_size() const /* Auto detect step size. */ float3 size = one_float3(); #ifdef WITH_NANOVDB - /* Dimensions were not applied to image transform with NanOVDB (see image_vdb.cpp) */ + /* Dimensions were not applied to image transform with NanoVDB (see image_vdb.cpp) */ if (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) #endif size /= make_float3(metadata.width, metadata.height, metadata.depth); diff --git a/intern/cycles/util/texture.h b/intern/cycles/util/texture.h index e8bb058a3c9..90e842933c2 100644 --- a/intern/cycles/util/texture.h +++ b/intern/cycles/util/texture.h @@ -37,6 +37,8 @@ typedef enum ImageDataType { IMAGE_DATA_TYPE_USHORT = 7, IMAGE_DATA_TYPE_NANOVDB_FLOAT = 8, IMAGE_DATA_TYPE_NANOVDB_FLOAT3 = 9, + IMAGE_DATA_TYPE_NANOVDB_FPN = 10, + IMAGE_DATA_TYPE_NANOVDB_FP16 = 11, IMAGE_DATA_NUM_TYPES } ImageDataType; |