Skip to content

Commit 01d0c2f

Browse files
Got the first XML Scene to Parse its Materials!
1 parent b0c324f commit 01d0c2f

10 files changed

Lines changed: 477 additions & 214 deletions

File tree

include/nbl/asset/material_compiler3/CFrontendIR.h

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -749,14 +749,33 @@ class CFrontendIR final : public CNodePool
749749
// Some things we can't check such as the compatibility of the BTDF with the BRDF (matching indices of refraction, etc.)
750750
bool valid(const typed_pointer_type<const CLayer> rootHandle, system::logger_opt_ptr logger) const;
751751

752-
// For Debug Visualization (TODO: refactor to allow printing invalid nodes not in the `m_rootNodes` -> `printDotTree(std::ostringstream&,typed_pointer_type<const INode>)`)
753-
NBL_API2 void printDotGraph(std::ostringstream& str) const;
754-
inline core::string printDotGraph() const
752+
// For Debug Visualization
753+
struct SDotPrinter final
755754
{
756-
std::ostringstream tmp;
757-
printDotGraph(tmp);
758-
return tmp.str();
759-
}
755+
public:
756+
inline SDotPrinter(const CFrontendIR* ir) : m_ir(ir) {}
757+
// assign in reverse because we want materials to print in order
758+
inline SDotPrinter(const CFrontendIR* ir, std::span<const typed_pointer_type<const CLayer>> roots) : m_ir(ir), layerStack(roots.rbegin(),roots.rend())
759+
{
760+
// should probably size it better, if I knew total node count allocated or live
761+
visitedNodes.reserve(roots.size()<<3);
762+
}
763+
764+
NBL_API2 void operator()(std::ostringstream& output);
765+
inline core::string operator()()
766+
{
767+
std::ostringstream tmp;
768+
operator()(tmp);
769+
return tmp.str();
770+
}
771+
772+
core::unordered_set<typed_pointer_type<const INode>> visitedNodes;
773+
// TODO: track layering depth and indent accordingly?
774+
core::vector<typed_pointer_type<const CLayer>> layerStack;
775+
core::stack<typed_pointer_type<const IExprNode>> exprStack;
776+
private:
777+
const CFrontendIR* m_ir;
778+
};
760779

761780
protected:
762781
using CNodePool::CNodePool;

include/nbl/core/alloc/SimpleBlockBasedAllocator.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ struct ConstHandle
2929
// God, I love C++20
3030
inline auto operator<=>(const ConstHandle&) const = default;
3131

32+
// TODO: would have to forward declare Handle template
33+
// Handle<ConstHandle> _const_cast() const;
34+
3235
// LSB is the offset in the block, MSB is the block index
3336
value_t value = Invalid;
3437
};
@@ -38,20 +41,32 @@ struct Handle : _ConstHandle
3841
using const_type = _ConstHandle;
3942

4043
inline auto operator<=>(const Handle& other) const {return _ConstHandle::operator<=>(other);}
44+
45+
// inline _ConstHandle _const_cast() const {return *this;}
4146
};
4247

