Skip to content

Commit 8637382

Browse files
authored
bug-fix to nanovdb related to new I/O (#1699)
* bug-fix to nanovdb related to new I/O Signed-off-by: Ken Museth <ken.museth@gmail.com> * improved GridData::isValid Signed-off-by: Ken Museth <ken.museth@gmail.com> --------- Signed-off-by: Ken Museth <ken.museth@gmail.com>
1 parent fc4a559 commit 8637382

File tree

4 files changed

+59
-78
lines changed

4 files changed

+59
-78
lines changed

nanovdb/nanovdb/NanoVDB.h

Lines changed: 41 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -249,60 +249,37 @@ namespace nanovdb {
249249
// --------------------------> Build types <------------------------------------
250250

251251
/// @brief Dummy type for a voxel whose value equals an offset into an external value array
252-
class ValueIndex
253-
{
254-
};
252+
class ValueIndex{};
255253

256254
/// @brief Dummy type for a voxel whose value equals an offset into an external value array of active values
257-
class ValueOnIndex
258-
{
259-
};
255+
class ValueOnIndex{};
260256

261257
/// @brief Like @c ValueIndex but with a mutable mask
262-
class ValueIndexMask
263-
{
264-
};
258+
class ValueIndexMask{};
265259

266260
/// @brief Like @c ValueOnIndex but with a mutable mask
267-
class ValueOnIndexMask
268-
{
269-
};
261+
class ValueOnIndexMask{};
270262

271263
/// @brief Dummy type for a voxel whose value equals its binary active state
272-
class ValueMask
273-
{
274-
};
264+
class ValueMask{};
275265

276-
/// @brief Dummy type for a 16 bit floating point values
277-
class Half
278-
{
279-
};
266+
/// @brief Dummy type for a 16 bit floating point values (placeholder for IEEE 754 Half)
267+
class Half{};
280268

281269
/// @brief Dummy type for a 4bit quantization of float point values
282-
class Fp4
283-
{
284-
};
270+
class Fp4{};
285271

286272
/// @brief Dummy type for a 8bit quantization of float point values
287-
class Fp8
288-
{
289-
};
273+
class Fp8{};
290274

291275
/// @brief Dummy type for a 16bit quantization of float point values
292-
class Fp16
293-
{
294-
};
276+
class Fp16{};
295277

296278
/// @brief Dummy type for a variable bit quantization of floating point values
297-
class FpN
298-
{
299-
};
279+
class FpN{};
300280

301-
/// @dummy type for indexing points into voxels
302-
class Point
303-
{
304-
};
305-
//using Points = Point;// for backwards compatibility
281+
/// @brief Dummy type for indexing points into voxels
282+
class Point{};
306283

307284
// --------------------------> GridType <------------------------------------
308285

@@ -760,7 +737,7 @@ __hostdev__ inline static T* alignPtr(T* p)
760737
return reinterpret_cast<T*>( (uint8_t*)p + alignmentPadding(p) );
761738
}
762739

763-
/// @brief offset the specified pointer so it is aligned.
740+
/// @brief offset the specified const pointer so it is aligned.
764741
template <typename T>
765742
__hostdev__ inline static const T* alignPtr(const T* p)
766743
{
@@ -863,10 +840,10 @@ __hostdev__ inline bool isIndex(GridType gridType)
863840
// --------------------------> memcpy64 <------------------------------------
864841

865842
/// @brief copy 64 bit words from @c src to @c dst
866-
/// @param dst pointer to destination
867-
/// @param src pointer to source
843+
/// @param dst 64 bit aligned pointer to destination
844+
/// @param src 64 bit aligned pointer to source
868845
/// @param word_count number of 64 bit words to be copied
869-
/// @return destination pointer
846+
/// @return destination pointer @c dst
870847
/// @warning @c src and @c dst cannot overlap and should both be 64 bit aligned
871848
__hostdev__ inline static void* memcpy64(void *dst, const void *src, size_t word_count)
872849
{
@@ -948,13 +925,16 @@ class Version
948925
{
949926
uint32_t mData; // 11 + 11 + 10 bit packing of major + minor + patch
950927
public:
928+
/// @brief Default constructor
951929
__hostdev__ Version()
952930
: mData(uint32_t(NANOVDB_MAJOR_VERSION_NUMBER) << 21 |
953931
uint32_t(NANOVDB_MINOR_VERSION_NUMBER) << 10 |
954932
uint32_t(NANOVDB_PATCH_VERSION_NUMBER))
955933
{
956934
}
935+
/// @brief Constructor from a raw uint32_t data representation
957936
__hostdev__ Version(uint32_t data) : mData(data) {}
937+
/// @brief Constructor from major.minor.patch version numbers
958938
__hostdev__ Version(uint32_t major, uint32_t minor, uint32_t patch)
959939
: mData(major << 21 | minor << 10 | patch)
960940
{
@@ -970,14 +950,15 @@ class Version
970950
__hostdev__ uint32_t id() const { return mData; }
971951
__hostdev__ uint32_t getMajor() const { return (mData >> 21) & ((1u << 11) - 1); }
972952
__hostdev__ uint32_t getMinor() const { return (mData >> 10) & ((1u << 11) - 1); }
973-
__hostdev__ uint32_t getPatch() const { return mData & ((1u << 10) - 1); }
974-
__hostdev__ bool isCompatible() const { return this->getMajor() == uint32_t(NANOVDB_MAJOR_VERSION_NUMBER);}
975-
/// @brief Check the major version of this instance relative to NANOVDB_MAJOR_VERSION_NUMBER
976-
/// @return return 0 if the major version equals NANOVDB_MAJOR_VERSION_NUMBER, else a negative age if it is
977-
/// older, i.e. smaller, and a positive age if it's newer, i.e.e larger.
953+
__hostdev__ uint32_t getPatch() const { return mData & ((1u << 10) - 1); }
954+
__hostdev__ bool isCompatible() const { return this->getMajor() == uint32_t(NANOVDB_MAJOR_VERSION_NUMBER); }
955+
/// @brief Returns the difference between major version of this instance and NANOVDB_MAJOR_VERSION_NUMBER
956+
/// @return return 0 if the major version equals NANOVDB_MAJOR_VERSION_NUMBER, else a negative age if this
957+
/// instance has a smaller major verion (is older), and a positive age if it is newer, i.e. larger.
978958
__hostdev__ int age() const {return int(this->getMajor()) - int(NANOVDB_MAJOR_VERSION_NUMBER);}
979959

980960
#ifndef __CUDACC_RTC__
961+
/// @brief returns a c-string of the semantic version, i.e. major.minor.patch
981962
const char* c_str() const
982963
{
983964
char* buffer = (char*)malloc(4 + 1 + 4 + 1 + 4 + 1); // xxxx.xxxx.xxxx\0
@@ -990,7 +971,7 @@ class Version
990971
// ----------------------------> Various math functions <-------------------------------------
991972

992973
//@{
993-
/// @brief Pi constant taken from Boost to match old behaviour
974+
/// @brief Pi constant taken from Boost to match old behaviour
994975
template<typename T>
995976
inline __hostdev__ constexpr T pi()
996977
{
@@ -3560,13 +3541,18 @@ struct NANOVDB_ALIGN(NANOVDB_DATA_ALIGNMENT) GridData
35603541
mGridType = gridType;
35613542
mBlindMetadataOffset = mGridSize; // i.e. no blind data
35623543
mBlindMetadataCount = 0u; // i.e. no blind data
3563-
mData0 = 0u;
3544+
mData0 = 0u; // zero padding
35643545
mData1 = 0u; // only used for index and point grids
3565-
mData2 = 0u;
3546+
mData2 = NANOVDB_MAGIC_GRID; // since version 32.6.0 (might be removed in the future)
35663547
}
35673548
/// @brief return true if the magic number and the version are both valid
35683549
__hostdev__ bool isValid() const {
3569-
return mMagic == NANOVDB_MAGIC_GRID || (mMagic == NANOVDB_MAGIC_NUMBER && mVersion.isCompatible());
3550+
if (mMagic == NANOVDB_MAGIC_GRID || mData2 == NANOVDB_MAGIC_GRID) return true;
3551+
bool test = mMagic == NANOVDB_MAGIC_NUMBER;// could be GridData or io::FileHeader
3552+
if (test) test = mVersion.isCompatible();
3553+
if (test) test = mGridCount > 0u && mGridIndex < mGridCount;
3554+
if (test) test = mGridClass < GridClass::End && mGridType < GridType::End;
3555+
return test;
35703556
}
35713557
// Set and unset various bit flags
35723558
__hostdev__ void setMinMaxOn(bool on = true) { mFlags.setMask(GridFlags::HasMinMax, on); }
@@ -7980,20 +7966,20 @@ VecT<GridHandleT> readUncompressedGrids(StreamT& is, const typename GridHandleT:
79807966
{
79817967
VecT<GridHandleT> handles;
79827968
GridData data;
7983-
is.read((char*)&data, 40);// we only need to load the first 40 bytes
7984-
if (data.mMagic == NANOVDB_MAGIC_GRID || data.isValid()) {// stream contains a raw grid buffer
7969+
is.read((char*)&data, sizeof(GridData));
7970+
if (data.isValid()) {// stream contains a raw grid buffer
79857971
uint64_t size = data.mGridSize, sum = 0u;
79867972
while(data.mGridIndex + 1u < data.mGridCount) {
7987-
is.skip(data.mGridSize - 40);// skip grid
7988-
is.read((char*)&data, 40);// read 40 bytes
7973+
is.skip(data.mGridSize - sizeof(GridData));// skip grid
7974+
is.read((char*)&data, sizeof(GridData));// read sizeof(GridData) bytes
79897975
sum += data.mGridSize;
79907976
}
7991-
is.skip(-int64_t(sum + 40));// rewind to start
7977+
is.skip(-int64_t(sum + sizeof(GridData)));// rewind to start
79927978
auto buffer = GridHandleT::BufferType::create(size + sum, &pool);
79937979
is.read((char*)(buffer.data()), buffer.size());
79947980
handles.emplace_back(std::move(buffer));
79957981
} else {// Header0, MetaData0, gridName0, Grid0...HeaderN, MetaDataN, gridNameN, GridN
7996-
is.skip(-40);// rewind
7982+
is.skip(-sizeof(GridData));// rewind
79977983
FileHeader head;
79987984
while(is.read((char*)&head, sizeof(FileHeader))) {
79997985
if (!head.isValid()) {

nanovdb/nanovdb/examples/ex_voxels_to_grid_cuda/ex_voxels_to_grid_cuda.cu

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ int main()
1717

1818
// Generate a NanoVDB grid that contains the list of voxels on the device
1919
auto handle = cudaVoxelsToGrid<float>(d_coords, numVoxels);
20-
auto *grid = handle.deviceGrid<float>();
20+
auto *d_grid = handle.deviceGrid<float>();
2121

2222
// Define a list of values and copy them to the device
2323
float values[numVoxels] = {1.4f, 6.7f, -5.0f}, *d_values;
@@ -29,13 +29,13 @@ int main()
2929
cudaLambdaKernel<<<numBlocks, numThreads>>>(numVoxels, [=] __device__(size_t tid) {
3030
using OpT = SetVoxel<float>;// defines type of random-access operation (set value)
3131
const Coord &ijk = d_coords[tid];
32-
grid->tree().set<OpT>(ijk, d_values[tid]);// normally one should use a ValueAccessor
33-
printf("GPU: voxel # %lu, grid(%4i,%4i,%4i) = %5.1f\n", tid, ijk[0], ijk[1], ijk[2], grid->tree().getValue(ijk));
32+
d_grid->tree().set<OpT>(ijk, d_values[tid]);// normally one should use a ValueAccessor
33+
printf("GPU: voxel # %lu, grid(%4i,%4i,%4i) = %5.1f\n", tid, ijk[0], ijk[1], ijk[2], d_grid->tree().getValue(ijk));
3434
}); cudaCheckError();
3535

3636
// Copy grid from GPU to CPU and print the voxel values for validation
3737
handle.deviceDownload();// creates a copy on the CPU
38-
grid = handle.grid<float>();
38+
auto *grid = handle.grid<float>();
3939
for (size_t i=0; i<numVoxels; ++i) {
4040
const Coord &ijk = coords[i];
4141
printf("CPU: voxel # %lu, grid(%4i,%4i,%4i) = %5.1f\n", i, ijk[0], ijk[1], ijk[2], grid->tree().getValue(ijk));

nanovdb/nanovdb/util/GridHandle.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -363,20 +363,20 @@ template<typename BufferT>
363363
void GridHandle<BufferT>::read(std::istream& is, const BufferT& pool)
364364
{
365365
GridData data;
366-
is.read((char*)&data, 40);// only 40 bytes are required for all the data we need in GridData
366+
is.read((char*)&data, sizeof(GridData));
367367
if (data.isValid()) {
368368
uint64_t size = data.mGridSize, sum = 0u;
369369
while(data.mGridIndex + 1u < data.mGridCount) {// loop over remaining raw grids in stream
370-
is.seekg(data.mGridSize - 40, std::ios::cur);// skip grid
371-
is.read((char*)&data, 40);// read 40 bytes of the next GridData
370+
is.seekg(data.mGridSize - sizeof(GridData), std::ios::cur);// skip grid
371+
is.read((char*)&data, sizeof(GridData));
372372
sum += data.mGridSize;
373373
}
374-
is.seekg(-int64_t(sum + 40), std::ios::cur);// rewind to start
375374
auto buffer = BufferT::create(size + sum, &pool);
375+
is.seekg(-int64_t(sum + sizeof(GridData)), std::ios::cur);// rewind to start
376376
is.read((char*)(buffer.data()), buffer.size());
377377
*this = GridHandle(std::move(buffer));
378378
} else {
379-
is.seekg(-40, std::ios::cur);// rewind
379+
is.seekg(-sizeof(GridData), std::ios::cur);// rewind
380380
throw std::logic_error("This stream does not contain a valid raw grid buffer");
381381
}
382382
}// void GridHandle<BufferT>::read(std::istream& is, const BufferT& pool)
@@ -385,20 +385,20 @@ template<typename BufferT>
385385
void GridHandle<BufferT>::read(std::istream& is, uint32_t n, const BufferT& pool)
386386
{
387387
GridData data;
388-
is.read((char*)&data, 40);// only 40 bytes are required for all the data we need in GridData
388+
is.read((char*)&data, sizeof(GridData));
389389
if (data.isValid()) {
390390
if (n>=data.mGridCount) throw std::runtime_error("stream does not contain a #" + std::to_string(n) + " grid");
391391
while(data.mGridIndex != n) {
392-
is.seekg(data.mGridSize - 40, std::ios::cur);// skip grid
393-
is.read((char*)&data, 40);// read 40 bytes
392+
is.seekg(data.mGridSize - sizeof(GridData), std::ios::cur);// skip grid
393+
is.read((char*)&data, sizeof(GridData));
394394
}
395395
auto buffer = BufferT::create(data.mGridSize, &pool);
396-
is.seekg(-40, std::ios::cur);// rewind
396+
is.seekg(-sizeof(GridData), std::ios::cur);// rewind
397397
is.read((char*)(buffer.data()), data.mGridSize);
398398
updateGridCount((GridData*)buffer.data(), 0u, 1u);
399399
*this = GridHandle(std::move(buffer));
400400
} else {
401-
is.seekg(-40, std::ios::cur);// rewind 40 bytes to undo initial read
401+
is.seekg(-sizeof(GridData), std::ios::cur);// rewind sizeof(GridData) bytes to undo initial read
402402
throw std::logic_error("This file does not contain a valid raw buffer");
403403
}
404404
}// void GridHandle<BufferT>::read(std::istream& is, uint32_t n, const BufferT& pool)
@@ -414,7 +414,7 @@ void GridHandle<BufferT>::read(std::istream& is, const std::string &gridName, co
414414
uint32_t n = 0;
415415
while(data.mGridName != gridName && n++ < data.mGridCount) {
416416
is.seekg(data.mGridSize, std::ios::cur);// skip grid
417-
is.read((char*)&data, byteSize);// read 40 bytes
417+
is.read((char*)&data, byteSize);// read sizeof(GridData) bytes
418418
is.seekg(-byteSize, std::ios::cur);// rewind
419419
}
420420
if (n>data.mGridCount) throw std::runtime_error("No raw grid named \""+gridName+"\"");

nanovdb/nanovdb/util/cuda/CudaPointsToGrid.cuh

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -552,28 +552,23 @@ void CudaPointsToGrid<BuildT, AllocT>::countNodes(const PtrT points, size_t poin
552552
if (mVerbose==2) mTimer.restart("Generate tile keys");
553553
cudaLambdaKernel<<<numBlocks(pointCount), mNumThreads, 0, mStream>>>(pointCount, [=] __device__(size_t tid, const Data *d_data, const PtrT points) {
554554
auto coordToKey = [](const Coord &ijk)->uint64_t{
555-
// int32_t has a range of -2^31 to 2^31 - 1
556-
// uint32_t has a range of 0 to 2^32 - 1
555+
// Note: int32_t has a range of -2^31 to 2^31 - 1 whereas uint32_t has a range of 0 to 2^32 - 1
557556
static constexpr int64_t offset = 1 << 31;
558557
return (uint64_t(uint32_t(int64_t(ijk[2]) + offset) >> 12) ) | // z is the lower 21 bits
559558
(uint64_t(uint32_t(int64_t(ijk[1]) + offset) >> 12) << 21) | // y is the middle 21 bits
560559
(uint64_t(uint32_t(int64_t(ijk[0]) + offset) >> 12) << 42); // x is the upper 21 bits
561-
};
560+
};// coordToKey lambda functor
562561
d_indx[tid] = uint32_t(tid);
563562
uint64_t &key = d_keys[tid];
564563
if constexpr(is_same<BuildT, Point>::value) {// points are in world space
565564
if constexpr(is_same<Vec3T, Vec3f>::value) {
566565
key = coordToKey(d_data->map.applyInverseMapF(points[tid]).round());
567-
//key = NanoRoot<Point>::CoordToKey(d_data->map.applyInverseMapF(points[tid]).round());
568566
} else {// points are Vec3d
569-
//key = NanoRoot<Point>::CoordToKey(d_data->map.applyInverseMap(points[tid]).round());
570567
key = coordToKey(d_data->map.applyInverseMap(points[tid]).round());
571568
}
572569
} else if constexpr(is_same<Vec3T, Coord>::value) {// points Coord are in index space
573-
//key = NanoRoot<BuildT>::CoordToKey(points[tid]);
574570
key = coordToKey(points[tid]);
575571
} else {// points are Vec3f or Vec3d in index space
576-
//key = NanoRoot<BuildT>::CoordToKey(points[tid].round());
577572
key = coordToKey(points[tid].round());
578573
}
579574
}, mDeviceData, points);
@@ -605,7 +600,7 @@ void CudaPointsToGrid<BuildT, AllocT>::countNodes(const PtrT points, size_t poin
605600
uint64_t(NanoUpper<BuildT>::CoordToOffset(ijk)) << 21 | // lower offset: 32^3 = 2^15, i.e. next 15 bits
606601
uint64_t(NanoLower<BuildT>::CoordToOffset(ijk)) << 9 | // leaf offset: 16^3 = 2^12, i.e. next 12 bits
607602
uint64_t(NanoLeaf< BuildT>::CoordToOffset(ijk)); // voxel offset: 8^3 = 2^9, i.e. first 9 bits
608-
};
603+
};// voxelKey lambda functor
609604
tid += offset;
610605
Vec3T p = points[d_indx[tid]];
611606
if constexpr(is_same<BuildT, Point>::value) p = is_same<Vec3T, Vec3f>::value ? d_data->map.applyInverseMapF(p) : d_data->map.applyInverseMap(p);

0 commit comments

Comments
 (0)