yum-mirror/slang

Making it easier to work with shaders

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

jarcherNVAdd static functions to create blobs from data (#8179)af27de015

master
11.2 KiB370 linesraw
1// unit-test-ir-blob.cpp
2
3#include "slang-com-ptr.h"
4#include "slang.h"
5#include "unit-test/slang-unit-test.h"
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11using namespace Slang;
12
13// Test the slang_loadModuleFromIRBlob and slang_loadModuleInfoFromIRBlob functions
14SLANG_UNIT_TEST(irBlob)
15{
16    // Test source code for creating IR data
17    const char* testModuleSource = R"(
18        module test_ir_module;
19
20        public struct TestStruct {
21            float x, y, z;
22        }
23
24        public void testFunction(TestStruct input) {
25            // Simple function
26        }
27
28        public static const float PI = 3.14159;
29    )";
30
31    ComPtr<slang::IGlobalSession> globalSession;
32    SLANG_CHECK(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK);
33
34    slang::SessionDesc sessionDesc = {};
35    sessionDesc.targetCount = 1;
36    slang::TargetDesc targetDesc = {};
37    targetDesc.format = SLANG_SPIRV;
38    targetDesc.profile = globalSession->findProfile("spirv_1_5");
39    sessionDesc.targets = &targetDesc;
40
41    ComPtr<slang::ISession> session;
42    SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK);
43
44    // Create IR data by serializing a module
45    ComPtr<ISlangBlob> irBlob;
46    {
47        ComPtr<slang::IModule> module;
48        ComPtr<ISlangBlob> diagnostics;
49
50        module = session->loadModuleFromSourceString(
51            "test_ir_module",
52            "test_ir_module.slang",
53            testModuleSource,
54            diagnostics.writeRef());
55
56        SLANG_CHECK(module != nullptr);
57        if (diagnostics && diagnostics->getBufferSize() > 0)
58        {
59            // Log diagnostics if any
60            printf(
61                "Module compilation diagnostics: %.*s\n",
62                (int)diagnostics->getBufferSize(),
63                (const char*)diagnostics->getBufferPointer());
64        }
65
66        // Serialize the module to create IR data
67        SLANG_CHECK(module->serialize(irBlob.writeRef()) == SLANG_OK);
68        SLANG_CHECK(irBlob != nullptr);
69        SLANG_CHECK(irBlob->getBufferSize() > 0);
70    }
71
72    // Test 1: Test slang_loadModuleFromIRBlob with valid IR data
73    {
74        ComPtr<slang::IModule> loadedModule;
75        ComPtr<ISlangBlob> diagnostics;
76
77        loadedModule = slang_loadModuleFromIRBlob(
78            session,
79            "test_ir_module_loaded",
80            "test_ir_module_loaded.slang",
81            irBlob->getBufferPointer(),
82            irBlob->getBufferSize(),
83            diagnostics.writeRef());
84
85        SLANG_CHECK(loadedModule != nullptr);
86        if (diagnostics && diagnostics->getBufferSize() > 0)
87        {
88            // Log diagnostics if any
89            printf(
90                "IR blob loading diagnostics: %.*s\n",
91                (int)diagnostics->getBufferSize(),
92                (const char*)diagnostics->getBufferPointer());
93        }
94
95        // Verify the loaded module is valid
96        SLANG_CHECK(loadedModule != nullptr);
97    }
98
99    // Test 2: Test slang_loadModuleInfoFromIRBlob with valid IR data
100    {
101        SlangInt moduleVersion;
102        const char* moduleCompilerVersion;
103        const char* moduleName;
104
105        SlangResult result = slang_loadModuleInfoFromIRBlob(
106            session,
107            irBlob->getBufferPointer(),
108            irBlob->getBufferSize(),
109            moduleVersion,
110            moduleCompilerVersion,
111            moduleName);
112
113        SLANG_CHECK(result == SLANG_OK);
114        SLANG_CHECK(moduleName != nullptr);
115        SLANG_CHECK(strcmp(moduleName, "test_ir_module") == 0);
116        SLANG_CHECK(moduleCompilerVersion != nullptr);
117        SLANG_CHECK(moduleVersion >= 0);
118    }
119
120    // Test 3: Test slang_loadModuleFromIRBlob with invalid parameters
121    {
122        ComPtr<slang::IModule> module;
123        ComPtr<ISlangBlob> diagnostics;
124
125        // Test with null session
126        module = slang_loadModuleFromIRBlob(
127            nullptr,
128            "testModule",
129            "test.slang",
130            irBlob->getBufferPointer(),
131            irBlob->getBufferSize(),
132            diagnostics.writeRef());
133
134        SLANG_CHECK(module == nullptr);
135
136        // Test with null moduleName
137        module = slang_loadModuleFromIRBlob(
138            session,
139            nullptr,
140            "test.slang",
141            irBlob->getBufferPointer(),
142            irBlob->getBufferSize(),
143            diagnostics.writeRef());
144
145        SLANG_CHECK(module == nullptr);
146
147        // Test with null path
148        module = slang_loadModuleFromIRBlob(
149            session,
150            "testModule",
151            nullptr,
152            irBlob->getBufferPointer(),
153            irBlob->getBufferSize(),
154            diagnostics.writeRef());
155
156        SLANG_CHECK(module == nullptr);
157
158        // Test with null source
159        module = slang_loadModuleFromIRBlob(
160            session,
161            "testModule",
162            "test.slang",
163            nullptr,
164            irBlob->getBufferSize(),
165            diagnostics.writeRef());
166
167        SLANG_CHECK(module == nullptr);
168
169        // Test with zero size
170        module = slang_loadModuleFromIRBlob(
171            session,
172            "testModule",
173            "test.slang",
174            irBlob->getBufferPointer(),
175            0,
176            diagnostics.writeRef());
177
178        SLANG_CHECK(module == nullptr);
179    }
180
181    // Test 4: Test slang_loadModuleInfoFromIRBlob with invalid parameters
182    {
183        SlangInt moduleVersion;
184        const char* moduleCompilerVersion;
185        const char* moduleName;
186
187        // Test with null session
188        SlangResult result = slang_loadModuleInfoFromIRBlob(
189            nullptr,
190            irBlob->getBufferPointer(),
191            irBlob->getBufferSize(),
192            moduleVersion,
193            moduleCompilerVersion,
194            moduleName);
195
196        SLANG_CHECK(result == SLANG_E_INVALID_ARG);
197
198        // Test with null source
199        result = slang_loadModuleInfoFromIRBlob(
200            session,
201            nullptr,
202            irBlob->getBufferSize(),
203            moduleVersion,
204            moduleCompilerVersion,
205            moduleName);
206
207        SLANG_CHECK(result == SLANG_E_INVALID_ARG);
208
209        // Test with zero size
210        result = slang_loadModuleInfoFromIRBlob(
211            session,
212            irBlob->getBufferPointer(),
213            0,
214            moduleVersion,
215            moduleCompilerVersion,
216            moduleName);
217
218        SLANG_CHECK(result == SLANG_E_INVALID_ARG);
219    }
220
221    // Test 5: Test with corrupted/invalid IR data
222    {
223        ComPtr<slang::IModule> module;
224        ComPtr<ISlangBlob> diagnostics;
225
226        // Create some invalid data
227        const char* invalidData = "This is not valid IR data";
228        size_t invalidDataSize = strlen(invalidData);
229
230        module = slang_loadModuleFromIRBlob(
231            session,
232            "testModule",
233            "test.slang",
234            invalidData,
235            invalidDataSize,
236            diagnostics.writeRef());
237
238        // This might return nullptr or a module with diagnostics
239        if (module == nullptr)
240        {
241            // If it failed, that's expected for invalid data
242            SLANG_CHECK(true);
243        }
244        else
245        {
246            // If it succeeded, there should be diagnostics
247            if (diagnostics && diagnostics->getBufferSize() > 0)
248            {
249                SLANG_CHECK(true);
250            }
251        }
252    }
253
254    // Test 6: Test slang_loadModuleInfoFromIRBlob with corrupted/invalid IR data
255    {
256        SlangInt moduleVersion;
257        const char* moduleCompilerVersion;
258        const char* moduleName;
259
260        // Create some invalid data
261        const char* invalidData = "This is not valid IR data";
262        size_t invalidDataSize = strlen(invalidData);
263
264        SlangResult result = slang_loadModuleInfoFromIRBlob(
265            session,
266            invalidData,
267            invalidDataSize,
268            moduleVersion,
269            moduleCompilerVersion,
270            moduleName);
271
272        // This should fail with invalid data
273        SLANG_CHECK(result != SLANG_OK);
274    }
275
276    // Test 7: Test round-trip serialization and loading
277    {
278        // Load the module from IR
279        ComPtr<slang::IModule> loadedModule;
280        ComPtr<ISlangBlob> diagnostics;
281
282        loadedModule = slang_loadModuleFromIRBlob(
283            session,
284            "test_round_trip",
285            "test_round_trip.slang",
286            irBlob->getBufferPointer(),
287            irBlob->getBufferSize(),
288            diagnostics.writeRef());
289
290        SLANG_CHECK(loadedModule != nullptr);
291
292        if (loadedModule)
293        {
294            // Serialize the loaded module again
295            ComPtr<ISlangBlob> roundTripBlob;
296            SLANG_CHECK(loadedModule->serialize(roundTripBlob.writeRef()) == SLANG_OK);
297            SLANG_CHECK(roundTripBlob != nullptr);
298            SLANG_CHECK(roundTripBlob->getBufferSize() > 0);
299
300            // Load it again
301            ComPtr<slang::IModule> roundTripModule;
302            roundTripModule = slang_loadModuleFromIRBlob(
303                session,
304                "test_round_trip_2",
305                "test_round_trip_2.slang",
306                roundTripBlob->getBufferPointer(),
307                roundTripBlob->getBufferSize(),
308                diagnostics.writeRef());
309
310            SLANG_CHECK(roundTripModule != nullptr);
311        }
312    }
313
314    // Test 8: Test multiple modules with different IR data
315    {
316        // Create a second module with different content
317        const char* testModuleSource2 = R"(
318            module test_ir_module_2;
319
320            public struct AnotherStruct {
321                int a, b, c;
322            }
323
324            public void anotherFunction(AnotherStruct input) {
325                // Another function
326            }
327        )";
328
329        ComPtr<slang::IModule> module2;
330        ComPtr<ISlangBlob> diagnostics2;
331        ComPtr<ISlangBlob> irBlob2;
332
333        module2 = session->loadModuleFromSourceString(
334            "test_ir_module_2",
335            "test_ir_module_2.slang",
336            testModuleSource2,
337            diagnostics2.writeRef());
338
339        SLANG_CHECK(module2 != nullptr);
340        SLANG_CHECK(module2->serialize(irBlob2.writeRef()) == SLANG_OK);
341
342        // Load both modules
343        ComPtr<slang::IModule> loadedModule1;
344        ComPtr<slang::IModule> loadedModule2;
345        ComPtr<ISlangBlob> diagnostics;
346
347        loadedModule1 = slang_loadModuleFromIRBlob(
348            session,
349            "test_ir_module_1_loaded",
350            "test_ir_module_1_loaded.slang",
351            irBlob->getBufferPointer(),
352            irBlob->getBufferSize(),
353            diagnostics.writeRef());
354
355        loadedModule2 = slang_loadModuleFromIRBlob(
356            session,
357            "test_ir_module_2_loaded",
358            "test_ir_module_2_loaded.slang",
359            irBlob2->getBufferPointer(),
360            irBlob2->getBufferSize(),
361            diagnostics.writeRef());
362
363        SLANG_CHECK(loadedModule1 != nullptr);
364        SLANG_CHECK(loadedModule2 != nullptr);
365
366        // Verify both modules loaded successfully
367        SLANG_CHECK(loadedModule1 != nullptr);
368        SLANG_CHECK(loadedModule2 != nullptr);
369    }
370}