yum-mirror/slang

Making it easier to work with shaders

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

Jay KwakFail slang-test when VVL printed errors (#8280)1681bc67f

master
10.7 KiB312 linesraw
1#include "gfx-test-util.h"
2
3#include "slang-com-ptr.h"
4#include "unit-test/slang-unit-test.h"
5
6#define GFX_ENABLE_RENDERDOC_INTEGRATION 0
7#define GFX_ENABLE_SPIRV_DEBUG 0
8#if GFX_ENABLE_RENDERDOC_INTEGRATION
9#include "external/renderdoc_app.h"
10
11#include <windows.h>
12#endif
13
14using Slang::ComPtr;
15
16namespace gfx_test
17{
18
19void diagnoseIfNeeded(slang::IBlob* diagnosticsBlob)
20{
21    if (diagnosticsBlob != nullptr)
22    {
23        getTestReporter()->message(
24            TestMessageType::Info,
25            (const char*)diagnosticsBlob->getBufferPointer());
26    }
27}
28
29Result loadComputeProgram(
30    IDevice* device,
31    ComPtr<IShaderProgram>& outShaderProgram,
32    const char* shaderModuleName,
33    const char* entryPointName,
34    slang::ProgramLayout*& slangReflection)
35{
36    ComPtr<slang::ISession> slangSession;
37    SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef()));
38    ComPtr<slang::IBlob> diagnosticsBlob;
39    slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef());
40    diagnoseIfNeeded(diagnosticsBlob);
41    if (!module)
42        return SLANG_FAIL;
43
44    ComPtr<slang::IEntryPoint> computeEntryPoint;
45    SLANG_RETURN_ON_FAIL(
46        module->findEntryPointByName(entryPointName, computeEntryPoint.writeRef()));
47
48    std::vector<slang::IComponentType*> componentTypes;
49    componentTypes.push_back(module);
50    componentTypes.push_back(computeEntryPoint);
51
52    ComPtr<slang::IComponentType> composedProgram;
53    Result result = slangSession->createCompositeComponentType(
54        componentTypes.data(),
55        componentTypes.size(),
56        composedProgram.writeRef(),
57        diagnosticsBlob.writeRef());
58    diagnoseIfNeeded(diagnosticsBlob);
59    SLANG_RETURN_ON_FAIL(result);
60
61    ComPtr<slang::IComponentType> linkedProgram;
62    result = composedProgram->link(linkedProgram.writeRef(), diagnosticsBlob.writeRef());
63    diagnoseIfNeeded(diagnosticsBlob);
64    SLANG_RETURN_ON_FAIL(result);
65
66    slangReflection = linkedProgram->getLayout();
67    outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
68    diagnoseIfNeeded(diagnosticsBlob);
69    return outShaderProgram ? SLANG_OK : SLANG_FAIL;
70}
71
72Result loadComputeProgram(
73    IDevice* device,
74    slang::ISession* slangSession,
75    ComPtr<IShaderProgram>& outShaderProgram,
76    const char* shaderModuleName,
77    const char* entryPointName,
78    slang::ProgramLayout*& slangReflection)
79{
80    ComPtr<slang::IBlob> diagnosticsBlob;
81    slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef());
82    diagnoseIfNeeded(diagnosticsBlob);
83    if (!module)
84        return SLANG_FAIL;
85
86    ComPtr<slang::IEntryPoint> computeEntryPoint;
87    SLANG_RETURN_ON_FAIL(
88        module->findEntryPointByName(entryPointName, computeEntryPoint.writeRef()));
89
90    std::vector<slang::IComponentType*> componentTypes;
91    componentTypes.push_back(module);
92    componentTypes.push_back(computeEntryPoint);
93
94    ComPtr<slang::IComponentType> composedProgram;
95    Result result = slangSession->createCompositeComponentType(
96        componentTypes.data(),
97        componentTypes.size(),
98        composedProgram.writeRef(),
99        diagnosticsBlob.writeRef());
100    diagnoseIfNeeded(diagnosticsBlob);
101    SLANG_RETURN_ON_FAIL(result);
102
103    ComPtr<slang::IComponentType> linkedProgram;
104    result = composedProgram->link(linkedProgram.writeRef(), diagnosticsBlob.writeRef());
105    diagnoseIfNeeded(diagnosticsBlob);
106    SLANG_RETURN_ON_FAIL(result);
107
108    slangReflection = linkedProgram->getLayout();
109    outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
110    diagnoseIfNeeded(diagnosticsBlob);
111    return outShaderProgram ? SLANG_OK : SLANG_FAIL;
112}
113
114Result loadComputeProgramFromSource(
115    IDevice* device,
116    ComPtr<IShaderProgram>& outShaderProgram,
117    std::string_view source)
118{
119    auto slangSession = device->getSlangSession();
120    slang::IModule* module = nullptr;
121    ComPtr<slang::IBlob> diagnosticsBlob;
122    size_t hash = std::hash<std::string_view>()(source);
123    std::string moduleName = "source_module_" + std::to_string(hash);
124    auto srcBlob = Slang::UnownedRawBlob::create(source.data(), source.size());
125    module = slangSession->loadModuleFromSource(
126        moduleName.data(),
127        moduleName.data(),
128        srcBlob,
129        diagnosticsBlob.writeRef());
130    diagnoseIfNeeded(diagnosticsBlob);
131    if (!module)
132        return SLANG_FAIL;
133
134    std::vector<ComPtr<slang::IComponentType>> componentTypes;
135    componentTypes.push_back(ComPtr<slang::IComponentType>(module));
136
137    for (SlangInt32 i = 0; i < module->getDefinedEntryPointCount(); i++)
138    {
139        ComPtr<slang::IEntryPoint> entryPoint;
140        SLANG_RETURN_ON_FAIL(module->getDefinedEntryPoint(i, entryPoint.writeRef()));
141        componentTypes.push_back(ComPtr<slang::IComponentType>(entryPoint.get()));
142    }
143
144    std::vector<slang::IComponentType*> rawComponentTypes;
145    for (auto& compType : componentTypes)
146        rawComponentTypes.push_back(compType.get());
147
148    ComPtr<slang::IComponentType> linkedProgram;
149    Result result = slangSession->createCompositeComponentType(
150        rawComponentTypes.data(),
151        rawComponentTypes.size(),
152        linkedProgram.writeRef(),
153        diagnosticsBlob.writeRef());
154    diagnoseIfNeeded(diagnosticsBlob);
155    SLANG_RETURN_ON_FAIL(result);
156
157    outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
158    diagnoseIfNeeded(diagnosticsBlob);
159    return outShaderProgram ? SLANG_OK : SLANG_FAIL;
160}
161
162Result loadGraphicsProgram(
163    IDevice* device,
164    ComPtr<IShaderProgram>& outShaderProgram,
165    const char* shaderModuleName,
166    const char* vertexEntryPointName,
167    const char* fragmentEntryPointName,
168    slang::ProgramLayout*& slangReflection)
169{
170    ComPtr<slang::ISession> slangSession;
171    SLANG_RETURN_ON_FAIL(device->getSlangSession(slangSession.writeRef()));
172    ComPtr<slang::IBlob> diagnosticsBlob;
173    slang::IModule* module = slangSession->loadModule(shaderModuleName, diagnosticsBlob.writeRef());
174    diagnoseIfNeeded(diagnosticsBlob);
175    if (!module)
176        return SLANG_FAIL;
177
178    ComPtr<slang::IEntryPoint> vertexEntryPoint;
179    SLANG_RETURN_ON_FAIL(
180        module->findEntryPointByName(vertexEntryPointName, vertexEntryPoint.writeRef()));
181
182    ComPtr<slang::IEntryPoint> fragmentEntryPoint;
183    SLANG_RETURN_ON_FAIL(
184        module->findEntryPointByName(fragmentEntryPointName, fragmentEntryPoint.writeRef()));
185
186    std::vector<slang::IComponentType*> componentTypes;
187    componentTypes.push_back(module);
188    componentTypes.push_back(vertexEntryPoint);
189    componentTypes.push_back(fragmentEntryPoint);
190
191    ComPtr<slang::IComponentType> composedProgram;
192    Result result = slangSession->createCompositeComponentType(
193        componentTypes.data(),
194        componentTypes.size(),
195        composedProgram.writeRef(),
196        diagnosticsBlob.writeRef());
197    diagnoseIfNeeded(diagnosticsBlob);
198    SLANG_RETURN_ON_FAIL(result);
199
200    ComPtr<slang::IComponentType> linkedProgram;
201    result = composedProgram->link(linkedProgram.writeRef(), diagnosticsBlob.writeRef());
202    diagnoseIfNeeded(diagnosticsBlob);
203    SLANG_RETURN_ON_FAIL(result);
204
205    slangReflection = linkedProgram->getLayout();
206    outShaderProgram = device->createShaderProgram(linkedProgram, diagnosticsBlob.writeRef());
207    diagnoseIfNeeded(diagnosticsBlob);
208    return outShaderProgram ? SLANG_OK : SLANG_FAIL;
209}
210
211Slang::ComPtr<IDevice> createTestingDevice(
212    UnitTestContext* context,
213    DeviceType deviceType,
214    Slang::List<const char*> additionalSearchPaths)
215{
216    Slang::ComPtr<IDevice> device;
217    DeviceDesc deviceDesc = {};
218    deviceDesc.deviceType = deviceType;
219
220    deviceDesc.slang.slangGlobalSession = context->slangGlobalSession;
221    Slang::List<const char*> searchPaths = getSlangSearchPaths();
222    searchPaths.addRange(additionalSearchPaths);
223    deviceDesc.slang.searchPaths = searchPaths.getBuffer();
224    deviceDesc.slang.searchPathCount = searchPaths.getCount();
225
226    std::vector<slang::PreprocessorMacroDesc> preprocessorMacros;
227    std::vector<slang::CompilerOptionEntry> compilerOptions;
228
229    slang::CompilerOptionEntry emitSpirvDirectlyEntry;
230    emitSpirvDirectlyEntry.name = slang::CompilerOptionName::EmitSpirvDirectly;
231    emitSpirvDirectlyEntry.value.intValue0 = 1;
232    compilerOptions.push_back(emitSpirvDirectlyEntry);
233#if DEBUG_SPIRV
234    slang::CompilerOptionEntry debugLevelCompilerOptionEntry = {};
235    debugLevelCompilerOptionEntry.name = slang::CompilerOptionName::DebugInformation;
236    debugLevelCompilerOptionEntry.value.intValue0 = SLANG_DEBUG_INFO_LEVEL_STANDARD;
237    compilerOptions.push_back(debugLevelCompilerOptionEntry);
238#endif
239#if DUMP_INTERMEDIATES
240    slang::CompilerOptionEntry dumpIntermediatesOptionEntry = {};
241    dumpIntermediatesOptionEntry.name = slang::CompilerOptionName::DumpIntermediates;
242    dumpIntermediatesOptionEntry.value.intValue0 = 1;
243    compilerOptions.push_back(dumpIntermediatesOptionEntry);
244#endif
245
246    deviceDesc.slang.preprocessorMacros = preprocessorMacros.data();
247    deviceDesc.slang.preprocessorMacroCount = preprocessorMacros.size();
248    deviceDesc.slang.compilerOptionEntries = compilerOptions.data();
249    deviceDesc.slang.compilerOptionEntryCount = compilerOptions.size();
250
251    if (context->enableDebugLayers)
252    {
253        deviceDesc.enableValidation = context->enableDebugLayers;
254        deviceDesc.debugCallback = context->debugCallback;
255        getRHI()->enableDebugLayers();
256    }
257
258    D3D12DeviceExtendedDesc extDesc = {};
259    if (deviceType == DeviceType::D3D12)
260    {
261        extDesc.rootParameterShaderAttributeName = "root";
262        deviceDesc.next = &extDesc;
263    }
264
265    auto createDeviceResult = getRHI()->createDevice(deviceDesc, device.writeRef());
266    if (SLANG_FAILED(createDeviceResult))
267    {
268        SLANG_IGNORE_TEST
269    }
270    return device;
271}
272
273Slang::List<const char*> getSlangSearchPaths()
274{
275    Slang::List<const char*> searchPaths;
276    searchPaths.add("");
277    searchPaths.add("../../tools/gfx-unit-test");
278    searchPaths.add("tools/gfx-unit-test");
279    return searchPaths;
280}
281
282#if GFX_ENABLE_RENDERDOC_INTEGRATION
283RENDERDOC_API_1_1_2* rdoc_api = NULL;
284void initializeRenderDoc()
285{
286    if (HMODULE mod = GetModuleHandleA("renderdoc.dll"))
287    {
288        pRENDERDOC_GetAPI RENDERDOC_GetAPI =
289            (pRENDERDOC_GetAPI)GetProcAddress(mod, "RENDERDOC_GetAPI");
290        int ret = RENDERDOC_GetAPI(eRENDERDOC_API_Version_1_1_2, (void**)&rdoc_api);
291        assert(ret == 1);
292    }
293}
294void renderDocBeginFrame()
295{
296    if (!rdoc_api)
297        initializeRenderDoc();
298    if (rdoc_api)
299        rdoc_api->StartFrameCapture(nullptr, nullptr);
300}
301void renderDocEndFrame()
302{
303    if (rdoc_api)
304        rdoc_api->EndFrameCapture(nullptr, nullptr);
305    _fgetchar();
306}
307#else
308void initializeRenderDoc() {}
309void renderDocBeginFrame() {}
310void renderDocEndFrame() {}
311#endif
312} // namespace gfx_test