Skip to content

Commit 6eb31a0

Browse files
Merge pull request #898 from Devsh-Graphics-Programming/mitsuba_serialized
Mitsuba serialized loader
2 parents 43a1d17 + 787212f commit 6eb31a0

35 files changed

+937
-670
lines changed

3rdparty/CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,11 +434,11 @@ if (NBL_BUILD_MITSUBA_LOADER)
434434
add_subdirectory(libexpat/expat EXCLUDE_FROM_ALL)
435435

436436
set(MITSUBA_LOADER_DEPENDENTS
437-
expat
437+
expat zlibstatic
438438
)
439439
set(MITSUBA_LOADER_DEPENDENTS ${MITSUBA_LOADER_DEPENDENTS} PARENT_SCOPE)
440440
set(MITSUBA_LOADER_DEPENDENT_LIBS
441-
expat
441+
expat "${ZLIB_LIBRARY}"
442442
)
443443
set(MITSUBA_LOADER_DEPENDENT_LIBS ${MITSUBA_LOADER_DEPENDENT_LIBS} PARENT_SCOPE)
444444
endif()

include/nbl/application_templates/BasicMultiQueueApplication.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class BasicMultiQueueApplication : public virtual MonoDeviceApplication
5151
return false;
5252

5353
using namespace core;
54-
m_utils = make_smart_refctd_ptr<video::IUtilities>(smart_refctd_ptr(m_device),smart_refctd_ptr(m_logger));
54+
m_utils = video::IUtilities::create(smart_refctd_ptr(m_device),smart_refctd_ptr(m_logger));
5555
if (!m_utils)
5656
return logFail("Failed to create nbl::video::IUtilities!");
5757

include/nbl/asset/ICPUGeometryCollection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class NBL_API2 ICPUGeometryCollection : public IAsset, public IGeometryCollectio
5151
}
5252

5353
//
54-
inline bool setAABB(const IGeometryBase::SAABBStorage& aabb)
54+
inline bool setAABB(const decltype(base_t::m_aabb)& aabb)
5555
{
5656
if (isMutable())
5757
{

include/nbl/asset/ICPUPolygonGeometry.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class NBL_API2 ICPUPolygonGeometry final : public IPolygonGeometry<ICPUBuffer>
3434
retval->m_positionView = m_positionView.clone(nextDepth);
3535
retval->m_jointOBBView = m_jointOBBView.clone(nextDepth);
3636
retval->m_indexView = m_indexView.clone(nextDepth);
37+
retval->m_aabb = m_aabb;
3738
retval->m_jointWeightViews.reserve(m_jointWeightViews.size());
3839
for (const auto& pair : m_jointWeightViews)
3940
retval->m_jointWeightViews.push_back({
@@ -96,6 +97,22 @@ class NBL_API2 ICPUPolygonGeometry final : public IPolygonGeometry<ICPUBuffer>
9697
return false;
9798
}
9899

100+
//
101+
template<typename Visitor>
102+
inline void visitAABB(Visitor&& visitor) const {return base_t::visitAABB(std::forward<Visitor>(visitor));}
103+
template<typename Visitor>
104+
inline bool visitAABB(Visitor&& visitor)
105+
{
106+
if (isMutable())
107+
{
108+
getAABBStorage().visit(getAABBFormat(),std::forward<Visitor>(visitor));
109+
return true;
110+
}
111+
return false;
112+
}
113+
template<typename Scalar>
114+
inline bool setAABB(const hlsl::shapes::AABB<3,Scalar>& aabb) {return visitAABB([&aabb](auto&& ref)->void{ref=aabb;});}
115+
99116
//
100117
inline bool setJointCount(const uint32_t count)
101118
{

include/nbl/asset/IGeometry.h

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class IGeometryBase : public virtual core::IReferenceCounted
4747
U8_NORM,
4848
S8,
4949
S8_NORM,
50+
Count,
5051
BitCount=4
5152
};
5253
//
@@ -155,6 +156,11 @@ class IGeometryBase : public virtual core::IReferenceCounted
155156
const_cast<SAABBStorage*>(this)->visit(format,std::forward<Visitor>(visitor));
156157
}
157158

159+
inline void reset(const EAABBFormat format)
160+
{
161+
visit(format,[](auto& aabb)->void{aabb = aabb.create();});
162+
}
163+
158164
hlsl::shapes::AABB<4,hlsl::float64_t> f64 = hlsl::shapes::AABB<4,hlsl::float64_t>::create();
159165
hlsl::shapes::AABB<4,uint64_t> u64;
160166
hlsl::shapes::AABB<4,int64_t> s64;
@@ -206,30 +212,23 @@ class IGeometryBase : public virtual core::IReferenceCounted
206212

207213
//
208214
template<typename Visitor>
209-
inline void visitAABB(Visitor&& visitor) {encodedDataRange.visit(rangeFormat,std::forward<Visitor>(visitor));}
215+
inline void visitRange(Visitor&& visitor) {encodedDataRange.visit(rangeFormat,std::forward<Visitor>(visitor));}
210216
template<typename Visitor>
211-
inline void visitAABB(Visitor&& visitor) const {encodedDataRange.visit(rangeFormat,std::forward<Visitor>(visitor));}
217+
inline void visitRange(Visitor&& visitor) const {encodedDataRange.visit(rangeFormat,std::forward<Visitor>(visitor));}
212218

213219
//
214-
inline void resetRange(const EAABBFormat newFormat)
215-
{
216-
rangeFormat = newFormat;
217-
auto tmp = [](auto& aabb)->void{aabb = aabb.create();};
218-
visitAABB(tmp);
219-
}
220-
inline void resetRange() {resetRange(rangeFormat);}
220+
inline void resetRange() {encodedDataRange.reset(rangeFormat);}
221221

222222
//
223223
template<typename AABB>
224224
inline AABB getRange() const
225225
{
226226
AABB retval = AABB::create();
227-
auto tmp = [&retval](const auto& aabb)->void
227+
visitRange([&retval](const auto& aabb)->void
228228
{
229229
retval.minVx = aabb.minVx;
230230
retval.maxVx = aabb.maxVx;
231-
};
232-
visitAABB(tmp);
231+
});
233232
return retval;
234233
}
235234

@@ -245,11 +244,23 @@ class IGeometryBase : public virtual core::IReferenceCounted
245244
};
246245

