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
8.6 KiB348 linesraw
1// slang-artifact-associated-impl.cpp
2#include "slang-artifact-associated-impl.h"
3
4#include "../core/slang-array-view.h"
5#include "../core/slang-char-util.h"
6#include "../core/slang-file-system.h"
7#include "../core/slang-io.h"
8#include "../core/slang-type-text-util.h"
9#include "slang-artifact-diagnostic-util.h"
10
11namespace Slang
12{
13
14/* !!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactDiagnostics !!!!!!!!!!!!!!!!!!!!!!!!!!! */
15
16ArtifactDiagnostics::ArtifactDiagnostics(const ThisType& rhs)
17    : ComBaseObject()
18    , m_result(rhs.m_result)
19    , m_diagnostics(rhs.m_diagnostics)
20    , m_raw(rhs.m_raw.getLength() + 1)
21{
22    // We need to be careful with raw, we want a new *copy* not a non atomic ref counting
23    // In initialization we should have enough space
24    m_raw.append(rhs.m_raw.getUnownedSlice());
25
26    // Reallocate all the strings
27    for (auto& diagnostic : m_diagnostics)
28    {
29        diagnostic.filePath = m_allocator.allocate(diagnostic.filePath);
30        diagnostic.code = m_allocator.allocate(diagnostic.code);
31        diagnostic.text = m_allocator.allocate(diagnostic.text);
32    }
33}
34
35void* ArtifactDiagnostics::clone(const Guid& guid)
36{
37    ThisType* copy = new ThisType(*this);
38    if (auto ptr = copy->castAs(guid))
39    {
40        return ptr;
41    }
42    // If the cast fails, we delete the item.
43    delete copy;
44    return nullptr;
45}
46
47void* ArtifactDiagnostics::getInterface(const Guid& guid)
48{
49    if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() ||
50        guid == IClonable::getTypeGuid() || guid == IArtifactDiagnostics::getTypeGuid())
51    {
52        return static_cast<IArtifactDiagnostics*>(this);
53    }
54    return nullptr;
55}
56
57void* ArtifactDiagnostics::getObject(const Guid& guid)
58{
59    SLANG_UNUSED(guid);
60    return nullptr;
61}
62
63void* ArtifactDiagnostics::castAs(const Guid& guid)
64{
65    if (auto intf = getInterface(guid))
66    {
67        return intf;
68    }
69    return getObject(guid);
70}
71
72void ArtifactDiagnostics::reset()
73{
74    m_diagnostics.clear();
75    m_raw.clear();
76    m_result = SLANG_OK;
77
78    m_allocator.deallocateAll();
79}
80
81void ArtifactDiagnostics::add(const Diagnostic& inDiagnostic)
82{
83    Diagnostic diagnostic(inDiagnostic);
84
85    diagnostic.text = m_allocator.allocate(inDiagnostic.text);
86    diagnostic.code = m_allocator.allocate(inDiagnostic.code);
87    diagnostic.filePath = m_allocator.allocate(inDiagnostic.filePath);
88
89    m_diagnostics.add(diagnostic);
90}
91
92void ArtifactDiagnostics::setRaw(const CharSlice& slice)
93{
94    m_raw.clear();
95    m_raw << asStringSlice(slice);
96}
97
98void ArtifactDiagnostics::appendRaw(const CharSlice& slice)
99{
100    if (m_raw.getLength() && m_raw[m_raw.getLength() - 1] != '\n')
101    {
102        m_raw.appendChar('\n');
103    }
104    m_raw << asStringSlice(slice);
105}
106
107Count ArtifactDiagnostics::getCountAtLeastSeverity(Diagnostic::Severity severity)
108{
109    Index count = 0;
110    for (const auto& msg : m_diagnostics)
111    {
112        count += Index(Index(msg.severity) >= Index(severity));
113    }
114    return count;
115}
116
117Count ArtifactDiagnostics::getCountBySeverity(Diagnostic::Severity severity)
118{
119    Index count = 0;
120    for (const auto& msg : m_diagnostics)
121    {
122        count += Index(msg.severity == severity);
123    }
124    return count;
125}
126
127bool ArtifactDiagnostics::hasOfAtLeastSeverity(Diagnostic::Severity severity)
128{
129    for (const auto& msg : m_diagnostics)
130    {
131        if (Index(msg.severity) >= Index(severity))
132        {
133            return true;
134        }
135    }
136    return false;
137}
138
139Count ArtifactDiagnostics::getCountByStage(
140    Diagnostic::Stage stage,
141    Count outCounts[Int(Diagnostic::Severity::CountOf)])
142{
143    Int count = 0;
144    ::memset(outCounts, 0, sizeof(Index) * Int(Diagnostic::Severity::CountOf));
145    for (const auto& diagnostic : m_diagnostics)
146    {
147        if (diagnostic.stage == stage)
148        {
149            count++;
150            outCounts[Index(diagnostic.severity)]++;
151        }
152    }
153    return count++;
154}
155
156void ArtifactDiagnostics::removeBySeverity(Diagnostic::Severity severity)
157{
158    Index count = m_diagnostics.getCount();
159    for (Index i = 0; i < count; ++i)
160    {
161        if (m_diagnostics[i].severity == severity)
162        {
163            m_diagnostics.removeAt(i);
164            i--;
165            count--;
166        }
167    }
168}
169
170void ArtifactDiagnostics::maybeAddNote(const CharSlice& in)
171{
172    ArtifactDiagnosticUtil::maybeAddNote(asStringSlice(in), this);
173}
174
175void ArtifactDiagnostics::requireErrorDiagnostic()
176{
177    // If we find an error, we don't need to add a generic diagnostic
178    for (const auto& msg : m_diagnostics)
179    {
180        if (Index(msg.severity) >= Index(Diagnostic::Severity::Error))
181        {
182            return;
183        }
184    }
185
186    Diagnostic diagnostic;
187    diagnostic.severity = Diagnostic::Severity::Error;
188    diagnostic.text = m_allocator.allocate(m_raw);
189
190    // Add the diagnostic
191    m_diagnostics.add(diagnostic);
192}
193
194/* static */ UnownedStringSlice _getSeverityText(ArtifactDiagnostic::Severity severity)
195{
196    typedef ArtifactDiagnostic::Severity Severity;
197    switch (severity)
198    {
199    default:
200        return UnownedStringSlice::fromLiteral("Unknown");
201    case Severity::Info:
202        return UnownedStringSlice::fromLiteral("Info");
203    case Severity::Warning:
204        return UnownedStringSlice::fromLiteral("Warning");
205    case Severity::Error:
206        return UnownedStringSlice::fromLiteral("Error");
207    }
208}
209
210static void _appendCounts(
211    const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)],
212    StringBuilder& out)
213{
214    typedef ArtifactDiagnostic::Severity Severity;
215
216    for (Index i = 0; i < Int(Severity::CountOf); i++)
217    {
218        if (counts[i] > 0)
219        {
220            out << _getSeverityText(Severity(i)) << "(" << counts[i] << ") ";
221        }
222    }
223}
224
225static void _appendSimplified(
226    const Index counts[Int(ArtifactDiagnostic::Severity::CountOf)],
227    StringBuilder& out)
228{
229    typedef ArtifactDiagnostic::Severity Severity;
230    for (Index i = 0; i < Int(Severity::CountOf); i++)
231    {
232        if (counts[i] > 0)
233        {
234            out << _getSeverityText(Severity(i)) << " ";
235        }
236    }
237}
238
239void ArtifactDiagnostics::calcSummary(ISlangBlob** outBlob)
240{
241    StringBuilder buf;
242
243    Index counts[Int(Diagnostic::Severity::CountOf)];
244    if (getCountByStage(Diagnostic::Stage::Compile, counts) > 0)
245    {
246        buf << "Compile: ";
247        _appendCounts(counts, buf);
248        buf << "\n";
249    }
250    if (getCountByStage(Diagnostic::Stage::Link, counts) > 0)
251    {
252        buf << "Link: ";
253        _appendCounts(counts, buf);
254        buf << "\n";
255    }
256
257    *outBlob = StringBlob::moveCreate(buf).detach();
258}
259
260void ArtifactDiagnostics::calcSimplifiedSummary(ISlangBlob** outBlob)
261{
262    StringBuilder buf;
263
264    Index counts[Int(Diagnostic::Severity::CountOf)];
265    if (getCountByStage(Diagnostic::Stage::Compile, counts) > 0)
266    {
267        buf << "Compile: ";
268        _appendSimplified(counts, buf);
269        buf << "\n";
270    }
271    if (getCountByStage(Diagnostic::Stage::Link, counts) > 0)
272    {
273        buf << "Link: ";
274        _appendSimplified(counts, buf);
275        buf << "\n";
276    }
277
278    *outBlob = StringBlob::moveCreate(buf).detach();
279}
280
281/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ArtifactPostEmitMetadata !!!!!!!!!!!!!!!!!!!!!!!!!!! */
282
283void* ArtifactPostEmitMetadata::getInterface(const Guid& guid)
284{
285    if (guid == ISlangUnknown::getTypeGuid() || guid == ICastable::getTypeGuid() ||
286        guid == IArtifactPostEmitMetadata::getTypeGuid())
287    {
288        return static_cast<IArtifactPostEmitMetadata*>(this);
289    }
290    return nullptr;
291}
292
293void* ArtifactPostEmitMetadata::getObject(const Guid& uuid)
294{
295    if (uuid == getTypeGuid())
296    {
297        return this;
298    }
299    return nullptr;
300}
301
302void* ArtifactPostEmitMetadata::castAs(const Guid& guid)
303{
304    if (auto ptr = getInterface(guid))
305    {
306        return ptr;
307    }
308    return getObject(guid);
309}
310
311Slice<ShaderBindingRange> ArtifactPostEmitMetadata::getUsedBindingRanges()
312{
313    return Slice<ShaderBindingRange>(m_usedBindings.getBuffer(), m_usedBindings.getCount());
314}
315
316Slice<String> ArtifactPostEmitMetadata::getExportedFunctionMangledNames()
317{
318    return Slice<String>(
319        m_exportedFunctionMangledNames.getBuffer(),
320        m_exportedFunctionMangledNames.getCount());
321}
322
323SlangResult ArtifactPostEmitMetadata::isParameterLocationUsed(
324    SlangParameterCategory category,
325    SlangUInt spaceIndex,
326    SlangUInt registerIndex,
327    bool& outUsed)
328{
329    for (const auto& range : getUsedBindingRanges())
330    {
331        if (range.containsBinding((slang::ParameterCategory)category, spaceIndex, registerIndex))
332        {
333            outUsed = true;
334            return SLANG_OK;
335        }
336    }
337
338    outUsed = false;
339    return SLANG_OK;
340}
341
342const char* ArtifactPostEmitMetadata::getDebugBuildIdentifier()
343{
344    return m_debugBuildIdentifier.getBuffer();
345}
346
347
348} // namespace Slang