yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
551d0c365
master
1#ifndef SLANG_CORE_RTTI_INFO_H 2#define SLANG_CORE_RTTI_INFO_H 3 4#include "slang-basic.h" 5#include "slang-dictionary.h" 6#include "slang-list.h" 7#include "slang-memory-arena.h" 8 9namespace Slang 10{ 11 12struct RttiInfo ; 13struct RttiTypeFuncsMap ; 14 15struct RttiTypeFuncs 16{ 17typedef void ( 18* CtorArray )(RttiTypeFuncsMap * typeMap ,const RttiInfo * rttiInfo ,void * dst ,Index count ); 19typedef void ( 20* DtorArray )(RttiTypeFuncsMap * typeMap ,const RttiInfo * rttiInfo ,void * dst ,Index count ); 21typedef void (* CopyArray )( 22RttiTypeFuncsMap * typeMap , 23const RttiInfo * rttiInfo , 24void * dst , 25const void * src , 26Index count ); 27 28bool isValid ()const {return ctorArray && dtorArray && copyArray ; } 29 30static RttiTypeFuncs makeEmpty () {return RttiTypeFuncs {nullptr ,nullptr ,nullptr }; } 31 32CtorArray ctorArray ; 33DtorArray dtorArray ; 34CopyArray copyArray ; 35}; 36 37/* Provides a mechanism to map a type to it's RttiFuncs */ 38struct RttiTypeFuncsMap 39{ 40/// For a given type returns the funcs. 41/// If not found returns funcs that return 'isValid' as false. 42RttiTypeFuncs getFuncsForType (const RttiInfo * rttiInfo ); 43 44/// Add funcs for a type 45void add (const RttiInfo * rttiInfo ,const RttiTypeFuncs & funcs ); 46 47protected : 48Dictionary < const RttiInfo * , RttiTypeFuncs > m_map ; 49}; 50 51/* Template to get funcs for any arbitrary type */ 52template < typename T > 53struct GetRttiTypeFuncs 54{ 55static void ctorArray ( 56RttiTypeFuncsMap * typeMap , 57const RttiInfo * rttiInfo , 58void * in , 59Index count ) 60{ 61SLANG_UNUSED ( typeMap ); 62SLANG_UNUSED ( rttiInfo ); 63T * dst = ( T * ) in ; 64for ( Index i = 0 ; i < count ; ++ i ) 65{ 66new ( dst + i ) T ; 67} 68} 69static void dtorArray ( 70RttiTypeFuncsMap * typeMap , 71const RttiInfo * rttiInfo , 72void * in , 73Index count ) 74{ 75SLANG_UNUSED ( typeMap ); 76SLANG_UNUSED ( rttiInfo ); 77T * dst = ( T * ) in ; 78for ( Index i = 0 ; i < count ; ++ i ) 79{ 80( dst + i ) -> ~ T (); 81} 82} 83static void copyArray ( 84RttiTypeFuncsMap * typeMap , 85const RttiInfo * rttiInfo , 86void * inDst , 87const void * inSrc , 88Index count ) 89{ 90SLANG_UNUSED ( rttiInfo ); 91SLANG_UNUSED ( typeMap ); 92 93T * dst = ( T * ) inDst ; 94const T * src = ( T * ) inSrc ; 95for ( Index i = 0 ; i < count ; ++ i ) 96{ 97dst [ i ] = src [ i ]; 98} 99} 100static RttiTypeFuncs getFuncs () 101{ 102RttiTypeFuncs funcs ; 103funcs .copyArray = & copyArray ; 104funcs .dtorArray = & dtorArray ; 105funcs .ctorArray = & ctorArray ; 106return funcs ; 107} 108}; 109 110/* An implementation of funcs, for a type that is POD *and* can be zero initialized. 111Built in types generally fall into this catagory, but so do raw pointers and other types, 112such as structs that only contain "ZeroPod" types */ 113template < typename T > 114struct GetRttiTypeFuncsForZeroPod 115{ 116static void ctorArray ( 117RttiTypeFuncsMap * typeMap , 118const RttiInfo * rttiInfo , 119void * dst , 120Index count ) 121{ 122SLANG_UNUSED ( typeMap ); 123SLANG_UNUSED ( rttiInfo ); 124:: memset ( dst , 0 , sizeof ( T ) * count ); 125} 126static void dtorArray ( 127RttiTypeFuncsMap * typeMap , 128const RttiInfo * rttiInfo , 129void * dst , 130Index count ) 131{ 132SLANG_UNUSED ( typeMap ); 133SLANG_UNUSED ( rttiInfo ); 134SLANG_UNUSED ( dst ); 135SLANG_UNUSED ( count ); 136} 137static void copyArray ( 138RttiTypeFuncsMap * typeMap , 139const RttiInfo * rttiInfo , 140void * dst , 141const void * src , 142Index count ) 143{ 144SLANG_UNUSED ( typeMap ); 145SLANG_UNUSED ( rttiInfo ); 146:: memcpy ( dst , src , sizeof ( T ) * count ); 147} 148 149static RttiTypeFuncs getFuncs () 150{ 151RttiTypeFuncs funcs ; 152funcs .copyArray = & copyArray ; 153funcs .dtorArray = & dtorArray ; 154funcs .ctorArray = & ctorArray ; 155return funcs ; 156} 157}; 158 159struct RttiInfo 160{ 161typedef uint8_t AlignmentType; 162typedef uint16_t SizeType ; 163 164enum class Kind : uint8_t 165{ 166Invalid , 167I32, 168U32, 169I64, 170U64, 171F32, 172F64, 173Bool, 174String, 175UnownedStringSlice, 176Ptr, 177RefPtr, 178FixedArray, 179Struct, 180Other, 181Enum, 182List, 183Dictionary, 184Optional, 185CountOf, 186}; 187 188Kind m_kind; 189AlignmentType m_alignment; 190SizeType m_size; 191 192void init( Kind kind , size_t alignment , size_t size ) 193{ 194m_kind = kind ; 195m_alignment = AlignmentType( alignment ); 196m_size = SizeType( size ); 197} 198 199template < typename T > 200void init ( Kind kind ) 201{ 202init ( kind , alignof( T ), sizeof ( T )); 203} 204 205/// Allocate memory for RttiInfo types. 206/// Is thread safe, and doesn't require the memory to be freed explicitly 207/// Will be freed at shutdown (via global dtor) 208static void * allocate ( size_t size ); 209/// Will free up any allocations. Can only be called at shutdown, and there are guarenteed no 210/// uses of RttiInfo - otherwise contents may be undefined. NOTE! Memory *will* be freed with 211/// final dtors, but if memory check functions are used they can report this memory. 212static void deallocateAll (); 213 214static bool isIntegral ( RttiInfo :: Kind kind ) 215{ 216return Index ( kind ) >= Index ( RttiInfo :: Kind :: I32 ) && 217Index ( kind ) <= Index ( RttiInfo :: Kind :: U64 ); 218} 219static bool isFloat ( RttiInfo :: Kind kind ) 220{ 221return kind == RttiInfo :: Kind :: F32 || kind == RttiInfo :: Kind :: F64 ; 222} 223static bool isBuiltIn ( RttiInfo :: Kind kind ) 224{ 225return Index ( kind ) >= Index ( RttiInfo :: Kind :: I32 ) && 226Index ( kind ) <= Index ( RttiInfo :: Kind :: Bool ); 227} 228static bool isNamed ( RttiInfo :: Kind kind ) 229{ 230return Index ( kind ) >= Index ( RttiInfo :: Kind :: Struct ) && 231Index ( kind ) <= Index ( RttiInfo :: Kind :: Enum ); 232} 233 234bool isIntegral () const { return isIntegral ( m_kind ); } 235bool isFloat () const { return isFloat ( m_kind ); } 236bool isBuiltIn () const { return isBuiltIn ( m_kind ); } 237bool isNamed () const { return isNamed ( m_kind ); } 238 239static void append ( const RttiInfo * info , StringBuilder & out ); 240 241static const RttiInfo g_basicTypes [ Index ( Kind :: CountOf )]; 242}; 243 244// Can combine into flags on a field. Could store default value with a field, 245// but this works fine for most purposes 246enum class RttiDefaultValue : uint8_t 247{ 248Normal , ///< Zero for integral/float types/false for bool 249One , 250MinusOne , 251 252Mask = 0x7 , 253}; 254 255struct NamedRttiInfo : public RttiInfo 256{ 257const char * m_name ; ///< Name 258}; 259 260struct StructRttiInfo : public NamedRttiInfo 261{ 262typedef uint8_t Flags ; 263struct Flag 264{ 265enum Enum : Flags 266{ 267// We use low bits for 'RttiDefaultValue' value 268Optional = 0x8 , 269}; 270}; 271 272struct Field 273{ 274const char * m_name; ///< Name of this field 275const RttiInfo * m_type; ///< The type of this field 276uint32_t m_offset; ///< Offset from object type in bytes 277Flags m_flags; ///< Field flags 278}; 279 280const StructRttiInfo * m_super ; ///< Super class or nullptr if not defined 281 282Index m_fieldCount ; ///< Amount of fields 283const Field * m_fields ; ///< Fields 284bool m_ignoreUnknownFieldsInJson = false; 285}; 286 287struct EnumRttiInfo : public NamedRttiInfo 288{ 289// TODO(JS): 290}; 291 292SLANG_FORCE_INLINE StructRttiInfo :: Flags combine ( 293StructRttiInfo :: Flags flags , 294RttiDefaultValue defaultValue ) 295{ 296return StructRttiInfo :: Flags ( defaultValue ) | flags ; 297} 298 299struct OptionalRttiInfo : public RttiInfo 300{ 301const RttiInfo * m_elementType ; 302uint32_t m_valueOffset ; 303}; 304 305struct ListRttiInfo : public RttiInfo 306{ 307const RttiInfo * m_elementType ; 308}; 309 310struct DictionaryRttiInfo : public RttiInfo 311{ 312const RttiInfo * m_keyType ; 313const RttiInfo * m_valueType ; 314}; 315 316struct PtrRttiInfo : public RttiInfo 317{ 318const RttiInfo * m_targetType ; 319}; 320 321struct RefPtrRttiInfo : public RttiInfo 322{ 323const RttiInfo * m_targetType ; 324}; 325 326struct FixedArrayRttiInfo : public RttiInfo 327{ 328const RttiInfo * m_elementType ; 329size_t m_elementCount ; 330}; 331 332struct OtherRttiInfo : public NamedRttiInfo 333{ 334typedef bool ( * IsDefaultFunc )( const RttiInfo * rttiInfo , const void * in ); 335IsDefaultFunc m_isDefaultFunc ; 336RttiTypeFuncs m_typeFuncs ; 337}; 338 339// The default is to just get the info from a global held inside the type. 340template < typename T > 341struct GetRttiInfo 342{ 343SLANG_FORCE_INLINE static const RttiInfo * get () { return & T :: g_rttiInfo ; } 344}; 345 346template <> 347struct GetRttiInfo < bool > 348{ 349static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: Bool )]; } 350}; 351template <> 352struct GetRttiInfo < int32_t > 353{ 354static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: I32 )]; } 355}; 356template <> 357struct GetRttiInfo < int64_t > 358{ 359static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: I64 )]; } 360}; 361template <> 362struct GetRttiInfo < uint32_t > 363{ 364static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: U32 )]; } 365}; 366template <> 367struct GetRttiInfo < uint64_t > 368{ 369static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: U64 )]; } 370}; 371template <> 372struct GetRttiInfo < float > 373{ 374static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: F32 )]; } 375}; 376template <> 377struct GetRttiInfo < double > 378{ 379static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: F64 )]; } 380}; 381template <> 382struct GetRttiInfo < String > 383{ 384static const RttiInfo * get () { return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: String )]; } 385}; 386template <> 387struct GetRttiInfo < UnownedStringSlice > 388{ 389static const RttiInfo * get () 390{ 391return & RttiInfo :: g_basicTypes [ Index ( RttiInfo :: Kind :: UnownedStringSlice )]; 392} 393}; 394 395template < typename T > 396struct GetRttiInfo < List < T >> 397{ 398static const ListRttiInfo _make () 399{ 400ListRttiInfo info ; 401info .init < List < Byte >>( RttiInfo :: Kind :: List ); 402info .m_elementType = GetRttiInfo < T > :: get (); 403return info ; 404} 405static const RttiInfo * get () 406{ 407static const ListRttiInfo g_info = _make (); 408return & g_info ; 409} 410}; 411 412// Strip const 413template < typename T > 414struct GetRttiInfo < const T > 415{ 416static const RttiInfo * get () { return GetRttiInfo < T > :: get (); } 417}; 418 419template < typename K , typename V > 420struct GetRttiInfo < Dictionary < K , V >> 421{ 422static const DictionaryRttiInfo _make () 423{ 424DictionaryRttiInfo info ; 425info .init < Dictionary < Byte , Byte >>( RttiInfo :: Kind :: Dictionary ); 426info .m_keyType = GetRttiInfo < K > :: get (); 427info .m_valueType = GetRttiInfo < V > :: get (); 428return info ; 429} 430static const RttiInfo * get () 431{ 432static const DictionaryRttiInfo g_info = _make (); 433return & g_info ; 434} 435}; 436 437template < typename TARGET > 438struct GetRttiInfo < TARGET *> 439{ 440static const PtrRttiInfo _make () 441{ 442PtrRttiInfo info ; 443info .init < void *> ( RttiInfo :: Kind :: Ptr ); 444info .m_targetType = GetRttiInfo < TARGET > :: get (); 445return info ; 446} 447static const RttiInfo * get () 448{ 449static const PtrRttiInfo g_info = _make (); 450return & g_info ; 451} 452}; 453 454template < typename TARGET > 455struct GetRttiInfo < RefPtr < TARGET >> 456{ 457static const RefPtrRttiInfo _make () 458{ 459RefPtrRttiInfo info ; 460info .init < RefPtr < StringRepresentation >>( RttiInfo :: Kind :: RefPtr ); 461info .m_targetType = GetRttiInfo < TARGET > :: get (); 462return info ; 463} 464static const RttiInfo * get () 465{ 466static const RefPtrRttiInfo g_info = _make (); 467return & g_info ; 468} 469}; 470 471template < typename T , size_t COUNT > 472struct GetRttiInfo < T [ COUNT ] > 473{ 474static const FixedArrayRttiInfo _make () 475{ 476FixedArrayRttiInfo info ; 477info .m_kind = RttiInfo :: Kind :: FixedArray ; 478info .m_alignment = RttiInfo :: AlignmentType (alignof( T )); 479info .m_size = RttiInfo :: SizeType ( sizeof ( T ) * COUNT ); 480info .m_elementType = GetRttiInfo < T > :: get (); 481info .m_elementCount = COUNT ; 482return info ; 483} 484static const RttiInfo * get () 485{ 486static const FixedArrayRttiInfo g_info = _make (); 487return & g_info ; 488} 489}; 490 491struct StructRttiBuilder 492{ 493template < typename T > 494StructRttiBuilder( T * obj , const char * name , const StructRttiInfo * super ) 495{ 496m_rttiInfo.init < T > (RttiInfo:: Kind :: Struct ); 497_init ( name , super , ( const Byte * )obj); 498} 499 500template < typename T > 501void addField ( const char * name , const T * fieldPtr , StructRttiInfo :: Flags flags = 0 ) 502{ 503StructRttiInfo:: Field field ; 504 505field .m_name = name ; 506field .m_type = GetRttiInfo < T > :: get (); 507field .m_offset = uint32_t ( ptrdiff_t (( const Byte * ) fieldPtr - m_base )); 508field .m_flags = flags ; 509m_fields . add ( field ); 510} 511 512void ignoreUnknownFields () { m_rttiInfo .m_ignoreUnknownFieldsInJson = true; } 513 514StructRttiInfo make (); 515 516void _init ( const char * name , const StructRttiInfo * super , const Byte * base ); 517 518StructRttiInfo m_rttiInfo ; 519 520List < StructRttiInfo :: Field > m_fields ; 521const Byte * m_base ; 522}; 523 524 525} // namespace Slang 526 527#endif // SLANG_CORE_RTTI_INFO_H