247246
virtual EAABBFormat getAABBFormat() const = 0;
248-
virtual const SAABBStorage& getAABB() const = 0;
247+
virtual const SAABBStorage& getAABBStorage() const = 0;
249248
template<typename Visitor>
250249
inline void visitAABB(Visitor&& visitor) const
251250
{
252-
getAABB().visit(getAABBFormat(),std::forward<Visitor>(visitor));
251+
getAABBStorage().visit(getAABBFormat(),std::forward<Visitor>(visitor));
252+
}
253+
//
254+
template<typename AABB>
255+
inline AABB getAABB() const
256+
{
257+
auto retval = AABB::create();
258+
visitAABB([&retval](const auto& aabb)->void
259+
{
260+
retval.minVx = aabb.minVx;
261+
retval.maxVx = aabb.maxVx;
262+
});
263+
return retval;
253264
}
254265

255266
protected:
@@ -278,6 +289,9 @@ class IGeometry : public std::conditional_t<std::is_same_v<BufferType,ICPUBuffer
278289
return true;
279290
}
280291

292+
//
293+
inline IGeometryBase::EAABBFormat getAABBFormat() const override final {return m_positionView.composed.rangeFormat;}
294+
281295
struct SDataView
282296
{
283297
inline operator bool() const {return src && composed;}
@@ -488,7 +502,7 @@ struct blake3_hasher::update_impl<asset::IGeometryBase::SDataViewBase,Dummy>
488502
hasher << input.stride;
489503
hasher << input.format;
490504
hasher << input.rangeFormat;
491-
input.visitAABB([&hasher](auto& aabb)->void{hasher.update(&aabb,sizeof(aabb));});
505+
input.visitRange([&hasher](auto& aabb)->void{hasher.update(&aabb,sizeof(aabb));});
492506
}
493507
};
494508
}

include/nbl/asset/IGeometryCollection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class NBL_API2 IGeometryCollection : public virtual core::IReferenceCounted
116116

117117

