yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
04db5a956
master
1// slang-castable.h 2#ifndef SLANG_CASTABLE_H 3#define SLANG_CASTABLE_H 4 5 6#include "../core/slang-com-object.h" 7#include "slang-com-helper.h" 8#include "slang-com-ptr.h" 9 10namespace Slang 11{ 12 13// Dynamic cast of ICastable derived types 14template < typename T > 15SLANG_FORCE_INLINE T * dynamicCast (ICastable * castable ) 16{ 17if (castable ) 18 { 19void * obj = castable -> castAs (T ::getTypeGuid ()); 20return obj ?reinterpret_cast < T *> (obj ) : ((T * )nullptr ); 21 } 22return nullptr ; 23} 24 25// as style cast 26template < typename T > 27SLANG_FORCE_INLINE T * as (ICastable * castable ) 28{ 29if (castable ) 30 { 31void * obj = castable -> castAs (T ::getTypeGuid ()); 32return obj ?reinterpret_cast < T *> (obj ) : ((T * )nullptr ); 33 } 34return nullptr ; 35} 36 37/* An interface for boxing values */ 38class IBoxValueBase :public ICastable 39{ 40SLANG_COM_INTERFACE ( 410x8b4aad81 , 420x4934 , 430x4a67 , 44 {0xb2 ,0xe2 ,0xe9 ,0x17 ,0xfc ,0x29 ,0x12 ,0x54 }); 45 46/// Get the contained object 47virtual SLANG_NO_THROW void * SLANG_MCALL getValuePtr ()= 0 ; 48/// Get the guid that represents the contained ref object 49virtual SLANG_NO_THROW SlangUUID SLANG_MCALL getValueTypeGuid ()= 0 ; 50}; 51 52template < typename T > 53class IBoxValue :public IBoxValueBase 54{ 55public : 56SLANG_FORCE_INLINE T & get () {return * reinterpret_cast < T *> (getValuePtr ()); } 57SLANG_FORCE_INLINE T * getPtr () {return reinterpret_cast < T *> (getValuePtr ()); } 58}; 59 60// Cast into a boxed value type 61template < typename T > 62SLANG_FORCE_INLINE IBoxValue < T >* asBoxValue (ICastable * castable ) 63{ 64IBoxValueBase * base = as < IBoxValueBase > (castable ); 65return (base && base -> getValueTypeGuid ()== T ::getTypeGuid ()) ?static_cast < IBoxValue < T >* >(base) 66: nullptr ; 67} 68 69template < typename T > 70class BoxValue : public ComBaseObject, public IBoxValue < T > 71{ 72public : 73SLANG_COM_BASE_IUNKNOWN_ALL 74 75// ICastable 76SLANG_NO_THROW void * SLANG_MCALL castAs( const Guid & guid) SLANG_OVERRIDE ; 77 78// IBoxValue 79virtual SLANG_NO_THROW void * SLANG_MCALL getValuePtr () SLANG_OVERRIDE { return & m_value; } 80virtual SLANG_NO_THROW SlangUUID SLANG_MCALL getValueTypeGuid () SLANG_OVERRIDE 81{ 82return T :: getTypeGuid (); 83} 84 85BoxValue () {} 86 87explicit BoxValue ( const T & rhs) 88: m_value (rhs) 89{ 90} 91 92protected : 93void * getInterface ( const Guid & guid); 94void * getObject ( const Guid & guid); 95 96T m_value; 97}; 98 99// ------------------------------------------------------------ 100template < typename T > 101void * BoxValue < T > :: getInterface (const Guid & guid) 102{ 103if (guid == ISlangUnknown:: getTypeGuid () || guid == ICastable:: getTypeGuid () || 104guid == IBoxValueBase:: getTypeGuid ()) 105{ 106return static_cast < IBoxValueBase *> (this); 107} 108return nullptr ; 109} 110 111// ------------------------------------------------------------ 112template < typename T > 113void * BoxValue < T > :: getObject (const Guid & guid) 114{ 115if (guid == T :: getTypeGuid ()) 116{ 117return & m_value; 118} 119return nullptr ; 120} 121 122// ------------------------------------------------------------ 123template < typename T > 124void * BoxValue < T > :: castAs (const Guid & guid) 125{ 126if (auto ptr = getObject (guid)) 127{ 128return ptr; 129} 130return getInterface (guid); 131} 132 133/* Adapter interface to make a non castable types work as ICastable */ 134class IUnknownCastableAdapter : public ICastable 135{ 136SLANG_COM_INTERFACE ( 1370x8b4aad81 , 1380x4934 , 1390x4a67 , 140{ 0xb2 , 0xe2 , 0xe9 , 0x17 , 0xfc , 0x29 , 0x12 , 0x54 }); 141 142/// When using the adapter, this provides a way to directly get the internal no ICastable type 143virtual SLANG_NO_THROW ISlangUnknown * SLANG_MCALL getContained () = 0 ; 144}; 145 146 147/* An adapter such that types which aren't derived from ICastable, can be used as such. 148 149With the following caveats. 150* the interfaces/objects of the adapter are checked *first*, so IUnknown will always be for the 151adapter 152* assumes when doing a queryInterface on the contained item, it will remain in scope when released 153(this is *not* strict COM) 154*/ 155class UnknownCastableAdapter : public ComBaseObject, public IUnknownCastableAdapter 156{ 157public : 158SLANG_COM_BASE_IUNKNOWN_ALL 159 160// ICastable 161SLANG_NO_THROW void * SLANG_MCALL castAs( const Guid & guid) SLANG_OVERRIDE ; 162 163// IUnknownCastableAdapter 164virtual SLANG_NO_THROW ISlangUnknown * SLANG_MCALL getContained () SLANG_OVERRIDE 165{ 166return m_contained; 167} 168 169UnknownCastableAdapter (ISlangUnknown * unk) 170: m_contained (unk) 171{ 172SLANG_ASSERT (unk); 173} 174 175protected : 176void * getInterface ( const Guid & guid); 177void * getObject ( const Guid & guid); 178 179ComPtr < ISlangUnknown > m_contained; 180 181// We hold a cache for a single lookup to make things a little faster 182void * m_found = nullptr ; 183Guid m_foundGuid; 184}; 185 186struct CastableUtil 187{ 188/// Given an ISlangUnkown return as a castable interface. 189/// Can use UnknownCastableAdapter if can't queryInterface unk to ICastable 190static ComPtr < ICastable > getCastable ( ISlangUnknown * unk); 191}; 192 193 194// A way to clone an interface (that derives from IClonable) such that it returns an interface 195// of the same type. 196template < typename T > 197SLANG_FORCE_INLINE ComPtr < T > cloneInterface ( T * in) 198{ 199SLANG_ASSERT (in); 200// Must be derivable from clonable 201IClonable * clonable = in; 202// We can clone with the same interface 203T * clone = ( T * )clonable -> clone ( T :: getTypeGuid ()); 204// Clone must exist 205SLANG_ASSERT (clone); 206return ComPtr < T > (clone); 207} 208 209} // namespace Slang 210 211#endif