yum-mirror/slang

Making it easier to work with shaders

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

RonanAdded getCanonicalGenericConstraints2 (sorts constraints and allows more generic expressions) (#6787)a5efbb1b7

master
22.7 KiB534 linesraw
1// unit-test-translation-unit-import.cpp
2
3#include "../../source/core/slang-io.h"
4#include "../../source/core/slang-process.h"
5#include "slang-com-ptr.h"
6#include "slang.h"
7#include "unit-test/slang-unit-test.h"
8
9#include <stdio.h>
10#include <stdlib.h>
11
12using namespace Slang;
13
14static String getTypeFullName(slang::TypeReflection* type)
15{
16    ComPtr<ISlangBlob> blob;
17    type->getFullName(blob.writeRef());
18    return String((const char*)blob->getBufferPointer());
19}
20
21static void printRefl(slang::DeclReflection* refl, unsigned int level = 0)
22{
23    // Mapping of kind ids to names
24    std::string names[] = {"Unsupported", "Struct", "Function", "Module", "Generic", "Variable"};
25    for (unsigned int i = 0; i < level; i++)
26    {
27        std::cout << "  ";
28    }
29    std::cout << "[" << names[(unsigned int)refl->getKind()] << "] (" << refl->getChildrenCount()
30              << ")" << std::endl;
31
32    for (auto* child : refl->getChildren())
33    {
34        printRefl(child, level + 1);
35    }
36}
37
38// Test that the reflection API provides correct info about entry point and ordinary functions.
39
40SLANG_UNIT_TEST(declTreeReflection)
41{
42    // Source for a module that contains an undecorated entrypoint.
43    const char* userSourceBody = R"(
44        [__AttributeUsage(_AttributeTargets.Function)]
45        struct MyFuncPropertyAttribute {int v;}
46
47        [MyFuncProperty(1024)]
48        [Differentiable]
49        float ordinaryFunc(no_diff float x, int y) { return x + y; }
50
51        float4 fragMain(float4 pos:SV_Position) : SV_Position
52        {
53            return pos;
54        }
55
56        uint f(uint y) { return y; }
57
58        struct MyType
59        {
60            int x;
61            float f(float x) { return x; }
62        }
63
64        struct MyGenericType<T : IArithmetic & IFloat>
65        {
66            T z;
67
68            __init(T _z) { z = _z; }
69            
70            T g() { return z; }
71            U h<U>(U x, out T y) { y = z; return x; }
72
73            T j<let N : int>(T x, out int o) { o = N; return x; }
74
75            U q<U>(U x, T y) { return x; }
76        }
77
78        namespace MyNamespace
79        {
80            struct MyStruct
81            {
82                int x;
83            }
84        }
85
86        T foo<T, U>(T t, U u) { return t; }
87
88        )";
89
90    auto moduleName = "moduleG" + String(Process::getId());
91    String userSource = "import " + moduleName + ";\n" + userSourceBody;
92    ComPtr<slang::IGlobalSession> globalSession;
93    SLANG_CHECK(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK);
94    slang::TargetDesc targetDesc = {};
95    targetDesc.format = SLANG_HLSL;
96    targetDesc.profile = globalSession->findProfile("sm_5_0");
97    slang::SessionDesc sessionDesc = {};
98    sessionDesc.targetCount = 1;
99    sessionDesc.targets = &targetDesc;
100    ComPtr<slang::ISession> session;
101    SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK);
102
103    ComPtr<slang::IBlob> diagnosticBlob;
104    auto module = session->loadModuleFromSourceString(
105        "m",
106        "m.slang",
107        userSourceBody,
108        diagnosticBlob.writeRef());
109    SLANG_CHECK(module != nullptr);
110
111    ComPtr<slang::IEntryPoint> entryPoint;
112    module->findAndCheckEntryPoint(
113        "fragMain",
114        SLANG_STAGE_FRAGMENT,
115        entryPoint.writeRef(),
116        diagnosticBlob.writeRef());
117    SLANG_CHECK(entryPoint != nullptr);
118
119    ComPtr<slang::IComponentType> compositeProgram;
120    slang::IComponentType* components[] = {module, entryPoint.get()};
121    session->createCompositeComponentType(
122        components,
123        2,
124        compositeProgram.writeRef(),
125        diagnosticBlob.writeRef());
126    SLANG_CHECK(compositeProgram != nullptr);
127
128    auto moduleDeclReflection = module->getModuleReflection();
129    SLANG_CHECK(moduleDeclReflection != nullptr);
130    SLANG_CHECK(moduleDeclReflection->getKind() == slang::DeclReflection::Kind::Module);
131    SLANG_CHECK(moduleDeclReflection->getChildrenCount() == 9);
132
133    // First declaration should be a struct with 1 variable and a synthesized constructor
134    auto firstDecl = moduleDeclReflection->getChild(0);
135    SLANG_CHECK(firstDecl->getKind() == slang::DeclReflection::Kind::Struct);
136    SLANG_CHECK(firstDecl->getChildrenCount() == 2);
137
138    {
139        slang::TypeReflection* type = firstDecl->getType();
140        SLANG_CHECK(getTypeFullName(type) == "MyFuncPropertyAttribute");
141
142        // Check the field of the struct.
143        SLANG_CHECK(type->getFieldCount() == 1);
144        auto field = type->getFieldByIndex(0);
145        SLANG_CHECK(UnownedStringSlice(field->getName()) == "v");
146        SLANG_CHECK(getTypeFullName(field->getType()) == "int");
147    }
148
149    // Second declaration should be a function
150    auto secondDecl = moduleDeclReflection->getChild(1);
151    SLANG_CHECK(secondDecl->getKind() == slang::DeclReflection::Kind::Func);
152    SLANG_CHECK(
153        secondDecl->getChildrenCount() ==
154        2); // Parameter declarations are children (return type is not)
155
156    {
157        auto funcReflection = secondDecl->asFunction();
158        SLANG_CHECK(funcReflection->findModifier(slang::Modifier::Differentiable) != nullptr);
159        SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "float");
160        SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "ordinaryFunc");
161        SLANG_CHECK(funcReflection->getParameterCount() == 2);
162        SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(0)->getName()) == "x");
163        SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) == "float");
164        SLANG_CHECK(
165            funcReflection->getParameterByIndex(0)->findModifier(slang::Modifier::NoDiff) !=
166            nullptr);
167
168        SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(1)->getName()) == "y");
169        SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(1)->getType()) == "int");
170
171        SLANG_CHECK(funcReflection->getUserAttributeCount() == 1);
172        auto userAttribute = funcReflection->getUserAttributeByIndex(0);
173        SLANG_CHECK(UnownedStringSlice(userAttribute->getName()) == "MyFuncProperty");
174        SLANG_CHECK(userAttribute->getArgumentCount() == 1);
175        SLANG_CHECK(getTypeFullName(userAttribute->getArgumentType(0)) == "int");
176        int val = 0;
177        auto result = userAttribute->getArgumentValueInt(0, &val);
178        SLANG_CHECK(result == SLANG_OK);
179        SLANG_CHECK(val == 1024);
180        SLANG_CHECK(
181            funcReflection->findAttributeByName(globalSession.get(), "MyFuncProperty") ==
182            userAttribute);
183    }
184
185    // Third declaration should also be a function
186    auto thirdDecl = moduleDeclReflection->getChild(2);
187    SLANG_CHECK(thirdDecl->getKind() == slang::DeclReflection::Kind::Func);
188    SLANG_CHECK(thirdDecl->getChildrenCount() == 1);
189
190    {
191        auto funcReflection = thirdDecl->asFunction();
192        SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "vector<float,4>");
193        SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "fragMain");
194        SLANG_CHECK(funcReflection->getParameterCount() == 1);
195        SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(0)->getName()) == "pos");
196        SLANG_CHECK(
197            getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) ==
198            "vector<float,4>");
199    }
200
201    // Sixth declaration should be a generic struct
202    auto sixthDecl = moduleDeclReflection->getChild(5);
203    SLANG_CHECK(sixthDecl->getKind() == slang::DeclReflection::Kind::Generic);
204    auto genericReflection = sixthDecl->asGeneric();
205    SLANG_CHECK(genericReflection->getTypeParameterCount() == 1);
206    auto typeParamT = genericReflection->getTypeParameter(0);
207    SLANG_CHECK(UnownedStringSlice(typeParamT->getName()) == "T");
208    auto typeParamTConstraintCount = genericReflection->getTypeParameterConstraintCount(typeParamT);
209    SLANG_CHECK(typeParamTConstraintCount == 2);
210    auto typeParamTConstraintType1 =
211        genericReflection->getTypeParameterConstraintType(typeParamT, 0);
212    SLANG_CHECK(getTypeFullName(typeParamTConstraintType1) == "IFloat");
213    auto typeParamTConstraintType2 =
214        genericReflection->getTypeParameterConstraintType(typeParamT, 1);
215    SLANG_CHECK(getTypeFullName(typeParamTConstraintType2) == "IArithmetic");
216
217    auto innerStruct = genericReflection->getInnerDecl();
218    SLANG_CHECK(innerStruct->getKind() == slang::DeclReflection::Kind::Struct);
219
220    // Check that the seventh declaration is a namespace
221    auto seventhDecl = moduleDeclReflection->getChild(6);
222    SLANG_CHECK(seventhDecl->getKind() == slang::DeclReflection::Kind::Namespace);
223    SLANG_CHECK(UnownedStringSlice(seventhDecl->getName()) == "MyNamespace");
224
225
226    // Check type-lookup-by-name
227    {
228        auto type = compositeProgram->getLayout()->findTypeByName("MyType");
229        SLANG_CHECK(type != nullptr);
230        // SLANG_CHECK(type->getKind() == slang::DeclReflection::Kind::Struct);
231        SLANG_CHECK(UnownedStringSlice(type->getName()) == "MyType");
232        auto funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "f");
233        SLANG_CHECK(funcReflection != nullptr);
234        SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "f");
235        SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "float");
236        SLANG_CHECK(funcReflection->getParameterCount() == 1);
237        SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(0)->getName()) == "x");
238        SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) == "float");
239    }
240
241    // Check type-lookup-by-name for generic type
242    {
243        auto type = compositeProgram->getLayout()->findTypeByName("MyGenericType<half>");
244        SLANG_CHECK(type != nullptr);
245        SLANG_CHECK(getTypeFullName(type) == "MyGenericType<half>");
246        auto funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "g");
247        SLANG_CHECK(funcReflection != nullptr);
248        SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "g");
249        SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "half");
250        SLANG_CHECK(funcReflection->getParameterCount() == 0);
251
252        auto varReflection = compositeProgram->getLayout()->findVarByNameInType(type, "z");
253        SLANG_CHECK(varReflection != nullptr);
254        SLANG_CHECK(UnownedStringSlice(varReflection->getName()) == "z");
255        SLANG_CHECK(getTypeFullName(varReflection->getType()) == "half");
256
257        funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "h<float>");
258        SLANG_CHECK(funcReflection != nullptr);
259        SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "h");
260        SLANG_CHECK(getTypeFullName(funcReflection->getReturnType()) == "float");
261        SLANG_CHECK(funcReflection->getParameterCount() == 2);
262        SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(0)->getName()) == "x");
263        SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(0)->getType()) == "float");
264        SLANG_CHECK(UnownedStringSlice(funcReflection->getParameterByIndex(1)->getName()) == "y");
265        SLANG_CHECK(getTypeFullName(funcReflection->getParameterByIndex(1)->getType()) == "half");
266
267        // Access parent generic container from a specialized method.
268        auto specializationInfo = funcReflection->getGenericContainer();
269        SLANG_CHECK(specializationInfo != nullptr);
270        SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "h");
271        SLANG_CHECK(
272            specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic);
273        // Check type parameters
274        SLANG_CHECK(specializationInfo->getTypeParameterCount() == 1);
275        auto typeParam = specializationInfo->getTypeParameter(0);
276        SLANG_CHECK(UnownedStringSlice(typeParam->getName()) == "U"); // generic name
277        SLANG_CHECK(
278            getTypeFullName(specializationInfo->getConcreteType(typeParam)) ==
279            "float"); // specialized type name under the context in which the generic is obtained
280        SLANG_CHECK(specializationInfo->getTypeParameterConstraintCount(typeParam) == 0);
281
282        // Go up another level to the generic struct
283        specializationInfo = specializationInfo->getOuterGenericContainer();
284        SLANG_CHECK(specializationInfo != nullptr);
285        SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "MyGenericType");
286        SLANG_CHECK(
287            specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic);
288        // Check type parameters
289        SLANG_CHECK(specializationInfo->getTypeParameterCount() == 1);
290        typeParam = specializationInfo->getTypeParameter(0);
291        SLANG_CHECK(UnownedStringSlice(typeParam->getName()) == "T"); // generic name
292        SLANG_CHECK(
293            getTypeFullName(specializationInfo->getConcreteType(typeParam)) ==
294            "half"); // specialized type name under the context in which the generic is obtained
295        SLANG_CHECK(specializationInfo->getTypeParameterConstraintCount(typeParam) == 2);
296
297        // Query 'j' on the type 'half'
298        funcReflection = compositeProgram->getLayout()->findFunctionByNameInType(type, "j<10>");
299        SLANG_CHECK(funcReflection != nullptr);
300        SLANG_CHECK(UnownedStringSlice(funcReflection->getName()) == "j");
301
302        // Check the generic parameters
303        specializationInfo = funcReflection->getGenericContainer();
304        SLANG_CHECK(specializationInfo != nullptr);
305        SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "j");
306        SLANG_CHECK(
307            specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic);
308        SLANG_CHECK(specializationInfo->getValueParameterCount() == 1);
309        auto valueParam = specializationInfo->getValueParameter(0);
310        SLANG_CHECK(UnownedStringSlice(valueParam->getName()) == "N"); // generic name
311        SLANG_CHECK(specializationInfo->getConcreteIntVal(valueParam) == 10);
312    }
313
314    // Check specializeGeneric() and applySpecializations()
315    {
316        auto unspecializedType = compositeProgram->getLayout()->findTypeByName("MyGenericType");
317        SLANG_CHECK(unspecializedType != nullptr);
318        auto halfType = compositeProgram->getLayout()->findTypeByName("half");
319        SLANG_CHECK(halfType != nullptr);
320
321        slang::GenericReflection* genericContainer = unspecializedType->getGenericContainer();
322        SLANG_CHECK(genericContainer != nullptr);
323        // auto typeParamT = genericContainer->getTypeParameter(0);
324
325        List<slang::GenericArgType> argTypes;
326        List<slang::GenericArgReflection> args;
327        argTypes.add(slang::GenericArgType::SLANG_GENERIC_ARG_TYPE);
328        args.add({halfType});
329        auto specializedContainer = compositeProgram->getLayout()->specializeGeneric(
330            genericContainer,
331            argTypes.getCount(),
332            argTypes.getBuffer(),
333            args.getBuffer(),
334            nullptr);
335
336        SLANG_CHECK(specializedContainer != nullptr);
337
338        auto specializedType = unspecializedType->applySpecializations(specializedContainer);
339        SLANG_CHECK(specializedType != nullptr);
340        SLANG_CHECK(getTypeFullName(specializedType) == "MyGenericType<half>");
341    }
342
343    // Check specializeGeneric() and applySpecializations() on multiple levels (generic function
344    // nested in a generic struct)
345    {
346        auto unspecializedType = compositeProgram->getLayout()->findTypeByName("MyGenericType");
347        auto unspecializedFunc =
348            compositeProgram->getLayout()->findFunctionByNameInType(unspecializedType, "j");
349
350        SLANG_CHECK(unspecializedFunc != nullptr);
351        auto halfType = compositeProgram->getLayout()->findTypeByName("half");
352        SLANG_CHECK(halfType != nullptr);
353
354        slang::GenericReflection* genericFuncContainer = unspecializedFunc->getGenericContainer();
355        SLANG_CHECK(genericFuncContainer != nullptr);
356        slang::GenericReflection* genericStructContainer =
357            genericFuncContainer->getOuterGenericContainer();
358        SLANG_CHECK(genericStructContainer != nullptr);
359
360        // Specialize the outer container with half
361        List<slang::GenericArgType> argTypes;
362        List<slang::GenericArgReflection> args;
363        argTypes.add(slang::GenericArgType::SLANG_GENERIC_ARG_TYPE);
364        args.add({halfType});
365        auto specializedStructContainer = compositeProgram->getLayout()->specializeGeneric(
366            genericStructContainer,
367            argTypes.getCount(),
368            argTypes.getBuffer(),
369            args.getBuffer(),
370            nullptr);
371        SLANG_CHECK(specializedStructContainer != nullptr);
372
373        // apply T=half. N is still left unspecialized.
374        genericFuncContainer =
375            genericFuncContainer->applySpecializations(specializedStructContainer);
376
377        // Specialize the inner container with 10 separately..
378        argTypes.clear();
379        args.clear();
380
381        slang::GenericArgReflection argN;
382        argN.intVal = 10;
383        argTypes.add(slang::GenericArgType::SLANG_GENERIC_ARG_INT);
384        args.add(argN);
385
386        auto specializedFuncContainer = compositeProgram->getLayout()->specializeGeneric(
387            genericFuncContainer,
388            argTypes.getCount(),
389            argTypes.getBuffer(),
390            args.getBuffer(),
391            nullptr);
392
393        auto specializedFunc = unspecializedFunc->applySpecializations(specializedFuncContainer);
394        SLANG_CHECK(specializedFunc != nullptr);
395
396        // ------ check the specialized function
397        auto specializationInfo = specializedFunc->getGenericContainer();
398        SLANG_CHECK(specializationInfo != nullptr);
399        SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "j");
400        SLANG_CHECK(
401            specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic);
402        SLANG_CHECK(specializationInfo->getValueParameterCount() == 1);
403        auto valueParam = specializationInfo->getValueParameter(0);
404        SLANG_CHECK(UnownedStringSlice(valueParam->getName()) == "N"); // generic name
405        SLANG_CHECK(specializationInfo->getConcreteIntVal(valueParam) == 10);
406
407        // check outer container
408        specializationInfo = specializationInfo->getOuterGenericContainer();
409        SLANG_CHECK(specializationInfo != nullptr);
410        SLANG_CHECK(UnownedStringSlice(specializationInfo->getName()) == "MyGenericType");
411        SLANG_CHECK(
412            specializationInfo->asDecl()->getKind() == slang::DeclReflection::Kind::Generic);
413        // Check type parameters
414        SLANG_CHECK(specializationInfo->getTypeParameterCount() == 1);
415        auto typeParam = specializationInfo->getTypeParameter(0);
416        SLANG_CHECK(UnownedStringSlice(typeParam->getName()) == "T"); // generic name
417        SLANG_CHECK(getTypeFullName(specializationInfo->getConcreteType(typeParam)) == "half");
418    }
419
420    // Check sub-type relations
421    {
422        auto floatType = compositeProgram->getLayout()->findTypeByName("float");
423        SLANG_CHECK(floatType != nullptr);
424        auto diffType = compositeProgram->getLayout()->findTypeByName("IDifferentiable");
425        SLANG_CHECK(diffType != nullptr);
426
427        SLANG_CHECK(compositeProgram->getLayout()->isSubType(floatType, diffType) == true);
428
429        auto uintType = compositeProgram->getLayout()->findTypeByName("uint");
430        SLANG_CHECK(compositeProgram->getLayout()->isSubType(uintType, diffType) == false);
431    }
432
433    // Check specializeWithArgTypes()
434    {
435        auto unspecializedFoo = compositeProgram->getLayout()->findFunctionByName("foo");
436        SLANG_CHECK(unspecializedFoo != nullptr);
437
438        auto floatType = compositeProgram->getLayout()->findTypeByName("float");
439        SLANG_CHECK(floatType != nullptr);
440        auto uintType = compositeProgram->getLayout()->findTypeByName("uint");
441        SLANG_CHECK(uintType != nullptr);
442
443        List<slang::TypeReflection*> argTypes;
444        argTypes.add(floatType);
445        argTypes.add(uintType);
446
447        slang::FunctionReflection* specializedFoo =
448            unspecializedFoo->specializeWithArgTypes(argTypes.getCount(), argTypes.getBuffer());
449        SLANG_CHECK(specializedFoo != nullptr);
450
451        SLANG_CHECK(getTypeFullName(specializedFoo->getReturnType()) == "float");
452        SLANG_CHECK(specializedFoo->getParameterCount() == 2);
453
454        SLANG_CHECK(UnownedStringSlice(specializedFoo->getParameterByIndex(0)->getName()) == "t");
455        SLANG_CHECK(getTypeFullName(specializedFoo->getParameterByIndex(0)->getType()) == "float");
456
457        SLANG_CHECK(UnownedStringSlice(specializedFoo->getParameterByIndex(1)->getName()) == "u");
458        SLANG_CHECK(getTypeFullName(specializedFoo->getParameterByIndex(1)->getType()) == "uint");
459    }
460
461    // Check specializeArgTypes on member method looked up through a specialized type
462    {
463        auto specializedType = compositeProgram->getLayout()->findTypeByName("MyGenericType<half>");
464        SLANG_CHECK(specializedType != nullptr);
465
466        auto unspecializedMethod =
467            compositeProgram->getLayout()->findFunctionByNameInType(specializedType, "h");
468        SLANG_CHECK(unspecializedMethod != nullptr);
469
470        // Specialize the method with float
471        auto floatType = compositeProgram->getLayout()->findTypeByName("float");
472        SLANG_CHECK(floatType != nullptr);
473
474        auto halfType = compositeProgram->getLayout()->findTypeByName("half");
475        SLANG_CHECK(halfType != nullptr);
476
477        List<slang::TypeReflection*> argTypes;
478        argTypes.add(floatType);
479        argTypes.add(halfType);
480
481        auto specializedMethodWithFloat =
482            unspecializedMethod->specializeWithArgTypes(argTypes.getCount(), argTypes.getBuffer());
483        SLANG_CHECK(specializedMethodWithFloat != nullptr);
484        SLANG_CHECK(getTypeFullName(specializedMethodWithFloat->getReturnType()) == "float");
485    }
486
487    // Check getTypeFullName() on nested objects.
488    {
489        auto structType = compositeProgram->getLayout()->findTypeByName("MyNamespace::MyStruct");
490        SLANG_CHECK(getTypeFullName(structType) == "MyNamespace.MyStruct");
491    }
492
493    // Check iterators
494    {
495        unsigned int count = 0;
496        for (auto* child : moduleDeclReflection->getChildren())
497        {
498            count++;
499        }
500        SLANG_CHECK(count == 9);
501
502        count = 0;
503        for (auto* child :
504             moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Func>())
505        {
506            count++;
507        }
508        SLANG_CHECK(count == 3);
509
510        count = 0;
511        for (auto* child :
512             moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Struct>())
513        {
514            count++;
515        }
516        SLANG_CHECK(count == 2);
517
518        count = 0;
519        for (auto* child :
520             moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Generic>())
521        {
522            count++;
523        }
524        SLANG_CHECK(count == 2);
525
526        count = 0;
527        for (auto* child :
528             moduleDeclReflection->getChildrenOfKind<slang::DeclReflection::Kind::Namespace>())
529        {
530            count++;
531        }
532        SLANG_CHECK(count == 1);
533    }
534}