4348
template<typename T, typename _Handle> requires std::is_same_v<Handle<ConstHandle<typename _Handle::value_t,_Handle::Invalid>>,_Handle>
4449
struct TypedHandle final : std::conditional_t<std::is_const_v<T>,typename _Handle::const_type,_Handle>
4550
{
4651
private:
47-
using base_t = std::conditional_t<std::is_const_v<T>,typename _Handle::const_type,_Handle>;
52+
constexpr static inline bool IsConst = std::is_const_v<T>;
53+
using base_t = std::conditional_t<IsConst,typename _Handle::const_type,_Handle>;
4854

4955
public:
5056
inline auto operator<=>(const _Handle& other) const {return base_t::operator<=>(other);}
5157
inline auto operator<=>(const typename _Handle::const_type& other) const {return base_t::operator<=>(other);}
5258

59+
// implicit const_cast
5360
inline operator TypedHandle<const T,_Handle>() const {return {{.value=base_t::value}};}
61+
// explicit const_cast
62+
inline auto _const_cast() const
63+
{
64+
TypedHandle<std::conditional_t<IsConst,std::remove_const_t<T>,const T>,_Handle> retval;
65+
retval.value = base_t::value;
66+
return retval;
67+
}
5468

69+
// implicit static_cast
5570
template<typename U> requires ((std::is_void_v<U> || std::is_base_of_v<U,T>) && (!std::is_const_v<T> || std::is_const_v<U>))
5671
inline operator TypedHandle<U,_Handle>() const
5772
{
@@ -308,12 +323,8 @@ class SimpleBlockBasedAllocator<AddressAllocator,HandleValue> final : protected
308323

309324
//
310325
template<typename T, typename U> requires std::is_same_v<std::remove_cv_t<T>,std::remove_cv_t<U>>
311-
static inline typed_pointer_type<T> _const_cast(typed_pointer_type<U> p)
312-
{
313-
typed_pointer_type<T> retval;
314-
retval.value = p.value;
315-
return retval;
316-
}
326+
static inline typed_pointer_type<T> _const_cast(typed_pointer_type<U> p) {return p._const_cast();}
327+
// TODO: add `_reinrepret_cast` and `_static_cast` to the TypedHandle` and do in terms of that
317328
template<typename T, typename U> requires (!std::is_const_v<U> || std::is_const_v<T>)
318329
static inline typed_pointer_type<T> _reinterpret_cast(typed_pointer_type<U> p)
319330
{

include/nbl/ext/MitsubaLoader/CElementShape.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,14 @@ class CElementShape final : public IElement
249249
return local;
250250
}
251251

252-
inline CElementEmitter obtainEmitter() const
252+
inline const CElementEmitter* obtainEmitter() const
253253
{
254254
if (emitter)
255-
return *emitter;
255+
return emitter;
256256
if (type==CElementShape::INSTANCE && instance.parent && instance.parent->emitter)
257-
return *instance.parent->emitter;
257+
return instance.parent->emitter;
258258

259-
return CElementEmitter("");
259+
return nullptr;
260260
}
261261

262262

include/nbl/ext/MitsubaLoader/CMitsubaLoader.h

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,9 @@ class CMitsubaMaterialCompilerFrontend;
2121

2222
#if 0 // TODO
2323
//#include "nbl/builtin/glsl/ext/MitsubaLoader/instance_data_struct.glsl"
24-
#define uint uint32_t
25-
#define uvec2 uint64_t
26-
#define mat4x3 nbl::core::matrix3x4SIMD
2724
#define nbl_glsl_MC_material_data_t asset::material_compiler::material_data_t
2825
struct nbl_glsl_ext_Mitsuba_Loader_instance_data_t
2926
{
30-
struct vec3
31-
{
32-
float x, y, z;
33-
};
3427
mat4x3 tform;
3528
vec3 normalMatrixRow0;
3629
uint padding0;
@@ -40,9 +33,6 @@ struct nbl_glsl_ext_Mitsuba_Loader_instance_data_t
4033
uint determinantSignBit;
4134
nbl_glsl_MC_material_data_t material;
4235
};
43-
#undef uint
44-
#undef uvec2
45-
#undef mat4x3
4636
#undef nbl_glsl_MC_material_data_t
4737
using instance_data_t = nbl_glsl_ext_Mitsuba_Loader_instance_data_t;
4838
#endif
@@ -61,9 +51,6 @@ class CMitsubaLoader final : public asset::ISceneLoader
6151
void cacheTexture(SContext& ctx, uint32_t hierarchyLevel, const CElementTexture* texture, const CMitsubaMaterialCompilerFrontend::E_IMAGE_VIEW_SEMANTIC semantic);
6252
void cacheEmissionProfile(SContext& ctx, const CElementEmissionProfile* profile);
6353

64-
SContext::bsdf_type getBSDFtreeTraversal(SContext& ctx, const CElementBSDF* bsdf, const CElementEmitter* emitter, core::matrix4SIMD tform);
65-
SContext::bsdf_type genBSDFtreeTraversal(SContext& ctx, const CElementBSDF* bsdf);
66-
6754
template <typename Iter>
6855
core::smart_refctd_ptr<asset::ICPUDescriptorSet> createDS0(const SContext& _ctx, asset::ICPUPipelineLayout* _layout, const asset::material_compiler::CMaterialCompilerGLSLBackendCommon::result_t& _compResult, Iter meshBegin, Iter meshEnd);
6956
#endif

include/nbl/ext/MitsubaLoader/CMitsubaMaterialCompilerFrontend.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,6 @@ class CMitsubaMaterialCompilerFrontend
3333
EIVS_COUNT
3434
};
3535

36-
struct front_and_back_t
37-
{
38-
IRNode* front;
39-
IRNode* back;
40-
};
41-
4236
explicit CMitsubaMaterialCompilerFrontend(const SContext* _ctx) : m_loaderContext(_ctx) {}
4337

4438
front_and_back_t compileToIRTree(asset::material_compiler::IR* ir, const CElementBSDF* _bsdf);
@@ -57,8 +51,6 @@ class CMitsubaMaterialCompilerFrontend
5751
emission_profile_type getEmissionProfile(const CElementEmissionProfile* _element);
5852

5953
tex_ass_type getErrorTexture(const E_IMAGE_VIEW_SEMANTIC semantic) const;
60-
61-
IRNode* createIRNode(asset::material_compiler::IR* ir, const CElementBSDF* _bsdf);
6254
#endif
6355
};
6456

