yum-mirror/slang

Making it easier to work with shaders

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

jarcherNVAdd command line option for separate debug info (#7178)0d16228ae

master
9.1 KiB381 linesraw
1// slang-artifact-impl.cpp
2#include "slang-artifact-impl.h"
3
4#include "../core/slang-castable.h"
5#include "slang-artifact-desc-util.h"
6#include "slang-artifact-handler-impl.h"
7#include "slang-artifact-representation.h"
8#include "slang-artifact-util.h"
9#include "slang-slice-allocator.h"
10
11namespace Slang
12{
13
14namespace
15{ // anonymous
16
17/* Get a view as a slice of *raw* pointers */
18template<typename T>
19SLANG_FORCE_INLINE ConstArrayView<T*> _getRawView(const List<ComPtr<T>>& in)
20{
21    return makeConstArrayView((T* const*)in.getBuffer(), in.getCount());
22}
23
24} // namespace
25
26/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Artifact !!!!!!!!!!!!!!!!!!!!!!!!!!! */
27
28void* Artifact::castAs(const Guid& guid)
29{
30    if (auto ptr = getInterface(guid))
31    {
32        return ptr;
33    }
34    return getObject(guid);
35}
36
37void* Artifact::getInterface(const Guid& uuid)
38{
39    if (uuid == ISlangUnknown::getTypeGuid() || uuid == ICastable::getTypeGuid() ||
40        uuid == IArtifact::getTypeGuid())
41    {
42        return static_cast<IArtifact*>(this);
43    }
44    return nullptr;
45}
46
47void* Artifact::getObject(const Guid& uuid)
48{
49    SLANG_UNUSED(uuid);
50    return nullptr;
51}
52
53IArtifactHandler* Artifact::_getHandler()
54{
55    return m_handler ? m_handler : DefaultArtifactHandler::getSingleton();
56}
57
58void Artifact::_requireChildren()
59{
60    if (m_expandResult == SLANG_E_UNINITIALIZED)
61    {
62        const auto res = expandChildren();
63        SLANG_UNUSED(res);
64
65        SLANG_ASSERT(SLANG_SUCCEEDED(res) || res == SLANG_E_NOT_IMPLEMENTED);
66    }
67}
68
69bool Artifact::exists()
70{
71    for (ICastable* rep : m_representations.getArrayView())
72    {
73        if (auto artifactRep = as<IArtifactRepresentation>(rep))
74        {
75            // It is an artifact rep and it exists, we are done
76            if (artifactRep->exists())
77            {
78                return true;
79            }
80        }
81        else
82        {
83            // If it's *not* IArtifactRepresentation derived, it's existance *is* a representation
84            return true;
85        }
86    }
87
88    return false;
89}
90
91SlangResult Artifact::requireFile(Keep keep, IOSFileArtifactRepresentation** outFileRep)
92{
93    auto handler = _getHandler();
94
95    ComPtr<ICastable> castable;
96    SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(
97        this,
98        IOSFileArtifactRepresentation::getTypeGuid(),
99        keep,
100        castable.writeRef()));
101
102    auto fileRep = as<IOSFileArtifactRepresentation>(castable);
103    fileRep->addRef();
104
105    *outFileRep = fileRep;
106    return SLANG_OK;
107}
108
109SlangResult Artifact::loadSharedLibrary(ArtifactKeep keep, ISlangSharedLibrary** outSharedLibrary)
110{
111    auto handler = _getHandler();
112
113    ComPtr<ICastable> castable;
114    SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(
115        this,
116        ISlangSharedLibrary::getTypeGuid(),
117        keep,
118        castable.writeRef()));
119
120    auto lib = as<ISlangSharedLibrary>(castable);
121    lib->addRef();
122
123    *outSharedLibrary = lib;
124    return SLANG_OK;
125}
126
127IArtifactHandler* Artifact::getHandler()
128{
129    return m_handler;
130}
131
132void Artifact::setHandler(IArtifactHandler* handler)
133{
134    m_handler = handler;
135}
136
137void Artifact::clear(IArtifact::ContainedKind kind)
138{
139    switch (kind)
140    {
141    case ContainedKind::Associated:
142        m_associated.clear();
143        break;
144    case ContainedKind::Representation:
145        m_representations.clear();
146        break;
147    case ContainedKind::Children:
148        m_children.clear();
149        break;
150    default:
151        break;
152    }
153}
154
155void Artifact::removeAt(ContainedKind kind, Index i)
156{
157    switch (kind)
158    {
159    case ContainedKind::Associated:
160        m_associated.removeAt(i);
161        break;
162    case ContainedKind::Representation:
163        m_representations.removeAt(i);
164        break;
165    case ContainedKind::Children:
166        m_children.removeAt(i);
167        break;
168    default:
169        break;
170    }
171}
172
173uint32_t Artifact::getItemCount()
174{
175    // Ignore the metadata when counting items, and the base artifact is item 0.
176    uint32_t count = 1;
177    for (auto artifact : m_associated)
178        if (artifact->getDesc().payload != ArtifactPayload::Metadata &&
179            artifact->getDesc().payload != ArtifactPayload::PostEmitMetadata)
180            count++;
181    return count;
182}
183
184SlangResult Artifact::getItemData(uint32_t index, slang::IBlob** outblob)
185{
186    // Item 0 is the base artifact, otherwise iterate and ignore the metadata.
187    if (index == 0)
188        return loadBlob(ArtifactKeep::Yes, outblob);
189
190    uint32_t count = 1;
191    for (auto artifact : m_associated)
192    {
193        if (artifact->getDesc().payload == ArtifactPayload::Metadata ||
194            artifact->getDesc().payload == ArtifactPayload::PostEmitMetadata)
195            continue;
196        if (count == index)
197            return artifact->loadBlob(ArtifactKeep::Yes, outblob);
198        count++;
199    }
200    return SLANG_FAIL;
201}
202
203SlangResult Artifact::getMetadata(slang::IMetadata** outMetadata)
204{
205    // Find and return the associated metadata artifact.
206    auto metadata = findAssociatedRepresentation<IArtifactPostEmitMetadata>(this);
207    if (!metadata)
208        return SLANG_E_NOT_AVAILABLE;
209
210    *outMetadata = static_cast<slang::IMetadata*>(metadata);
211    (*outMetadata)->addRef();
212    return SLANG_OK;
213}
214
215SlangResult Artifact::getOrCreateRepresentation(
216    const Guid& typeGuid,
217    ArtifactKeep keep,
218    ICastable** outCastable)
219{
220    auto handler = _getHandler();
221    return handler->getOrCreateRepresentation(this, typeGuid, keep, outCastable);
222}
223
224SlangResult Artifact::loadBlob(Keep keep, ISlangBlob** outBlob)
225{
226    auto handler = _getHandler();
227
228    ComPtr<ICastable> castable;
229    SLANG_RETURN_ON_FAIL(handler->getOrCreateRepresentation(
230        this,
231        ISlangBlob::getTypeGuid(),
232        keep,
233        castable.writeRef()));
234
235    ISlangBlob* blob = as<ISlangBlob>(castable);
236    blob->addRef();
237
238    *outBlob = blob;
239    return SLANG_OK;
240}
241
242void Artifact::addAssociated(IArtifact* artifact)
243{
244    SLANG_ASSERT(artifact);
245    m_associated.add(ComPtr<IArtifact>(artifact));
246}
247
248static void* _findRepresentation(const ConstArrayView<ICastable*>& castables, const Guid& guid)
249{
250    for (const auto& cur : castables)
251    {
252        if (auto ptr = cur->castAs(guid))
253        {
254            return ptr;
255        }
256    }
257    return nullptr;
258}
259
260static void* _findRepresentation(const ConstArrayView<IArtifact*>& artifacts, const Guid& guid)
261{
262    for (auto child : artifacts)
263    {
264        if (auto rep = child->findRepresentation(Artifact::ContainedKind::Representation, guid))
265        {
266            return rep;
267        }
268    }
269    return nullptr;
270}
271
272void* Artifact::findRepresentation(ContainedKind kind, const Guid& guid)
273{
274    switch (kind)
275    {
276    case ContainedKind::Associated:
277        return _findRepresentation(_getRawView(m_associated), guid);
278    case ContainedKind::Representation:
279        return _findRepresentation(_getRawView(m_representations), guid);
280    case ContainedKind::Children:
281        {
282            _requireChildren();
283            return _findRepresentation(_getRawView(m_children), guid);
284        }
285    }
286    return nullptr;
287}
288
289Slice<IArtifact*> Artifact::getAssociated()
290{
291    return SliceUtil::asSlice(m_associated);
292}
293
294void Artifact::addRepresentation(ICastable* castable)
295{
296    SLANG_ASSERT(castable);
297
298    auto view = _getRawView(m_representations);
299    if (view.indexOf(castable) >= 0)
300    {
301        SLANG_ASSERT_FAILURE("Already have this representation");
302        return;
303    }
304
305    m_representations.add(ComPtr<ICastable>(castable));
306}
307
308void Artifact::addRepresentationUnknown(ISlangUnknown* unk)
309{
310    SLANG_ASSERT(unk);
311
312    {
313        const auto view = makeConstArrayView(
314            (ISlangUnknown* const*)m_representations.getBuffer(),
315            m_representations.getCount());
316        if (view.indexOf(unk) >= 0)
317        {
318            SLANG_ASSERT_FAILURE("Already have this representation");
319            return;
320        }
321    }
322
323    ComPtr<ICastable> castable;
324    if (SLANG_SUCCEEDED(unk->queryInterface(SLANG_IID_PPV_ARGS(castable.writeRef()))) && castable)
325    {
326        if (_getRawView(m_representations).indexOf(castable) >= 0)
327        {
328            SLANG_ASSERT_FAILURE("Already have this representation");
329            return;
330        }
331        m_representations.add(castable);
332    }
333    else
334    {
335        UnknownCastableAdapter* adapter = new UnknownCastableAdapter(unk);
336        m_representations.add(ComPtr<ICastable>(adapter));
337    }
338}
339
340Slice<ICastable*> Artifact::getRepresentations()
341{
342    return SliceUtil::asSlice(m_representations);
343}
344
345void Artifact::setChildren(IArtifact* const* children, Count count)
346{
347    m_expandResult = SLANG_OK;
348
349    m_children.clearAndDeallocate();
350    m_children.setCount(count);
351
352    ComPtr<IArtifact>* dst = m_children.getBuffer();
353    for (Index i = 0; i < count; ++i)
354    {
355        dst[i] = children[i];
356    }
357}
358
359SlangResult Artifact::expandChildren()
360{
361    auto handler = _getHandler();
362    return handler->expandChildren(this);
363}
364
365Slice<IArtifact*> Artifact::getChildren()
366{
367    _requireChildren();
368    return SliceUtil::asSlice(m_children);
369}
370
371void Artifact::addChild(IArtifact* artifact)
372{
373    SLANG_ASSERT(artifact);
374    SLANG_ASSERT(_getRawView(m_children).indexOf(artifact) < 0);
375
376    _requireChildren();
377
378    m_children.add(ComPtr<IArtifact>(artifact));
379}
380
381} // namespace Slang