118118
// For the entire collection, as always it should NOT include any geometry which is affected by a joint.
119-
IGeometryBase::SAABBStorage m_aabb;
119+
hlsl::shapes::AABB<3,hlsl::float64_t> m_aabb;
120120
SDataView m_inverseBindPoseView = {};
121121
// The AABBs gathered from all geometries (optional) and are in "bone-space" so there's no need for OBB option,
122122
// joint influence is usually aligned to the covariance matrix of geometry affected by it.

include/nbl/asset/IPolygonGeometry.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ class IPolygonGeometry : public IIndexableGeometry<BufferType>, public IPolygonG
160160
inline EPrimitiveType getPrimitiveType() const override final {return PrimitiveType;}
161161

162162
//
163-
inline IGeometryBase::EAABBFormat getAABBFormat() const override final {return base_t::m_positionView.composed.rangeFormat;}
164-
inline const IGeometryBase::SAABBStorage& getAABB() const override final {return base_t::m_positionView.composed.encodedDataRange;}
163+
inline const IGeometryBase::SAABBStorage& getAABBStorage() const override final {return m_aabb;}
165164

166165
//
167166
inline uint64_t getVertexReferenceCount() const {return base_t::getIndexView() ? base_t::getIndexCount():base_t::m_positionView.getElementCount();}
@@ -261,6 +260,8 @@ class IPolygonGeometry : public IIndexableGeometry<BufferType>, public IPolygonG
261260
return true;
262261
}
263262

263+
//
264+
IGeometryBase::SAABBStorage m_aabb = {};
264265
//
265266
core::vector<SJointWeight> m_jointWeightViews = {};
266267
//

include/nbl/asset/interchange/IGeometryLoader.h

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "nbl/asset/ICPUPolygonGeometry.h"
1111
#include "nbl/asset/interchange/IAssetLoader.h"
1212
#include "nbl/asset/interchange/IImageAssetHandlerBase.h"
13+
#include "nbl/asset/utils/CGeometryManipulator.h"
1314

1415

1516
namespace nbl::asset
@@ -23,18 +24,74 @@ class IGeometryLoader : public IAssetLoader
2324
protected:
2425
inline IGeometryLoader() {}
2526