include/nbl/ext/MitsubaLoader/SContext.h

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,16 @@ struct SContext final
3232
// the `shape` will have to be `Type::SHAPEGROUP`
3333
shape_ass_type loadShapeGroup(const CElementShape* shape);
3434

35+
// Mitsuba XML Materials do not support emission from a BSDF node (i.e. emitter behind a coating or glass screen), its purely additive and cannot be backface emitting
36+
using material_t = asset::material_compiler3::CFrontendIR::typed_pointer_type<const asset::material_compiler3::CFrontendIR::CLayer>; // TODO: change to true IR
37+
material_t getMaterial(const CElementBSDF* bsdf, const CElementEmitter* frontFaceEmitter, const hlsl::float32_t3x3& iesProfileOrientation, const core::string& debugName, system::ISystem* debugFileWriter=nullptr);
38+
39+
inline void writeFrontendForestDot3(system::ISystem* system, const system::path& filepath)
40+
{
41+
asset::material_compiler3::CFrontendIR::SDotPrinter printer = {frontIR.get(),frontIR->getMaterials()};
42+
writeDot3File(system,filepath,printer);
43+
}
44+
3545
inline void transferMetadata()
3646
{
3747
meta->setGeometryCollectionMeta(std::move(shapeCache));
@@ -45,10 +55,23 @@ struct SContext final
4555
core::smart_refctd_ptr<asset::ICPUScene> scene;
4656

4757
private:
58+
using frontend_ir_t = asset::material_compiler3::CFrontendIR;
59+
using frontend_material_t = frontend_ir_t::typed_pointer_type<const frontend_ir_t::CLayer>;
60+
// not `frontend_ir_t::CEmitter` because the color factor gets multiplied in
61+
using frontend_emitter_t = frontend_ir_t::typed_pointer_type<const frontend_ir_t::CMul>;
62+
frontend_material_t genMaterial(const CElementBSDF* bsdf, system::ISystem* debugFileWriter);
63+
frontend_emitter_t getEmitter(const CElementEmitter* emitter, const hlsl::float32_t3x3& iesProfileOrientation, system::ISystem* debugFileWriter);
64+
frontend_emitter_t genEmitter(const CElementEmitter* emitter, system::ISystem* debugFileWriter);
65+
//
66+
void writeDot3File(system::ISystem* system, const system::path& filepath, frontend_ir_t::SDotPrinter& printer);
67+
4868
//
4969
core::unordered_map<const CElementShape*,CMitsubaMetadata::SGeometryCollectionMetaPair> shapeCache;
5070
//
5171
core::unordered_map<const CElementShape::ShapeGroup*,CMitsubaMetadata::SGeometryCollectionMetaPair> groupCache;
72+
//
73+
core::unordered_map<const CElementBSDF*,frontend_material_t> bsdfCache;
74+
core::unordered_map<const CElementEmitter*,frontend_emitter_t> emitterCache;
5275

5376
#if 0 // stuff that belongs in the Material Compiler backend
5477
//image, sampler
@@ -121,13 +144,15 @@ struct SContext final
121144
params.MinLod = 0.f;
122145
return params;
123146
}
124-
125-
//index of root node in IR
126-
using bsdf_type = const CMitsubaMaterialCompilerFrontend::front_and_back_t;
127-
//caches instr buffer instr-wise offset (.first) and instruction count (.second) for each bsdf node
128-
core::unordered_map<const CElementBSDF*, bsdf_type> instrStreamCache;
129147
#endif
130-
core::smart_refctd_ptr<asset::material_compiler3::CFrontendIR> frontIR;
148+
core::smart_refctd_ptr<frontend_ir_t> frontIR;
149+
// Common Debug Names
150+
enum class ECommonDebug : uint16_t
151+
{
152+
Albedo,
153+
Count
154+
};
155+
frontend_ir_t::obj_pool_type::typed_pointer_type<const frontend_ir_t::CDebugInfo> commonDebugNames[uint16_t(ECommonDebug::Count)];
131156
};
132157

133158
}

src/nbl/asset/material_compiler3/CFrontendIR.cpp

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -220,17 +220,42 @@ auto CFrontendIR::createNamedFresnel(const std::string_view name) -> typed_point
220220
return frH;
221221
}
222222

