yum-mirror/slang

Making it easier to work with shaders

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

Yong HeAdd Slang Byte Code generation and interpreter. (#6896)c39c29bf4

master
6.6 KiB232 linesraw
1// main.cpp
2
3// This file implements the entry point for `slangi`, an interpreter for the Slang language.
4
5#include "../../source/core/slang-basic.h"
6#include "core/slang-io.h"
7#include "slang-com-ptr.h"
8#include "slang.h"
9
10using namespace Slang;
11using namespace slang;
12
13void printUsage()
14{
15    printf("Slang Interpreter (Experimental)\n");
16    printf("Compile and interpret Slang code.\n");
17    printf("Usage: slangi [options] <filename>\n");
18    printf("Options:\n");
19    printf("  -entry <name>   Specify the entry point function name to run. (default: main)\n");
20    printf("  -disasm         Disassemble the bytecode after compilation.\n");
21    printf("  -help           Show this help message\n");
22}
23
24void maybePrintDiagnostic(const ComPtr<slang::IBlob>& diagnosticBlob)
25{
26    if (diagnosticBlob)
27    {
28        const char* diagText = (const char*)diagnosticBlob->getBufferPointer();
29        fprintf(stderr, "%s\n", diagText);
30    }
31}
32
33SlangResult compileAndInterpret(
34    UnownedStringSlice fileName,
35    const char* entryPointName,
36    bool disasm,
37    int argc,
38    const char* const* argv)
39{
40    ComPtr<slang::IGlobalSession> globalSession;
41    SLANG_RETURN_ON_FAIL(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()));
42    slang::TargetDesc targetDesc = {};
43    targetDesc.format = SLANG_HOST_VM;
44    slang::SessionDesc sessionDesc = {};
45    sessionDesc.targetCount = 1;
46    sessionDesc.targets = &targetDesc;
47    sessionDesc.compilerOptionEntryCount = 0;
48    String pathName = Path::getParentDirectory(fileName);
49    String moduleName = Path::getFileNameWithoutExt(fileName);
50    const char* searchPaths[] = {pathName.getBuffer()};
51    if (pathName.getLength())
52    {
53        sessionDesc.searchPathCount = 1;
54        sessionDesc.searchPaths = searchPaths;
55    }
56    ComPtr<slang::ISession> session;
57    SLANG_RETURN_ON_FAIL(globalSession->createSession(sessionDesc, session.writeRef()));
58
59    ComPtr<slang::IBlob> diagnosticBlob;
60    auto module = session->loadModule(moduleName.getBuffer(), diagnosticBlob.writeRef());
61    if (!module)
62    {
63        maybePrintDiagnostic(diagnosticBlob);
64        return SLANG_FAIL;
65    }
66    ComPtr<slang::IEntryPoint> entryPoint;
67    if (SLANG_FAILED(module->findAndCheckEntryPoint(
68            entryPointName,
69            SLANG_STAGE_DISPATCH,
70            entryPoint.writeRef(),
71            diagnosticBlob.writeRef())))
72    {
73        maybePrintDiagnostic(diagnosticBlob);
74        return SLANG_FAIL;
75    }
76
77    ComPtr<slang::IComponentType> compositeComponent;
78    slang::IComponentType* components[] = {module, entryPoint.get()};
79    if (SLANG_FAILED(session->createCompositeComponentType(
80            components,
81            2,
82            compositeComponent.writeRef(),
83            diagnosticBlob.writeRef())))
84    {
85        maybePrintDiagnostic(diagnosticBlob);
86        return SLANG_FAIL;
87    }
88
89    ComPtr<slang::IComponentType> linkedProgram;
90    if (SLANG_FAILED(compositeComponent->link(linkedProgram.writeRef(), diagnosticBlob.writeRef())))
91    {
92        maybePrintDiagnostic(diagnosticBlob);
93        return SLANG_FAIL;
94    }
95    ComPtr<slang::IBlob> code;
96
97    if (SLANG_FAILED(linkedProgram->getTargetCode(0, code.writeRef(), diagnosticBlob.writeRef())))
98    {
99        maybePrintDiagnostic(diagnosticBlob);
100        return SLANG_FAIL;
101    }
102
103    if (code->getBufferSize() == 0)
104    {
105        return SLANG_FAIL;
106    }
107
108    if (disasm)
109    {
110        ComPtr<slang::IBlob> disasmBlob;
111        if (SLANG_FAILED(slang_disassembleByteCode(code, disasmBlob.writeRef())))
112        {
113            maybePrintDiagnostic(diagnosticBlob);
114            return SLANG_FAIL;
115        }
116        const char* disasmText = (const char*)disasmBlob->getBufferPointer();
117        printf("%s\n", disasmText);
118    }
119
120    // Create a byte code runner and interpret the code.
121    ComPtr<slang::IByteCodeRunner> runner;
122    slang::ByteCodeRunnerDesc runnerDesc = {};
123    SLANG_RETURN_ON_FAIL(slang_createByteCodeRunner(&runnerDesc, runner.writeRef()));
124    if (SLANG_FAILED(runner->loadModule(code)))
125    {
126        runner->getErrorString(diagnosticBlob.writeRef());
127        maybePrintDiagnostic(diagnosticBlob);
128    }
129    auto funcIndex = runner->findFunctionByName(entryPointName);
130    if (funcIndex < 0)
131    {
132        printf("Function '%s' not found in byte code.\n", entryPointName);
133        return SLANG_FAIL;
134    }
135
136    if (SLANG_FAILED(runner->selectFunctionByIndex((uint32_t)funcIndex)))
137    {
138        runner->getErrorString(diagnosticBlob.writeRef());
139        maybePrintDiagnostic(diagnosticBlob);
140        return SLANG_FAIL;
141    }
142
143    struct Arguments
144    {
145        uint32_t argc;
146        const char* const* argv;
147    };
148    Arguments args;
149    args.argc = argc;
150    args.argv = argv;
151    void* arguments = nullptr;
152    size_t argSize = 0;
153    slang::ByteCodeFuncInfo funcInfo;
154    if (SLANG_FAILED(runner->getFunctionInfo((uint32_t)funcIndex, &funcInfo)))
155    {
156        runner->getErrorString(diagnosticBlob.writeRef());
157        maybePrintDiagnostic(diagnosticBlob);
158        return SLANG_FAIL;
159    }
160    if (funcInfo.parameterCount == 2)
161    {
162        arguments = &args;
163        argSize = sizeof(Arguments);
164    }
165    if (SLANG_FAILED(runner->execute(arguments, argSize)))
166    {
167        runner->getErrorString(diagnosticBlob.writeRef());
168        maybePrintDiagnostic(diagnosticBlob);
169        return SLANG_FAIL;
170    }
171    size_t returnValueSize = 0;
172    void* returnVal = runner->getReturnValue(&returnValueSize);
173    SlangResult result = SLANG_OK;
174    memcpy(&result, returnVal, returnValueSize);
175    return result;
176}
177
178int main(int argc, const char* const* argv)
179{
180    String entryPointName = toSlice("main");
181    UnownedStringSlice fileName;
182    bool disasm = false;
183    int innerArgIndex = 0;
184    if (argc < 2)
185    {
186        printUsage();
187        return 0;
188    }
189    for (auto i = 1; i < argc; i++)
190    {
191        auto arg = UnownedStringSlice(argv[i]);
192        if (arg == "-entry")
193        {
194            entryPointName = UnownedStringSlice(argv[++i]);
195        }
196        else if (arg == "-help" || arg == "--help")
197        {
198            printUsage();
199            return 0;
200        }
201        else if (arg == "-disasm")
202        {
203            disasm = true;
204        }
205        else if (arg.startsWith("-"))
206        {
207            fprintf(stderr, "Unknown option: %s\n", arg.begin());
208            printUsage();
209            return -1;
210        }
211        else
212        {
213            fileName = arg;
214            innerArgIndex = i;
215            break;
216        }
217    }
218    if (!fileName.getLength())
219    {
220        printUsage();
221        return 0;
222    }
223
224    auto result = compileAndInterpret(
225        fileName,
226        entryPointName.getBuffer(),
227        disasm,
228        argc - innerArgIndex,
229        argv + innerArgIndex);
230    slang::shutdown();
231    return result;
232}