@@ -289,16 +289,19 @@ class CFrontendIR : public CNodePool
289289
290290 enum class Semantics : uint8_t
291291 {
292+ NoneUndefined = 0 ,
292293 // 3 knots, their wavelengths are implied and fixed at color primaries
293- Fixed3_SRGB = 0 ,
294- Fixed3_DCI_P3 = 1 ,
295- Fixed3_BT2020 = 2 ,
296- Fixed3_AdobeRGB = 3 ,
297- Fixed3_AcesCG = 4 ,
294+ Fixed3_SRGB = 1 ,
295+ Fixed3_DCI_P3 = 2 ,
296+ Fixed3_BT2020 = 3 ,
297+ Fixed3_AdobeRGB = 4 ,
298+ Fixed3_AcesCG = 5 ,
298299 // Ideas: each node is described by (wavelength,value) pair
299300 // PairsLinear = 5, // linear interpolation
300301 // PairsLogLinear = 5, // linear interpolation in wavelenght log space
301302 };
303+
304+ //
302305 template <uint8_t Count>
303306 struct SCreationParams
304307 {
@@ -312,46 +315,74 @@ class CFrontendIR : public CNodePool
312315 template <bool Enable=true > requires (Enable==(Count>1 ))
313316 const Semantics& getSemantics() const {return const_cast <const Semantics&>(const_cast <SCreationParams<Count>*>(this )->getSemantics ());}
314317 };
318+ //
315319 template <uint8_t Count>
316- static inline uint32_t calc_size ( const SCreationParams<Count>&)
320+ inline CSpectralVariable ( SCreationParams<Count>&& params )
317321 {
318- return sizeof (CSpectralVariable)+sizeof (SCreationParams<Count>);
322+ // back up the count
323+ params.knots .params [0 ].padding [1 ] = Count;
324+ // set it correctly for monochrome
325+ if constexpr (Count==1 )
326+ params.knots .params [0 ].padding [2 ] = static_cast <uint8_t >(Semantics::NoneUndefined);
327+ else
328+ {
329+ assert (params.getSemantics ()!=Semantics::NoneUndefined);
330+ }
331+ std::construct_at (reinterpret_cast <SCreationParams<Count>*>(this +1 ),std::move (params));
319332 }
320-
333+
334+ // encapsulation due to padding abuse
335+ inline uint8_t & uvSlot () {return pWonky ()->knots .uvSlot ();}
336+ inline const uint8_t & uvSlot () const {return pWonky ()->knots .uvSlot ();}
337+
338+ // these getters are immutable
321339 inline uint8_t getKnotCount () const
322340 {
323341 static_assert (sizeof (SParameter::padding)>1 );
324342 return paramsBeginPadding ()[1 ];
325343 }
326- inline uint32_t getSize () const override
344+ inline Semantics getSemantics () const
327345 {
328- return sizeof (CSpectralVariable)+sizeof (SCreationParams<1 >)+(getKnotCount ()-1 )*sizeof (SParameter);
346+ static_assert (sizeof (SParameter::padding)>2 );
347+ const auto retval = static_cast <Semantics>(paramsBeginPadding ()[2 ]);
348+ assert ((getKnotCount ()==1 )==(retval==Semantics::NoneUndefined));
349+ return retval;
350+ }
351+
352+ //
353+ inline SParameter* getParam (const uint8_t i)
354+ {
355+ if (i<getKnotCount ())
356+ return &pWonky ()->knots .params [i];
357+ return nullptr ;
329358 }
359+ inline const SParameter* getParam (const uint8_t i) const {return const_cast <const SParameter*>(const_cast <CSpectralVariable*>(this )->getParam (i));}
330360
361+ //
331362 template <uint8_t Count>
332- inline CSpectralVariable ( SCreationParams<Count>&& params )
363+ static inline uint32_t calc_size ( const SCreationParams<Count>&)
333364 {
334- // back up the count
335- params.knots .params [0 ].padding [1 ] = Count;
336- std::construct_at (reinterpret_cast <SCreationParams<Count>*>(this +1 ),std::move (params));
365+ return sizeof (CSpectralVariable)+sizeof (SCreationParams<Count>);
366+ }
367+ inline uint32_t getSize () const override
368+ {
369+ return sizeof (CSpectralVariable)+sizeof (SCreationParams<1 >)+(getKnotCount ()-1 )*sizeof (SParameter);
337370 }
338371
339372 inline operator bool () const {return !invalid (SInvalidCheckArgs{.pool =nullptr ,.logger =nullptr });}
340373
341374 protected:
342375 inline ~CSpectralVariable ()
343376 {
344- auto pWonky = reinterpret_cast <SCreationParams<1 >*>(this +1 );
345- std::destroy_n (pWonky->knots .params ,getKnotCount ());
377+ std::destroy_n (pWonky ()->knots .params ,getKnotCount ());
346378 }
347379
348380 inline _TypedHandle<IExprNode> getChildHandle_impl (const uint8_t ix) const override {return {};}
349381 inline bool invalid (const SInvalidCheckArgs& args) const override
350382 {
351383 const auto knotCount = getKnotCount ();
352- auto pWonky = reinterpret_cast <const SCreationParams<2 >*>(this +1 );
353384 // non-monochrome spectral variable
354- if (const auto semantic=pWonky-> getSemantics (); knotCount>1 )
385+ if (const auto semantic=getSemantics (); knotCount>1 )
355386 switch (semantic)
356387 {
357388 case Semantics::Fixed3_SRGB: [[fallthrough]];
@@ -370,7 +401,7 @@ class CFrontendIR : public CNodePool
370401 return true ;
371402 }
372403 for (auto i=0u ; i<knotCount; i++)
373- if (!pWonky-> knots . params [i] )
404+ if (!* getParam (i) )
374405 {
375406 args.logger .log (" Knot %u parameters invalid" ,system::ILogger::ELL_ERROR,i);
376407 return true ;
@@ -382,7 +413,9 @@ class CFrontendIR : public CNodePool
382413 NBL_API void printDot (std::ostringstream& sstr, const core::string& selfID) const override ;
383414
384415 private:
385- const uint8_t * paramsBeginPadding () const {return reinterpret_cast <const SCreationParams<1 >*>(this +1 )->knots .params [0 ].padding ;}
416+ SCreationParams<1 >* pWonky () {return reinterpret_cast <SCreationParams<1 >*>(this +1 );}
417+ const SCreationParams<1 >* pWonky () const {return reinterpret_cast <const SCreationParams<1 >*>(this +1 );}
418+ const uint8_t * paramsBeginPadding () const {return pWonky ()->knots .params [0 ].padding ; }
386419 };
387420 //
388421 class IUnaryOp : public IExprNode
0 commit comments