223-
void CFrontendIR::printDotGraph(std::ostringstream& str) const
223+
void CFrontendIR::SDotPrinter::operator()(std::ostringstream& str)
224224
{
225225
str << "digraph {\n";
226+
227+
auto drainExprStack = [&]()->void
228+
{
229+
while (!exprStack.empty())
230+
{
231+
const auto entry = exprStack.top();
232+
exprStack.pop();
233+
const auto nodeID = m_ir->getNodeID(entry);
234+
str << "\n\t" << m_ir->getLabelledNodeID(entry);
235+
const auto* node = m_ir->getObjectPool().deref(entry);
236+
const auto childCount = node->getChildCount();
237+
if (childCount)
238+
{
239+
for (auto childIx=0; childIx<childCount; childIx++)
240+
{
241+
const auto childHandle = node->getChildHandle(childIx);
242+
if (const auto child=m_ir->getObjectPool().deref(childHandle); child)
243+
{
244+
str << "\n\t" << nodeID << " -> " << m_ir->getNodeID(childHandle) << "[label=\"" << node->getChildName_impl(childIx) << "\"]";
245+
const auto visited = visitedNodes.find(childHandle);
246+
if (visited!=visitedNodes.end())
247+
continue;
248+
exprStack.push(childHandle);
249+
visitedNodes.insert(childHandle);
250+
}
251+
}
252+
}
253+
// special printing
254+
node->printDot(str,nodeID);
255+
}
256+
};
257+
drainExprStack();
226258

227-
core::unordered_set<typed_pointer_type<const INode>> visitedNodes;
228-
// should probably size it better, if I knew total node count allocated or live
229-
visitedNodes.reserve(m_rootNodes.size()<<3);
230-
// TODO: track layering depth and indent accordingly?
231-
// assign in reverse because we want materials to print in order
232-
core::vector<typed_pointer_type<const CLayer>> layerStack(m_rootNodes.rbegin(),m_rootNodes.rend());
233-
core::stack<typed_pointer_type<const IExprNode>> exprStack;
234259
while (!layerStack.empty())
235260
{
236261
const auto layerHandle = layerStack.back();
@@ -240,22 +265,22 @@ void CFrontendIR::printDotGraph(std::ostringstream& str) const
240265
if (visited!=visitedNodes.end())
241266
continue;
242267
visitedNodes.insert(layerHandle);
243-
const auto* layerNode = getObjectPool().deref(layerHandle);
268+
const auto* layerNode = m_ir->getObjectPool().deref(layerHandle);
244269
//
245-
const auto layerID = getNodeID(layerHandle);
246-
str << "\n\t" << getLabelledNodeID(layerHandle);
270+
const auto layerID = m_ir->getNodeID(layerHandle);
271+
str << "\n\t" << m_ir->getLabelledNodeID(layerHandle);
247272
//
248273
if (layerNode->coated)
249274
{
250-
str << "\n\t" << layerID << " -> " << getNodeID(layerNode->coated) << "[label=\"coats\"]\n";
275+
str << "\n\t" << layerID << " -> " << m_ir->getNodeID(layerNode->coated) << "[label=\"coats\"]\n";
251276
layerStack.push_back(layerNode->coated);
252277
}
253278
auto pushExprRoot = [&](const typed_pointer_type<const IExprNode> root, const std::string_view edgeLabel)->void
254279
{
255280
if (!root)
256281
return;
257282
// print the link from the layer to the expression
258-
str << "\n\t" << layerID << " -> " << getNodeID(root) << "[label=\"" << edgeLabel << "\"]";
283+
str << "\n\t" << layerID << " -> " << m_ir->getNodeID(root) << "[label=\"" << edgeLabel << "\"]";
259284
// but not the expression again
260285
const auto visited = visitedNodes.find(root);
261286
if (visited!=visitedNodes.end())
@@ -266,33 +291,7 @@ void CFrontendIR::printDotGraph(std::ostringstream& str) const
266291
pushExprRoot(layerNode->brdfTop,"Top BRDF");
267292
pushExprRoot(layerNode->btdf,"BTDF");
268293
pushExprRoot(layerNode->brdfBottom,"Bottom BRDF");
269-
while (!exprStack.empty())
270-
{
271-
const auto entry = exprStack.top();
272-
exprStack.pop();
273-
const auto nodeID = getNodeID(entry);
274-
str << "\n\t" << getLabelledNodeID(entry);
275-
const auto* node = getObjectPool().deref(entry);
276-
const auto childCount = node->getChildCount();
277-
if (childCount)
278-
{
279-
for (auto childIx=0; childIx<childCount; childIx++)
280-
{
281-
const auto childHandle = node->getChildHandle(childIx);
282-
if (const auto child=getObjectPool().deref(childHandle); child)
283-
{
284-
str << "\n\t" << nodeID << " -> " << getNodeID(childHandle) << "[label=\"" << node->getChildName_impl(childIx) << "\"]";
285-
const auto visited = visitedNodes.find(childHandle);
286-
if (visited!=visitedNodes.end())
287-
continue;
288-
exprStack.push(childHandle);
289-
visitedNodes.insert(childHandle);
290-
}
291-
}
292-
}
293-
// special printing
294-
node->printDot(str,nodeID);
295-
}
294+
drainExprStack();
296295
}
297296

298297
// TODO: print image views

0 commit comments

Comments
 (0)