yum-mirror/slang

Making it easier to work with shaders

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

Yong HeAllow specializing entrypoints with generic value args or variadic types from API (#8119)dcdebc1a7

master
5.6 KiB142 linesraw
1// unit-test-generic-entrypoint.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
14// Test the compilation API for compiling a specialized generic entrypoint.
15
16SLANG_UNIT_TEST(genericEntryPointCompile)
17{
18    const char* userSourceBody = R"(
19            interface I { int getValue(); }
20            struct X : I { int getValue() { return 100; } }
21            float4 vertMain<T:I, int n, each U>(uniform T o) {
22                return float4(o.getValue(), countof(U), n, 1);
23            }
24        )";
25    ComPtr<slang::IGlobalSession> globalSession;
26    SLANG_CHECK(slang_createGlobalSession(SLANG_API_VERSION, globalSession.writeRef()) == SLANG_OK);
27    slang::TargetDesc targetDesc = {};
28    targetDesc.format = SLANG_GLSL;
29    slang::SessionDesc sessionDesc = {};
30    sessionDesc.targetCount = 1;
31    sessionDesc.targets = &targetDesc;
32    ComPtr<slang::ISession> session;
33    SLANG_CHECK(globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK);
34
35    ComPtr<slang::IBlob> diagnosticBlob;
36    auto module = session->loadModuleFromSourceString(
37        "m",
38        "m.slang",
39        userSourceBody,
40        diagnosticBlob.writeRef());
41    SLANG_CHECK(module != nullptr);
42
43    // Test 1: Using findAndCheckEntryPoint to supply arguments in string form.
44    {
45        ComPtr<slang::IEntryPoint> entryPoint;
46        module->findAndCheckEntryPoint(
47            "vertMain<X, 7, int, float>",
48            SLANG_STAGE_VERTEX,
49            entryPoint.writeRef(),
50            diagnosticBlob.writeRef());
51        SLANG_CHECK_ABORT(entryPoint != nullptr);
52        slang::IComponentType* componentTypes[2] = {module, entryPoint.get()};
53        ComPtr<slang::IComponentType> composedProgram;
54        session->createCompositeComponentType(
55            componentTypes,
56            2,
57            composedProgram.writeRef(),
58            diagnosticBlob.writeRef());
59
60        ComPtr<slang::IComponentType> linkedProgram;
61        composedProgram->link(linkedProgram.writeRef(), diagnosticBlob.writeRef());
62
63        ComPtr<slang::IBlob> code;
64        linkedProgram->getEntryPointCode(0, 0, code.writeRef(), diagnosticBlob.writeRef());
65
66        SLANG_CHECK(
67            UnownedStringSlice((char*)code->getBufferPointer())
68                .indexOf(toSlice("vec4(float(X_getValue_0()), 2.0, 7.0, 1.0)")) != -1);
69    }
70
71    // Test 2: Using `specialize` to supply arguments structurally with reflection types.
72    {
73        ComPtr<slang::IEntryPoint> entryPoint;
74        module->findAndCheckEntryPoint(
75            "vertMain",
76            SLANG_STAGE_VERTEX,
77            entryPoint.writeRef(),
78            diagnosticBlob.writeRef());
79        SLANG_CHECK_ABORT(entryPoint != nullptr);
80        ComPtr<slang::IComponentType> specializedEntryPoint;
81        slang::SpecializationArg args[] = {
82            slang::SpecializationArg::fromType(module->getLayout()->findTypeByName("X")),
83            slang::SpecializationArg::fromExpr("8"),
84            slang::SpecializationArg::fromType(module->getLayout()->findTypeByName("int")),
85            slang::SpecializationArg::fromType(module->getLayout()->findTypeByName("float"))};
86
87        entryPoint->specialize(args, 4, specializedEntryPoint.writeRef(), nullptr);
88        SLANG_CHECK_ABORT(specializedEntryPoint != nullptr);
89        slang::IComponentType* componentTypes[2] = {module, specializedEntryPoint.get()};
90        ComPtr<slang::IComponentType> composedProgram;
91        session->createCompositeComponentType(
92            componentTypes,
93            2,
94            composedProgram.writeRef(),
95            diagnosticBlob.writeRef());
96
97        ComPtr<slang::IComponentType> linkedProgram;
98        composedProgram->link(linkedProgram.writeRef(), diagnosticBlob.writeRef());
99
100        ComPtr<slang::IBlob> code;
101        linkedProgram->getEntryPointCode(0, 0, code.writeRef(), diagnosticBlob.writeRef());
102
103        SLANG_CHECK(
104            UnownedStringSlice((char*)code->getBufferPointer())
105                .indexOf(toSlice("vec4(float(X_getValue_0()), 2.0, 8.0, 1.0)")) != -1);
106    }
107
108    // Test 3: corner case: specialize variadic param with 0 types.
109    {
110        ComPtr<slang::IEntryPoint> entryPoint;
111        module->findAndCheckEntryPoint(
112            "vertMain",
113            SLANG_STAGE_VERTEX,
114            entryPoint.writeRef(),
115            diagnosticBlob.writeRef());
116        SLANG_CHECK_ABORT(entryPoint != nullptr);
117        ComPtr<slang::IComponentType> specializedEntryPoint;
118        slang::SpecializationArg args[] = {
119            slang::SpecializationArg::fromType(module->getLayout()->findTypeByName("X")),
120            slang::SpecializationArg::fromExpr("8")};
121
122        entryPoint->specialize(args, 2, specializedEntryPoint.writeRef(), nullptr);
123        SLANG_CHECK_ABORT(specializedEntryPoint != nullptr);
124        slang::IComponentType* componentTypes[2] = {module, specializedEntryPoint.get()};
125        ComPtr<slang::IComponentType> composedProgram;
126        session->createCompositeComponentType(
127            componentTypes,
128            2,
129            composedProgram.writeRef(),
130            diagnosticBlob.writeRef());
131
132        ComPtr<slang::IComponentType> linkedProgram;
133        composedProgram->link(linkedProgram.writeRef(), diagnosticBlob.writeRef());
134
135        ComPtr<slang::IBlob> code;
136        linkedProgram->getEntryPointCode(0, 0, code.writeRef(), diagnosticBlob.writeRef());
137
138        SLANG_CHECK(
139            UnownedStringSlice((char*)code->getBufferPointer())
140                .indexOf(toSlice("vec4(float(X_getValue_0()), 0.0, 8.0, 1.0)")) != -1);
141    }
142}