openvdb icon indicating copy to clipboard operation
openvdb copied to clipboard

[BUG] NanoVDB, no generic way to sample quantized float values in PNanoVDB.h

Open thilamb opened this issue 4 years ago • 1 comments

Environment

Operating System: Windows 2019 Version / Commit SHA: NanoVDB 32.3, OpenVDB 8.1 Other: C++, HLSL

Describe the bug

While testing the quantized NanoVDB floating point values (excellent addition to the library by the way), I noticed there was no "simple" and generic way to read floating point values. Although it is possible to abstract all the C++-side code and be floating point format agnostic, reading values in the HLSL shader requires some hard-coded changes, depending on the format.

For example when using pnanovdb_hdda_zero_crossing function (PNanoVDB.h), it is not ready yet for quantized models. I'm expecting this function to be optimal, and to keep using it to render my level sets, but it needs some adjustements to work correctly.

To Reproduce

Steps to reproduce the behavior:

  1. Load a Fp4, Fp8, Fp16, FpN quantized model in the viewer
  2. Use the HLSL mode (PNanoVDB.h)
  3. Model is filled with holes

Note that I haven't tried using the viewer for this, as it does not support a HLSL mode yet, and the GLSL mode doesn't even work on my machine anymore (it used to work with 29.3). Feel free to contact me for additional details if needed.

Expected behavior

  • Ideally, I would like an optimal and easy way to sample floating point values in a grid/root, without having to hard-code it (and without shader variations)
  • pnanovdb_hdda_zero_crossing from PNanoVDB.h should work with all floating point formats

Proposed solution

A sub-optimal but generic solution could be along the lines of:

PNANOVDB_FORCE_INLINE float pnanovdb_root_read_float_typed(pnanovdb_grid_type_t grid_type, pnanovdb_buf_t buf, pnanovdb_address_t address, PNANOVDB_IN(pnanovdb_coord_t) ijk, pnanovdb_uint32_t level)
{
	float ret;
	if (level == 0 && grid_type != PNANOVDB_GRID_TYPE_FLOAT)
	{
		if (grid_type == PNANOVDB_GRID_TYPE_FPN)
		{
			ret = pnanovdb_leaf_fpn_read_float(buf, address, ijk);
		}
		else
		{
			ret = pnanovdb_leaf_fp_read_float(buf, address, ijk, grid_type - PNANOVDB_GRID_TYPE_FP4 + 2u);
		}
	}
	else
	{
		ret = pnanovdb_read_float(buf, address);
	}
	return ret;
}

And adapting the pnanovdb_hdda_zero_crossing function would look like:

pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address_and_level(grid_type, buf, acc, PNANOVDB_REF(ijk), PNANOVDB_REF(level));
	float v0 = pnanovdb_root_read_float_typed(grid_type, buf, address, ijk, level);

instead of the current:

pnanovdb_address_t address = pnanovdb_readaccessor_get_value_address(PNANOVDB_GRID_TYPE_FLOAT, buf, acc, PNANOVDB_REF(ijk));
	float v0 = pnanovdb_read_float(buf, address);

thilamb avatar Aug 31 '21 17:08 thilamb

Thanks - we're looking into this now

kmuseth avatar Sep 30 '21 16:09 kmuseth