yum-mirror/slang

Making it easier to work with shaders

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

Ellie Hermaszewskaformatf65d756bf

master
4.6 KiB152 linesraw
1#include "slang-tint-compiler.h"
2
3#include "../../external/slang-tint-headers/slang-tint.h"
4#include "slang-artifact-associated-impl.h"
5
6namespace Slang
7{
8
9class TintDownstreamCompiler : public DownstreamCompilerBase
10{
11
12public:
13    // IDownstreamCompiler
14    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
15    compile(const CompileOptions& options, IArtifact** outResult) SLANG_OVERRIDE;
16
17    virtual SLANG_NO_THROW bool SLANG_MCALL
18    canConvert(const ArtifactDesc& from, const ArtifactDesc& to) SLANG_OVERRIDE;
19
20    virtual SLANG_NO_THROW SlangResult SLANG_MCALL
21    convert(IArtifact* from, const ArtifactDesc& to, IArtifact** outArtifact) SLANG_OVERRIDE;
22
23    virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return false; }
24
25    virtual SLANG_NO_THROW SlangResult SLANG_MCALL getVersionString(slang::IBlob** outVersionString)
26        SLANG_OVERRIDE;
27
28    SlangResult compile(IArtifact* const sourceArtifact, IArtifact** outArtifact);
29
30    SlangResult init(ISlangSharedLibrary* library);
31
32protected:
33    ComPtr<ISlangSharedLibrary> m_sharedLibrary;
34
35private:
36    tint_CompileFunc m_compile;
37    tint_FreeResultFunc m_freeResult;
38};
39
40SlangResult TintDownstreamCompiler::init(ISlangSharedLibrary* library)
41{
42    tint_CompileFunc compile = (tint_CompileFunc)library->findFuncByName("tint_compile");
43    if (compile == nullptr)
44    {
45        return SLANG_FAIL;
46    }
47
48    tint_FreeResultFunc freeResult =
49        (tint_FreeResultFunc)library->findFuncByName("tint_free_result");
50    if (freeResult == nullptr)
51    {
52        return SLANG_FAIL;
53    }
54
55    m_sharedLibrary = library;
56    m_desc = Desc(SLANG_PASS_THROUGH_TINT);
57    m_compile = compile;
58    m_freeResult = freeResult;
59    return SLANG_OK;
60}
61
62SlangResult TintDownstreamCompilerUtil::locateCompilers(
63    const String& path,
64    ISlangSharedLibraryLoader* loader,
65    DownstreamCompilerSet* set)
66{
67    ComPtr<ISlangSharedLibrary> library;
68    SLANG_RETURN_ON_FAIL(
69        DownstreamCompilerUtil::loadSharedLibrary(path, loader, nullptr, "slang-tint", library));
70    SLANG_ASSERT(library);
71
72    ComPtr<IDownstreamCompiler> compiler =
73        ComPtr<IDownstreamCompiler>(new TintDownstreamCompiler());
74    SLANG_RETURN_ON_FAIL(static_cast<TintDownstreamCompiler*>(compiler.get())->init(library));
75
76    set->addCompiler(compiler);
77    return SLANG_OK;
78}
79
80SlangResult TintDownstreamCompiler::compile(const CompileOptions& options, IArtifact** outArtifact)
81{
82    IArtifact* sourceArtifact = options.sourceArtifacts[0];
83    return compile(sourceArtifact, outArtifact);
84}
85
86SlangResult TintDownstreamCompiler::compile(
87    IArtifact* const sourceArtifact,
88    IArtifact** outArtifact)
89{
90    tint_CompileRequest req = {};
91
92    if (sourceArtifact == nullptr)
93        return SLANG_FAIL;
94
95    ComPtr<ISlangBlob> sourceBlob;
96    SLANG_RETURN_FALSE_ON_FAIL(sourceArtifact->loadBlob(ArtifactKeep::Yes, sourceBlob.writeRef()));
97
98    String wgslCode(
99        (char*)sourceBlob->getBufferPointer(),
100        (char*)sourceBlob->getBufferPointer() + sourceBlob->getBufferSize());
101    req.wgslCode = wgslCode.begin();
102    req.wgslCodeLength = wgslCode.getLength();
103
104    tint_CompileResult result = {};
105    SLANG_DEFER(m_freeResult(&result));
106    bool compileSucceeded = m_compile(&req, &result) == 0;
107
108    ComPtr<ISlangBlob> spirvBlob = RawBlob::create(result.buffer, result.bufferSize);
109    result.buffer = nullptr;
110
111    ComPtr<IArtifact> resultArtifact =
112        ArtifactUtil::createArtifactForCompileTarget(SlangCompileTarget::SLANG_WGSL_SPIRV);
113    auto diagnostics = ArtifactDiagnostics::create();
114    diagnostics->setResult(compileSucceeded ? SLANG_OK : SLANG_FAIL);
115    ArtifactUtil::addAssociated(resultArtifact, diagnostics);
116    if (compileSucceeded)
117    {
118        resultArtifact->addRepresentationUnknown(spirvBlob);
119    }
120    else
121    {
122        diagnostics->setRaw(CharSlice(result.error));
123        diagnostics->requireErrorDiagnostic();
124    }
125
126    *outArtifact = resultArtifact.detach();
127    return SLANG_OK;
128}
129
130bool TintDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to)
131{
132    return (from.payload == ArtifactPayload::WGSL) && (to.payload == ArtifactPayload::SPIRV);
133}
134
135SlangResult TintDownstreamCompiler::convert(
136    IArtifact* from,
137    const ArtifactDesc& to,
138    IArtifact** outArtifact)
139{
140    if (!canConvert(from->getDesc(), to))
141        return SLANG_FAIL;
142    return compile(from, outArtifact);
143}
144
145SlangResult TintDownstreamCompiler::getVersionString(slang::IBlob** /* outVersionString */)
146{
147    // We just use Tint at whatever version is in our Dawn fork, so nobody should
148    // depend on the particular version at the moment.
149    return SLANG_FAIL;
150}
151
152} // namespace Slang