@@ -40,6 +40,10 @@ namespace nbl::asset::material_compiler3
40
40
// polygonization. Using PN-Triangles/displacement would be the optimal solution here.
41
41
class CFrontendIR : public CNodePool
42
42
{
43
+ protected:
44
+ template <typename T>
45
+ using _TypedHandle = CNodePool::TypedHandle<T>;
46
+
43
47
public:
44
48
// constructor
45
49
inline core::smart_refctd_ptr<CFrontendIR> create (const uint8_t chunkSizeLog2=19 , const uint8_t maxNodeAlignLog2=4 , refctd_pmr_t && _pmr={})
@@ -73,7 +77,7 @@ class CFrontendIR : public CNodePool
73
77
{
74
78
inline operator bool () const
75
79
{
76
- for (uint8_t i=o ; i<Count; i++)
80
+ for (uint8_t i=0 ; i<Count; i++)
77
81
if (!params[i])
78
82
return false ;
79
83
return true ;
@@ -98,11 +102,10 @@ class CFrontendIR : public CNodePool
98
102
public:
99
103
CNodePool::TypedHandle<CNodePool::CDebugInfo> debugInfo;
100
104
};
101
- template <typename T> requires std::is_base_of_v<INode,std::remove_cv_t <T>>
102
- using TypedHandle = CNodePool::TypedHandle <T>;
105
+ template <typename T> requires std::is_base_of_v<INode,std::remove_const_t <T>>
106
+ using TypedHandle = _TypedHandle <T>;
103
107
104
108
class IExprNode ;
105
-
106
109
// All layers are modelled as coatings, most combinations are not feasible and what combos are feasible depend on the compiler backend you use.
107
110
// Do not use Coatings for things which can be achieved with linear blends! (e.g. alpha transparency)
108
111
class CLayer final : public INode
@@ -122,30 +125,31 @@ class CFrontendIR : public CNodePool
122
125
// A null BRDF will not produce reflections, while a null BTDF will not allow any transmittance.
123
126
// The laws of BSDFs require reciprocity so we can only have one BTDF, but they allow separate/different BRDFs
124
127
// Concrete example, think Vantablack stuck to a Aluminimum foil on the other side.
125
- TypedHandle <IExprNode> brdfTop;
126
- TypedHandle <IExprNode> btdf;
128
+ _TypedHandle <IExprNode> brdfTop;
129
+ _TypedHandle <IExprNode> btdf;
127
130
// when dealing with refractice indices, we expect the `brdfTop` and `brdfBottom` to be in sync (reciprocals of each other)
128
- TypedHandle <IExprNode> brdfBottom;
131
+ _TypedHandle <IExprNode> brdfBottom;
129
132
// The layer below us, if in the stack there's a layer with a null BTDF, we reserve the right to split up the material into two separate
130
133
// materials, one for the front and one for the back face in the final IR. Everything between the first and last null BTDF will get discarded.
131
- TypedHandle <CLayer> coated;
134
+ _TypedHandle <CLayer> coated;
132
135
};
133
136
134
- //
137
+ //
135
138
class IExprNode : public INode
136
139
{
137
140
public:
138
141
// Only sane child count allowed
139
142
virtual uint8_t getChildCount () const = 0;
140
- inline TypedHandle <IExprNode> getChildHandle (const uint8_t ix)
143
+ inline _TypedHandle <IExprNode> getChildHandle (const uint8_t ix)
141
144
{
142
145
if (ix<getChildCount ())
143
146
return getChildHandle_impl (ix);
144
147
return {};
145
148
}
146
- inline TypedHandle <const IExprNode> getChildHandle (const uint8_t ix) const
149
+ inline _TypedHandle <const IExprNode> getChildHandle (const uint8_t ix) const
147
150
{
148
- return reinterpret_cast <const TypedHandle<const IExprNode>&>(const_cast <IExprNode*>(this )->getChildHandle (ix));
151
+ auto retval = const_cast <IExprNode*>(this )->getChildHandle (ix);
152
+ return retval;
149
153
}
150
154
151
155
// A "contributor" of a term to the lighting equation: a BxDF (reflection or tranmission) or Emitter term
@@ -161,8 +165,6 @@ class CFrontendIR : public CNodePool
161
165
162
166
protected:
163
167
friend class CFrontendIR ;
164
- //
165
- virtual TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const = 0;
166
168
// default is no special checks beyond the above
167
169
struct SInvalidCheckArgs
168
170
{
@@ -172,15 +174,14 @@ class CFrontendIR : public CNodePool
172
174
// there's space for 7 more bools
173
175
};
174
176
virtual inline bool invalid (const SInvalidCheckArgs&) const {return false ;}
177
+ virtual _TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const = 0;
175
178
};
179
+
176
180
// ! Base class for leaf node
177
181
class IExprLeaf : public IExprNode
178
182
{
179
183
public:
180
184
inline uint8_t getChildCount () const override final {return 0 ;}
181
-
182
- protected:
183
- inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override final {return {};}
184
185
};
185
186
186
187
// ! Base class for leaf node quantities which contribute additively to the Lighting Integral
@@ -246,7 +247,7 @@ class CFrontendIR : public CNodePool
246
247
std::construct_at (reinterpret_cast <SCreationParams<Count>*>(this +1 ),std::move (params));
247
248
}
248
249
249
- inline operator bool () const {return !invalid (nullptr ,{ });}
250
+ inline operator bool () const {return !invalid (SInvalidCheckArgs{. pool = nullptr ,. logger = nullptr });}
250
251
251
252
protected:
252
253
inline ~CSpectralVariable ()
@@ -274,7 +275,7 @@ class CFrontendIR : public CNodePool
274
275
class IUnaryOp : public IExprNode
275
276
{
276
277
protected:
277
- inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) override final {return child;}
278
+ inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override final {return child;}
278
279
279
280
public:
280
281
inline uint8_t getChildCount () const override final {return 1 ;}
@@ -284,7 +285,7 @@ class CFrontendIR : public CNodePool
284
285
class IBinOp : public IExprNode
285
286
{
286
287
protected:
287
- inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) override final {return ix ? rhs:lhs;}
288
+ inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override final {return ix ? rhs:lhs;}
288
289
289
290
public:
290
291
inline uint8_t getChildCount () const override final {return 2 ;}
@@ -333,7 +334,7 @@ class CFrontendIR : public CNodePool
333
334
class CThinInfiniteScatterCorrection final : public IExprNode
334
335
{
335
336
protected:
336
- inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) override final {return ix ? (ix!=1 ? extinction:transmittance):reflection ;}
337
+ inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override final {return ix ? (ix!=1 ? extinction:transmittance):reflectance ;}
337
338
338
339
public:
339
340
inline uint8_t getChildCount () const override final {return 3 ;}
@@ -374,7 +375,7 @@ class CFrontendIR : public CNodePool
374
375
// TODO: semantic flags/metadata (symmetries of the profile)
375
376
376
377
protected:
377
- inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) override {return radiance;}
378
+ inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override {return radiance;}
378
379
NBL_API bool invalid (const SInvalidCheckArgs& args) const override ;
379
380
};
380
381
// ! Special nodes meant to be used as `CMul::rhs`, as for the `N`, they use the normal used by the Leaf ContributorLeafs in its MUL node relative subgraph.
@@ -402,7 +403,7 @@ class CFrontendIR : public CNodePool
402
403
TypedHandle<CSpectralVariable> perpTransparency = {};
403
404
404
405
protected:
405
- inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) override {return perpTransparency;}
406
+ inline TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override {return perpTransparency;}
406
407
NBL_API bool invalid (const SInvalidCheckArgs& args) const override ;
407
408
};
408
409
// The "oriented" in the Etas means from frontface to backface, so there's no need to reciprocate them when creating matching BTDF for BRDF
@@ -432,11 +433,9 @@ class CFrontendIR : public CNodePool
432
433
// @kept_secret TODO: Thin Film Interference Fresnel
433
434
// ! Basic BxDF nodes
434
435
// Every BxDF leaf node is supposed to pass WFT test, color and extinction is added on later via multipliers
435
- class IBxDF : public IContributorLeaf
436
+ class IBxDF : public IContributor
436
437
{
437
- public
438
- inline uint8_t getChildCount () const override final {return 0 ;}
439
-
438
+ public:
440
439
// Why are all of these kept together and forced to fetch from the same UV ?
441
440
// Because they're supposed to be filtered together with the knowledge of the NDF
442
441
// TODO: should really be 5 parameters (2+3) cause of rotatable anisotropic roughness
@@ -524,11 +523,10 @@ class CFrontendIR : public CNodePool
524
523
};
525
524
526
525
// Each material comes down to this
527
- inline std::span<const TypedHandle<const CLayer>> getMaterials () const {return m_rootNodes;}
528
- inline std::span<const TypedHandle<CLayer>> getMaterials () {return m_rootNodes;}
529
- inline bool addMaterial (const TypedHandle<const CLayer>& rootNode)
526
+ inline std::span<const TypedHandle<const CLayer>> getMaterials () {return m_rootNodes;}
527
+ inline bool addMaterial (const TypedHandle<const CLayer>& rootNode, system::logger_opt_ptr logger)
530
528
{
531
- if (valid (rootNode))
529
+ if (valid (rootNode,logger ))
532
530
m_rootNodes.push_back (rootNode);
533
531
}
534
532
@@ -552,20 +550,20 @@ class CFrontendIR : public CNodePool
552
550
protected:
553
551
using CNodePool::CNodePool;
554
552
555
- core::vector<TypedHandle<CLayer>> m_rootNodes;
553
+ core::vector<TypedHandle<const CLayer>> m_rootNodes;
556
554
};
557
555
558
556
inline bool CFrontendIR::valid (const TypedHandle<const CLayer> rootHandle, system::logger_opt_ptr logger) const
559
557
{
560
- constexpr auto ELL_ERROR = ILogger::E_LOG_LEVEL::ELL_ERROR;
558
+ constexpr auto ELL_ERROR = system:: ILogger::E_LOG_LEVEL::ELL_ERROR;
561
559
562
560
core::stack<const CLayer*> layerStack;
563
561
auto pushLayer = [&](const TypedHandle<const CLayer> layerHandle)->bool
564
562
{
565
563
const auto * layer = deref (layerHandle);
566
564
if (!layer)
567
565
{
568
- logger.log (" Layer node %u of type %s not a `CLayer` node!" ,ELL_ERROR,layerHandle.untyped .value ,getTypeName (layerHandle).c_str ());
566
+ logger.log (" Layer node %u of type %s not a `CLayer` node!" ,ELL_ERROR,layerHandle.untyped .value ,getTypeName (layerHandle).data ());
569
567
return false ;
570
568
}
571
569
layerStack.push (layer);
@@ -595,7 +593,7 @@ inline bool CFrontendIR::valid(const TypedHandle<const CLayer> rootHandle, syste
595
593
const auto * root = deref (exprRoot);
596
594
if (!root)
597
595
{
598
- logger.log (" Node %u is not an Expression Node, it's %s" ,ELL_ERROR,exprRoot.untyped .value ,getTypeName (exprRoot).c_str ());
596
+ logger.log (" Node %u is not an Expression Node, it's %s" ,ELL_ERROR,exprRoot.untyped .value ,getTypeName (exprRoot).data ());
599
597
return false ;
600
598
}
601
599
//
@@ -607,15 +605,15 @@ inline bool CFrontendIR::valid(const TypedHandle<const CLayer> rootHandle, syste
607
605
const IExprNode::SInvalidCheckArgs invalidCheckArgs = {.pool =this ,.logger =logger,.isBTDF =isBTDF};
608
606
while (!exprStack.empty ())
609
607
{
610
- const StackEntry entry = stck. peek ();
611
- stck .pop ();
608
+ const StackEntry entry = exprStack. top ();
609
+ exprStack .pop ();
612
610
const auto * node = entry.node ;
613
611
const auto nodeType = node->getType ();
614
612
const bool nodeIsMul = nodeType==IExprNode::Type::Mul;
615
613
const bool nodeIsAdd = nodeType==IExprNode::Type::Add;
616
614
const auto childCount = node->getChildCount ();
617
615
bool takeOverContribSlot = true ; // first add child can do this
618
- for (auto childIx=0 ; chilxId <childCount childIx++)
616
+ for (auto childIx=0 ; childIx <childCount; childIx++)
619
617
{
620
618
const auto childHandle = node->getChildHandle (childIx);
621
619
if (const auto child=deref (childHandle); child)
@@ -626,7 +624,7 @@ inline bool CFrontendIR::valid(const TypedHandle<const CLayer> rootHandle, syste
626
624
{
627
625
if (child->getType ()==IExprNode::Type::Contributor)
628
626
{
629
- logger.log (" Contibutor node %u of type %s not allowed in this subtree!" ,ELL_ERROR,childHandle,getTypeName (childHandle).c_str ());
627
+ logger.log (" Contibutor node %u of type %s not allowed in this subtree!" ,ELL_ERROR,childHandle,getTypeName (childHandle).data ());
630
628
return false ;
631
629
}
632
630
newEntry.contribSlot = MaxContributors;
@@ -645,21 +643,21 @@ inline bool CFrontendIR::valid(const TypedHandle<const CLayer> rootHandle, syste
645
643
logger.log (" Expression too complex, more than %d contributors encountered" ,ELL_ERROR,MaxContributors);
646
644
return false ;
647
645
}
648
- stck .push (newEntry);
646
+ exprStack .push (newEntry);
649
647
}
650
648
else if (childHandle)
651
649
{
652
650
logger.log (
653
651
" Node %u of type %s has a %u th child %u which doesn't cast to `IExprNode`, its type is %s instead!" ,ELL_ERROR,
654
- entry.handle .value ,node->getTypeName ().c_str (),childIx,childHandle,getTypeName (childHandle).c_str ()
652
+ entry.handle .untyped . value ,node->getTypeName ().data (),childIx,childHandle,getTypeName (childHandle).data ()
655
653
);
656
654
return false ;
657
655
}
658
656
}
659
657
// check only after we know all children are OK
660
658
if (node->invalid (invalidCheckArgs))
661
659
{
662
- logger.log (" Node %u of type %s is invalid!" ,ELL_ERROR,entry.handle .value ,node->getTypeName ().c_str ());
660
+ logger.log (" Node %u of type %s is invalid!" ,ELL_ERROR,entry.handle .untyped . value ,node->getTypeName ().data ());
663
661
return false ;
664
662
}
665
663
if (entry.contribSlot <MaxContributors)
@@ -675,7 +673,7 @@ inline bool CFrontendIR::valid(const TypedHandle<const CLayer> rootHandle, syste
675
673
};
676
674
while (!layerStack.empty ())
677
675
{
678
- const auto * layer = deref ( layerStack.peek () );
676
+ const auto * layer = layerStack.top ( );
679
677
layerStack.pop ();
680
678
if (layer->coated && !pushLayer (layer->coated ))
681
679
{
@@ -686,15 +684,15 @@ inline bool CFrontendIR::valid(const TypedHandle<const CLayer> rootHandle, syste
686
684
{
687
685
logger.log (
688
686
" At least one BRDF in the Layer is required, Top is %u of type %s and Bottom is %u of type %s" ,ELL_ERROR,
689
- layer->brdfTop ,getTypeName (layer->brdfTop ).c_str (),layer->brdfBottom ,getTypeName (layer->brdfBottom ).c_str ()
687
+ layer->brdfTop ,getTypeName (layer->brdfTop ).data (),layer->brdfBottom ,getTypeName (layer->brdfBottom ).data ()
690
688
);
691
689
return false ;
692
690
}
693
- if (!pushExpression (layer->brdfTop ))
691
+ if (!validateExpression (layer->brdfTop , false ))
694
692
return false ;
695
- if (!pushExpression (layer->btdf ))
693
+ if (!validateExpression (layer->btdf , true ))
696
694
return false ;
697
- if (!pushExpression (layer->brdfBottom ))
695
+ if (!validateExpression (layer->brdfBottom , false ))
698
696
return false ;
699
697
}
700
698
return true ;
0 commit comments