From 185e56ce467974e5cb1399c6c70a2b9386ed1249 Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 22 Oct 2026 11:17:48 +0100 Subject: [PATCH 1/2] VDBObject : Register HalfGrid type This is available out of the box in OpenVDB 13, but not in our current OpenVDB 12. Also moved initialisation out of VDBObject constructor and into a static initialiser. Otherwise we'd have to use another mutex around our `isRegistered()/registerGrid()` calls - while each call is threadsafe in itself, there is a race condition in calling them both, which could lead to multiple registration errors. VDBObject constructors could be called concurrently, but static initialisation only happens once. --- Changes | 1 + src/IECoreVDB/VDBObject.cpp | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Changes b/Changes index d75f86aaa3..73684bb55a 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,7 @@ Improvements - USD : - All `radiance:sphericalHarmonicsCoefficients` are now loaded for `ParticleField3DGaussianSplat` objects, regardless of the `radiance:sphericalHarmonicsDegree`. - Added write support for `ParticleField3DGaussianSplat`. +- VDB : Added support for half-typed grids. 10.7.3.1 (relative to 10.7.3.0) ======== diff --git a/src/IECoreVDB/VDBObject.cpp b/src/IECoreVDB/VDBObject.cpp index ad49dd8a9b..9aa1a80f02 100644 --- a/src/IECoreVDB/VDBObject.cpp +++ b/src/IECoreVDB/VDBObject.cpp @@ -102,6 +102,22 @@ struct MurmurHashSink MurmurHash &hash; }; +const bool g_initialised = [] () { + + openvdb::initialize(); + + /// \todo Remove when we upgrade to OpenVDB 13. + using HalfTree = openvdb::tree::Tree4::Type; + using HalfGrid = openvdb::Grid; + if( !HalfGrid::isRegistered() ) + { + HalfGrid::registerGrid(); + } + + return true; + +} (); + } IE_CORE_DEFINEOBJECTTYPEDESCRIPTION( VDBObject ); @@ -114,8 +130,6 @@ VDBObject::VDBObject() : m_unmodifiedFromFile( false ) VDBObject::VDBObject( const std::string &filename ) : m_unmodifiedFromFile( true ) { - openvdb::initialize(); // safe to call multiple times but has a performance hit of a mutex. - // note it seems fine for this file object to go out of scope // and grids are still able to pull in additional grid data m_lockedFile.reset( new LockedFile( new openvdb::io::File( filename ) ) ); From 2e94fe960ec5cd8fe49078a172ff192613cb546e Mon Sep 17 00:00:00 2001 From: John Haddon Date: Thu, 22 Oct 2026 13:04:13 +0100 Subject: [PATCH 2/2] VDBObject : Mitigate lack of thread safety in `hash()` This made lots of interesting sequences of events possible - here's one : 1. Thread A sees `m_hashValid == false` and starts to compute the hash. 2. Thread B also sees `m_hashValid == false` and also starts to compute the hash. 3. Threads A and B merrily stomp over `m_hash` concurrently, so the result won't be deterministic. There are further problems though... 4. Thread A finishes stomping and sets `m_hashValid = true`. Thread B continues stomping. 5. Threads C, D, E etc see `m_hashValid == true` and read whatever the current value of `m_hash` is - all getting different values from different stages of thread B's stomping. This was causing instanced in-memory VDBS to lose their instancing when exported to Arnold, because each instance got a different random version of the hash. This is mitigated by computing the hash in a temporary variable before assigning it. This isn't a full fix though, because the compiler _could_ reorder `m_hashValid = true` before `m_hash = h` from the point of view of a reading thread. Solving that needs some form of synchronisation (mutex, call_once etc), which we can't do without an ABI break. --- src/IECoreVDB/VDBObject.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/IECoreVDB/VDBObject.cpp b/src/IECoreVDB/VDBObject.cpp index 9aa1a80f02..ef1ffb805f 100644 --- a/src/IECoreVDB/VDBObject.cpp +++ b/src/IECoreVDB/VDBObject.cpp @@ -434,11 +434,12 @@ openvdb::GridBase::Ptr VDBObject::HashedGrid::grid() const IECore::MurmurHash VDBObject::HashedGrid::hash() const { + /// \todo This is not threadsafe. Fix it. if( !m_hashValid ) { - m_hash = IECore::MurmurHash(); + IECore::MurmurHash h; - MurmurHashSink sink( m_hash ); + MurmurHashSink sink( h ); boost::iostreams::stream hashStream( sink ); openvdb::io::StreamMetadata::Ptr streamMetadata ( new openvdb::io::StreamMetadata() ); @@ -449,6 +450,7 @@ IECore::MurmurHash VDBObject::HashedGrid::hash() const m_grid->writeBuffers( hashStream ); m_grid->writeTransform( hashStream ); + m_hash = h; m_hashValid = true; }