26-
static inline IGeometry<ICPUBuffer>::SDataView createView(const E_FORMAT format, const size_t elementCount, const void* data=nullptr)
27+
template<bool AdoptMemory=false>
28+
static inline IGeometry<ICPUBuffer>::SDataView createView(
29+
const E_FORMAT format, const size_t elementCount, const void* data=nullptr,
30+
core::smart_refctd_ptr<core::refctd_memory_resource>&& memoryResource=nullptr, const size_t alignment=_NBL_SIMD_ALIGNMENT
31+
)
2732
{
2833
const auto stride = getTexelOrBlockBytesize(format);
29-
auto buffer = ICPUBuffer::create({{stride*elementCount},const_cast<void*>(data)});
30-
return {
34+
core::smart_refctd_ptr<ICPUBuffer> buffer;
35+
if constexpr (AdoptMemory)
36+
buffer = ICPUBuffer::create({{stride*elementCount},const_cast<void*>(data),std::move(memoryResource),alignment},core::adopt_memory);
37+
else
38+
buffer = ICPUBuffer::create({{stride*elementCount},const_cast<void*>(data),std::move(memoryResource),alignment});
39+
IGeometry<ICPUBuffer>::SDataView retval = {
3140
.composed = {
3241
.stride = stride,
3342
.format = format,
3443
.rangeFormat = IGeometryBase::getMatchingAABBFormat(format)
3544
},
3645
.src = {.offset=0,.size=buffer->getSize(),.buffer=std::move(buffer)}
3746
};
47+
if (data)
48+
{
49+
CGeometryManipulator::recomputeContentHash(retval);
50+
CGeometryManipulator::recomputeRange(retval);
51+
}
52+
return retval;
53+
}
54+
// creates a View from a mapped file
55+
class CFileMemoryResource final : public core::refctd_memory_resource
56+
{
57+
public:
58+
inline CFileMemoryResource(core::smart_refctd_ptr<system::IFile>&& _file) : m_file(std::move(_file)) {}
59+
60+
inline void* allocate(std::size_t bytes, std::size_t alignment) override
61+
{
62+
assert(false); // should never be called
63+
}
64+
inline void deallocate(void* p, std::size_t bytes, std::size_t alignment) override
65+
{
66+
assert(m_file);
67+
auto* const basePtr = reinterpret_cast<const uint8_t*>(m_file->getMappedPointer());
68+
assert(basePtr && basePtr<=p && p<=basePtr+m_file->getSize());
69+
}
70+
71+
protected:
72+
core::smart_refctd_ptr<system::IFile> m_file;
73+
};
74+
static inline IGeometry<ICPUBuffer>::SDataView createView(const E_FORMAT format, const size_t elementCount, core::smart_refctd_ptr<system::IFile>&& file, const size_t offsetInFile)
75+
{
76+
if (auto* const basePtr=reinterpret_cast<const uint8_t*>(file->getMappedPointer()); basePtr)
77+
{
78+
auto resource = core::make_smart_refctd_ptr<CFileMemoryResource>(std::move(file));
79+
auto* const data = basePtr+offsetInFile;
80+
return createView<true>(format,elementCount,data,std::move(resource),0x1ull<<hlsl::findLSB(ptrdiff_t(data)));
81+
}
82+
else
83+
{
84+
auto view = createView(format,elementCount);
85+
system::IFile::success_t success;
86+
file->read(success,reinterpret_cast<uint8_t*>(view.src.buffer->getPointer())+view.src.offset,offsetInFile,view.src.actualSize());
87+
if (success)
88+
{
89+
CGeometryManipulator::recomputeContentHash(view);
90+
CGeometryManipulator::recomputeRange(view);
91+
return view;
92+
}
93+
}
94+
return {};
3895
}
3996

4097
private:
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (C) 2018-2025 - DevSH Graphics Programming Sp. z O.O.
2+
// This file is part of the "Nabla Engine".
3+
// For conditions of distribution and use, see copyright notice in nabla.h
4+
#ifndef _NBL_ASSET_C_GEOMETRY_MANIPULATOR_H_INCLUDED_
5+
#define _NBL_ASSET_C_GEOMETRY_MANIPULATOR_H_INCLUDED_
6+
7+
8+
#include "nbl/core/declarations.h"
9+
10+
#include "nbl/asset/ICPUPolygonGeometry.h"
11+
#include "nbl/asset/utils/CQuantNormalCache.h"
12+
#include "nbl/asset/utils/CQuantQuaternionCache.h"
13+
14+
namespace nbl::asset
15+
{
16+
17+
class NBL_API2 CGeometryManipulator
18+
{
19+
public:
20+
static inline void recomputeContentHash(const IGeometry<ICPUBuffer>::SDataView& view)
21+
{
22+
if (!view)
23+
return;
24+
view.src.buffer->setContentHash(view.src.buffer->computeContentHash());
25+
}
26+
27+
static inline IGeometryBase::SAABBStorage computeRange(const IGeometry<ICPUBuffer>::SDataView& view)
28+
{
29+
if (!view || !view.composed.isFormatted())
30+
return {};
31+
auto it = reinterpret_cast<char*>(view.src.buffer->getPointer())+view.src.offset;
32+
const auto end = it+view.src.actualSize();
33+
auto addToAABB = [&](auto& aabb)->void
34+
{
35+
using aabb_t = std::remove_reference_t<decltype(aabb)>;
36+
for (auto i=0; i!=view.getElementCount(); i++)
37+
{
38+
typename aabb_t::point_t pt;
39+
view.decodeElement(i,pt);
40+
aabb.addPoint(pt);
41+
}
42+
};
43+
IGeometryBase::SDataViewBase tmp = view.composed;
44+
tmp.resetRange();
45+
tmp.visitRange(addToAABB);
46+
return tmp.encodedDataRange;
47+
}
48+
49+
static inline void recomputeRange(IGeometry<ICPUBuffer>::SDataView& view, const bool deduceRangeFormat=true)
50+
{
51+
if (!view || !view.composed.isFormatted())
52+
return;
53+
if (deduceRangeFormat)
54+
view.composed.rangeFormat = IGeometryBase::getMatchingAABBFormat(view.composed.format);
55+
view.composed.encodedDataRange = computeRange(view);
56+
}
57+
};
58+
59+
// TODO: Utility in another header for GeometryCollection to compute AABBs, deal with skins (joints), etc.
60+
61+
} // end namespace nbl::asset
62+
#endif

0 commit comments

Comments
 (0)