yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Jay KwakFix compiler warning with clang 18.1.8 on windows (#6843)04db5a956

master
5.4 KiB211 linesraw
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{
17    if (castable)
18    {
19        void* obj = castable->castAs(T::getTypeGuid());
20        return obj ? reinterpret_cast<T*>(obj) : ((T*)nullptr);
21    }
22    return nullptr;
23}
24
25// as style cast
26template<typename T>
27SLANG_FORCE_INLINE T* as(ICastable* castable)
28{
29    if (castable)
30    {
31        void* obj = castable->castAs(T::getTypeGuid());
32        return obj ? reinterpret_cast<T*>(obj) : ((T*)nullptr);
33    }
34    return nullptr;
35}
36
37/* An interface for boxing values */
38class IBoxValueBase : public ICastable
39{
40    SLANG_COM_INTERFACE(
41        0x8b4aad81,
42        0x4934,
43        0x4a67,
44        {0xb2, 0xe2, 0xe9, 0x17, 0xfc, 0x29, 0x12, 0x54});
45
46    /// Get the contained object
47    virtual SLANG_NO_THROW void* SLANG_MCALL getValuePtr() = 0;
48    /// Get the guid that represents the contained ref object
49    virtual SLANG_NO_THROW SlangUUID SLANG_MCALL getValueTypeGuid() = 0;
50};
51
52template<typename T>
53class IBoxValue : public IBoxValueBase
54{
55public:
56    SLANG_FORCE_INLINE T& get() { return *reinterpret_cast<T*>(getValuePtr()); }
57    SLANG_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{
64    IBoxValueBase* base = as<IBoxValueBase>(castable);
65    return (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:
73    SLANG_COM_BASE_IUNKNOWN_ALL
74
75    // ICastable
76    SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
77
78    // IBoxValue
79    virtual SLANG_NO_THROW void* SLANG_MCALL getValuePtr() SLANG_OVERRIDE { return &m_value; }
80    virtual SLANG_NO_THROW SlangUUID SLANG_MCALL getValueTypeGuid() SLANG_OVERRIDE
81    {
82        return T::getTypeGuid();
83    }
84
85    BoxValue() {}
86
87    explicit BoxValue(const T& rhs)
88        : m_value(rhs)
89    {
90    }
91
92protected:
93    void* getInterface(const Guid& guid);
94    void* getObject(const Guid& guid);
95
96    T m_value;
97};
98
99// ------------------------------------------------------------
100template<typename T>
101void* BoxValue<T>::getInterface(const Guid& guid)
102{
103    if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() ||
104        guid == IBoxValueBase::getTypeGuid())
105    {
106        return static_cast<IBoxValueBase*>(this);
107    }
108    return nullptr;
109}
110
111// ------------------------------------------------------------
112template<typename T>
113void* BoxValue<T>::getObject(const Guid& guid)
114{
115    if (guid == T::getTypeGuid())
116    {
117        return &m_value;
118    }
119    return nullptr;
120}
121
122// ------------------------------------------------------------
123template<typename T>
124void* BoxValue<T>::castAs(const Guid& guid)
125{
126    if (auto ptr = getObject(guid))
127    {
128        return ptr;
129    }
130    return getInterface(guid);
131}
132
133/* Adapter interface to make a non castable types work as ICastable */
134class IUnknownCastableAdapter : public ICastable
135{
136    SLANG_COM_INTERFACE(
137        0x8b4aad81,
138        0x4934,
139        0x4a67,
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
143    virtual 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:
158    SLANG_COM_BASE_IUNKNOWN_ALL
159
160    // ICastable
161    SLANG_NO_THROW void* SLANG_MCALL castAs(const Guid& guid) SLANG_OVERRIDE;
162
163    // IUnknownCastableAdapter
164    virtual SLANG_NO_THROW ISlangUnknown* SLANG_MCALL getContained() SLANG_OVERRIDE
165    {
166        return m_contained;
167    }
168
169    UnknownCastableAdapter(ISlangUnknown* unk)
170        : m_contained(unk)
171    {
172        SLANG_ASSERT(unk);
173    }
174
175protected:
176    void* getInterface(const Guid& guid);
177    void* getObject(const Guid& guid);
178
179    ComPtr<ISlangUnknown> m_contained;
180
181    // We hold a cache for a single lookup to make things a little faster
182    void* m_found = nullptr;
183    Guid 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
190    static 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{
199    SLANG_ASSERT(in);
200    // Must be derivable from clonable
201    IClonable* clonable = in;
202    // We can clone with the same interface
203    T* clone = (T*)clonable->clone(T::getTypeGuid());
204    // Clone must exist
205    SLANG_ASSERT(clone);
206    return ComPtr<T>(clone);
207}
208
209} // namespace Slang
210
211#endif