yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
9.0 KiB344 linesraw
1// slang-artifact-util.cpp
2#include "slang-artifact-util.h"
3
4#include "../core/slang-castable.h"
5#include "../core/slang-io.h"
6#include "slang-artifact-desc-util.h"
7#include "slang-artifact-impl.h"
8#include "slang-artifact-representation-impl.h"
9
10namespace Slang
11{
12
13static bool _checkSelf(ArtifactUtil::FindStyle findStyle)
14{
15    return Index(findStyle) <= Index(ArtifactUtil::FindStyle::SelfOrChildren);
16}
17
18static bool _checkChildren(ArtifactUtil::FindStyle findStyle)
19{
20    return Index(findStyle) >= Index(ArtifactUtil::FindStyle::SelfOrChildren);
21}
22
23static bool _checkRecursive(ArtifactUtil::FindStyle findStyle)
24{
25    return findStyle == ArtifactUtil::FindStyle::Recursive ||
26           findStyle == ArtifactUtil::FindStyle::ChildrenRecursive;
27}
28
29/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactUtil !!!!!!!!!!!!!!!!!!!!!!!!!!! */
30
31/* static */ ComPtr<IArtifact> ArtifactUtil::createArtifact(
32    const ArtifactDesc& desc,
33    const char* name)
34{
35    auto artifact = createArtifact(desc);
36    artifact->setName(name);
37    return artifact;
38}
39
40/* static */ ComPtr<IArtifact> ArtifactUtil::createArtifact(const ArtifactDesc& desc)
41{
42    return Artifact::create(desc);
43}
44
45/* static */ ComPtr<IArtifact> ArtifactUtil::createArtifactForCompileTarget(
46    SlangCompileTarget target)
47{
48    auto desc = ArtifactDescUtil::makeDescForCompileTarget(target);
49    return createArtifact(desc);
50}
51
52/* static */ bool ArtifactUtil::isSignificant(IArtifact* artifact)
53{
54    return isSignificant(artifact->getDesc());
55}
56
57/* static */ bool ArtifactUtil::isSignificant(const ArtifactDesc& desc)
58{
59    // Containers are not significant as of themselves, they may contain something tho
60    if (isDerivedFrom(desc.kind, ArtifactKind::Container))
61    {
62        return false;
63    }
64
65    // If it has no payload.. we are done
66    if (desc.payload == ArtifactPayload::None || desc.payload == ArtifactPayload::Invalid)
67    {
68        return false;
69    }
70
71    // If it's binary like or assembly/source we it's significant
72    if (isDerivedFrom(desc.kind, ArtifactKind::CompileBinary) ||
73        desc.kind == ArtifactKind::Assembly || desc.kind == ArtifactKind::Source)
74    {
75        return true;
76    }
77
78    /* Hmm, we might want to have a base class for 'significant' payloads,
79    where signifiance here means somewhat approximately 'the meat' of a compilation result,
80    as contrasted with 'meta data', 'diagnostics etc'*/
81    if (isDerivedFrom(desc.payload, ArtifactPayload::Metadata))
82    {
83        return false;
84    }
85
86    /* We currently can't write out diagnostics, so for now we'll say they are insignificant */
87    if (isDerivedFrom(desc.payload, ArtifactPayload::Diagnostics))
88    {
89        return false;
90    }
91
92    return true;
93}
94
95
96/* static */ bool ArtifactUtil::isSignificant(IArtifact* artifact, void* data)
97{
98    SLANG_UNUSED(data);
99    return isSignificant(artifact->getDesc());
100}
101
102/* static */ IArtifact* ArtifactUtil::findSignificant(IArtifact* artifact)
103{
104    return findArtifactByPredicate(
105        artifact,
106        FindStyle::SelfOrChildren,
107        &ArtifactUtil::isSignificant,
108        nullptr);
109}
110
111UnownedStringSlice ArtifactUtil::findPath(IArtifact* artifact)
112{
113    // If a name is set we'll just use that
114    {
115        const UnownedStringSlice name(artifact->getName());
116        if (name.getLength())
117        {
118            return name;
119        }
120    }
121
122    IPathArtifactRepresentation* bestRep = nullptr;
123
124    // Look for a rep with a path. Prefer IExtFile because a IOSFile might be a temporary file
125    for (auto rep : artifact->getRepresentations())
126    {
127        if (auto pathRep = as<IPathArtifactRepresentation>(rep))
128        {
129            if (pathRep->getPathType() == SLANG_PATH_TYPE_FILE &&
130                (bestRep == nullptr || as<IExtFileArtifactRepresentation>(rep)))
131            {
132                bestRep = pathRep;
133            }
134        }
135    }
136
137    const UnownedStringSlice name =
138        bestRep ? UnownedStringSlice(bestRep->getPath()) : UnownedStringSlice();
139    return name.getLength() ? name : UnownedStringSlice();
140}
141
142/* static */ UnownedStringSlice ArtifactUtil::inferExtension(IArtifact* artifact)
143{
144    const UnownedStringSlice path = findPath(artifact);
145    if (path.getLength())
146    {
147        auto ext = Path::getPathExt(UnownedStringSlice(path));
148        if (ext.getLength())
149        {
150            return ext;
151        }
152    }
153    return UnownedStringSlice();
154}
155
156/* static */ UnownedStringSlice ArtifactUtil::findName(IArtifact* artifact)
157{
158    const UnownedStringSlice path = findPath(artifact);
159    const Index pos = Path::findLastSeparatorIndex(path);
160    return (pos >= 0) ? path.tail(pos + 1) : path;
161}
162
163static SlangResult _calcInferred(
164    IArtifact* artifact,
165    const UnownedStringSlice& basePath,
166    StringBuilder& outPath)
167{
168    auto ext = ArtifactUtil::inferExtension(artifact);
169
170    // If no extension was determined by inferring, go with unknown
171    if (ext.begin() == nullptr)
172    {
173        ext = toSlice("unknown");
174    }
175
176    outPath.clear();
177    outPath.append(basePath);
178    if (ext.getLength())
179    {
180        outPath.appendChar('.');
181        outPath.append(ext);
182    }
183    return SLANG_OK;
184}
185
186/* static */ SlangResult ArtifactUtil::calcPath(
187    IArtifact* artifact,
188    const UnownedStringSlice& basePath,
189    StringBuilder& outPath)
190{
191    if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc()))
192    {
193        return ArtifactDescUtil::calcPathForDesc(artifact->getDesc(), basePath, outPath);
194    }
195    else
196    {
197        return _calcInferred(artifact, basePath, outPath);
198    }
199}
200
201/* static */ SlangResult ArtifactUtil::calcName(
202    IArtifact* artifact,
203    const UnownedStringSlice& baseName,
204    StringBuilder& outName)
205{
206    if (ArtifactDescUtil::hasDefinedNameForDesc(artifact->getDesc()))
207    {
208        return ArtifactDescUtil::calcNameForDesc(artifact->getDesc(), baseName, outName);
209    }
210    else
211    {
212        return _calcInferred(artifact, baseName, outName);
213    }
214}
215
216static bool _isByDerivedDesc(IArtifact* artifact, void* data)
217{
218    const ArtifactDesc& desc = *(const ArtifactDesc*)data;
219    return ArtifactDescUtil::isDescDerivedFrom(artifact->getDesc(), desc);
220}
221
222static bool _isDesc(IArtifact* artifact, void* data)
223{
224    const ArtifactDesc& desc = *(const ArtifactDesc*)data;
225    return artifact->getDesc() == desc;
226}
227
228static bool _isName(IArtifact* artifact, void* data)
229{
230    const char* name = (const char*)data;
231    const auto artifactName = artifact->getName();
232
233    if (name == nullptr || artifactName == nullptr)
234    {
235        return name == artifactName;
236    }
237    return ::strcmp(name, artifactName) == 0;
238}
239
240/* static */ IArtifact* ArtifactUtil::findArtifactByDerivedDesc(
241    IArtifact* artifact,
242    FindStyle findStyle,
243    const ArtifactDesc& desc)
244{
245    return findArtifactByPredicate(
246        artifact,
247        findStyle,
248        _isByDerivedDesc,
249        &const_cast<ArtifactDesc&>(desc));
250}
251
252/* static */ IArtifact* ArtifactUtil::findArtifactByName(
253    IArtifact* artifact,
254    FindStyle findStyle,
255    const char* name)
256{
257    return findArtifactByPredicate(artifact, findStyle, _isName, const_cast<char*>(name));
258}
259
260/* static */ IArtifact* ArtifactUtil::findArtifactByDesc(
261    IArtifact* artifact,
262    FindStyle findStyle,
263    const ArtifactDesc& desc)
264{
265    return findArtifactByPredicate(artifact, findStyle, _isDesc, &const_cast<ArtifactDesc&>(desc));
266}
267
268/* static */ IArtifact* ArtifactUtil::findArtifactByPredicate(
269    IArtifact* artifact,
270    FindStyle findStyle,
271    FindFunc func,
272    void* data)
273{
274    if (_checkSelf(findStyle) && func(artifact, data))
275    {
276        return artifact;
277    }
278
279    if (!_checkChildren(findStyle))
280    {
281        return nullptr;
282    }
283
284    // Expand the children so we can search them
285    artifact->expandChildren();
286
287    auto children = artifact->getChildren();
288    if (children.count == 0)
289    {
290        return nullptr;
291    }
292
293    // Check the children
294    for (auto child : children)
295    {
296        if (func(child, data))
297        {
298            return child;
299        }
300    }
301
302    // If it's recursive, we check all the children of children
303    if (_checkRecursive(findStyle))
304    {
305        for (auto child : children)
306        {
307            if (auto found =
308                    findArtifactByPredicate(child, FindStyle::ChildrenRecursive, func, data))
309            {
310                return found;
311            }
312        }
313    }
314
315    return nullptr;
316}
317
318/* static */ void ArtifactUtil::addAssociated(
319    IArtifact* artifact,
320    IArtifactPostEmitMetadata* metadata)
321{
322    if (metadata)
323    {
324        auto metadataArtifact = ArtifactUtil::createArtifact(
325            ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::PostEmitMetadata));
326        metadataArtifact->addRepresentation(metadata);
327        artifact->addAssociated(metadataArtifact);
328    }
329}
330
331/* static */ void ArtifactUtil::addAssociated(
332    IArtifact* artifact,
333    IArtifactDiagnostics* diagnostics)
334{
335    if (diagnostics)
336    {
337        auto diagnosticsArtifact = ArtifactUtil::createArtifact(
338            ArtifactDesc::make(ArtifactKind::Instance, ArtifactPayload::Diagnostics));
339        diagnosticsArtifact->addRepresentation(diagnostics);
340        artifact->addAssociated(diagnosticsArtifact);
341    }
342}
343
344} // namespace Slang