yum-mirror/slang

Making it easier to work with shaders

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

Yong HeFix crash when compiling specialized generic entrypoint containing a static const decl. (#8392)c5607e9d6

master
4.1 KiB120 linesraw
1// unit-test-gh8184.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// A regression test for github issue 8184.
15//
16// We fixed three issues with this regression test:
17// 1. After generating IR for a SpecializeComponentType, we should also strip the frontend
18//    decorations from the IR so there is no HighLevelDeclDecoration that will go into the backend.
19// 2. When lowering a static const inside a generic function, we should not give the static const
20//    a linkage, because it won't such constant will not appear in global scope. Trying to give it a
21//    linkage decoration will lead to the parent generic (for the function) to have two duplicate
22//    Export/Import decorations with different mangle names, and confuses the linker.
23// 3. Make sure internal exceptions does not leak through
24//    IComponentType::getEntryPointCode/getTargetCode.
25//
26SLANG_UNIT_TEST(gh8184)
27{
28    ComPtr<slang::IGlobalSession> globalSession;
29    {
30        SlangGlobalSessionDesc globalDesc = {};
31        SLANG_CHECK_ABORT(createGlobalSession(&globalDesc, globalSession.writeRef()) == SLANG_OK);
32    }
33
34    ComPtr<slang::ISession> session;
35    {
36        slang::TargetDesc targetDesc = {};
37        targetDesc.format = SLANG_WGSL;
38
39        slang::SessionDesc sessionDesc = {};
40        sessionDesc.targets = &targetDesc;
41        sessionDesc.targetCount = 1;
42        sessionDesc.defaultMatrixLayoutMode = SLANG_MATRIX_LAYOUT_COLUMN_MAJOR;
43
44        SLANG_CHECK_ABORT(
45            globalSession->createSession(sessionDesc, session.writeRef()) == SLANG_OK);
46    }
47
48    const char* shaderCode = R"SLANG(
49          interface Transformation
50          {
51              float3 apply(float3 coord);
52              static const uint32_t kParamCount;
53          }
54
55          struct T1 : Transformation {
56              float3 apply(float3 coord) { return float3(0, 0, 0); }
57              static const uint32_t kParamCount = 2;
58          };
59
60          struct T2 : Transformation {
61              float3 apply(float3 coord) { return float3(0, 0, 0); }
62              static const uint32_t kParamCount = 4;
63          };
64
65          [shader("compute")]
66          [numthreads(1, 1, 1)]
67          void XYPass<T>()
68          where T : Transformation
69          {
70              static const uint32_t kParamCount = T::kParamCount;
71          }
72      )SLANG";
73
74    Slang::ComPtr<slang::IModule> module;
75    Slang::ComPtr<slang::IBlob> diagnostics;
76    {
77        const char* moduleName = "bugrepro";
78        const char* virtualPath = "bugrepro.slang";
79        module = session->loadModuleFromSourceString(
80            moduleName,
81            virtualPath,
82            shaderCode,
83            diagnostics.writeRef());
84        SLANG_CHECK_ABORT(module != nullptr);
85    }
86
87    Slang::ComPtr<slang::IEntryPoint> entryPoint;
88    SLANG_CHECK_ABORT(module->findEntryPointByName("XYPass", entryPoint.writeRef()) == SLANG_OK);
89
90    Slang::ComPtr<slang::IComponentType> specializedEntryPoint;
91    {
92        slang::ProgramLayout* programLayout = module->getLayout();
93        SLANG_CHECK_ABORT(programLayout != nullptr);
94        auto* t1Type = programLayout->findTypeByName("T1");
95        SLANG_CHECK_ABORT(t1Type != nullptr);
96
97        slang::SpecializationArg arg = {};
98        arg.kind = slang::SpecializationArg::Kind::Type;
99        arg.type = t1Type;
100
101        SLANG_CHECK_ABORT(
102            entryPoint
103                ->specialize(&arg, 1, specializedEntryPoint.writeRef(), diagnostics.writeRef()) ==
104            SLANG_OK);
105    }
106
107    Slang::ComPtr<slang::IComponentType> program;
108    {
109        slang::IComponentType* components[] = {module.get(), specializedEntryPoint.get()};
110        SLANG_CHECK_ABORT(
111            session->createCompositeComponentType(components, 2, program.writeRef()) == SLANG_OK);
112    }
113
114    Slang::ComPtr<slang::IComponentType> linked;
115    SLANG_CHECK_ABORT(program->link(linked.writeRef(), diagnostics.writeRef()) == SLANG_OK);
116
117    Slang::ComPtr<slang::IBlob> code;
118    SLANG_CHECK(
119        linked->getEntryPointCode(0, 0, code.writeRef(), diagnostics.writeRef()) == SLANG_OK);
120}