yum-mirror/glslang

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

Diego NovilloAdd license to new test file.0f2400cd

main
7.7 KiB210 linesraw
1// Copyright (C) 2025 NVIDIA Corporation
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy
4// of this software and associated documentation files (the "Software"), to deal
5// in the Software without restriction, including without limitation the rights
6// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7// copies of the Software, and to permit persons to whom the Software is
8// furnished to do so, subject to the following conditions:
9//
10// The above copyright notice and this permission notice shall be included in all
11// copies or substantial portions of the Software.
12//
13// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19// SOFTWARE.
20
21#include "TestFixture.h"
22#include "glslang/Public/ResourceLimits.h"
23#include <gtest/gtest.h>
24#include <regex>
25#include <sstream>
26#include <string>
27
28namespace glslangtest {
29
30class SpvPatternTest : public ::testing::Test {
31protected:
32    void SetUp() override
33    {
34        // Set up any common test state.
35    }
36
37    void TearDown() override
38    {
39        // Clean up any common test state.
40    }
41
42    // Helper function to compile shader and get SPIR-V disassembly.
43    std::string compileShaderToSpirv(const std::string& shaderSource, EShLanguage stage)
44    {
45        glslang::TShader shader(stage);
46        glslang::TProgram program;
47
48        // Compile the shader
49        const char* shaderStrings = shaderSource.c_str();
50        shader.setStrings(&shaderStrings, 1);
51
52        if (!shader.parse(GetDefaultResources(), 450, false, EShMsgDefault)) {
53            return "COMPILATION_FAILED: " + std::string(shader.getInfoLog());
54        }
55
56        program.addShader(&shader);
57        if (!program.link(EShMsgDefault)) {
58            return "LINKING_FAILED: " + std::string(program.getInfoLog());
59        }
60
61        // Generate SPIR-V.
62        std::vector<uint32_t> spirv;
63        glslang::GlslangToSpv(*program.getIntermediate(stage), spirv);
64
65        // Disassemble SPIR-V to text.
66        std::ostringstream disassembly_stream;
67        spv::Disassemble(disassembly_stream, spirv);
68
69        return disassembly_stream.str();
70    }
71
72    // Helper function to check if the given SPIR-V string contains a specific pattern.
73    bool containsPattern(const std::string& spirvText, const std::string& pattern)
74    {
75        return spirvText.find(pattern) != std::string::npos;
76    }
77
78    // Helper function to check if the given SPIR-V string contains a UConvert instruction.
79    bool containsUConvert(const std::string& spirvText) { return containsPattern(spirvText, "UConvert"); }
80};
81
82// Test 1: Indexing an array with a regular int or uint should not generate a zero extension.
83TEST_F(SpvPatternTest, RegularIntUintArrayIndexNoConversion)
84{
85    const std::string shaderSource = R"(
86        #version 450 core
87
88        layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
89
90        void main() {
91            uint u = 150u;
92            int i = 100;
93            float arr[200];
94            float x = arr[u];  // Regular uint index
95            float y = arr[i];  // Regular int index
96        }
97        )";
98
99    std::string spirv = compileShaderToSpirv(shaderSource, EShLangCompute);
100
101    // Check that the SPIR-V does NOT contain conversion instructions for regular int/uint indices.
102    EXPECT_FALSE(containsUConvert(spirv))
103        << "SPIR-V should not contain OpUConvert instruction for regular int/uint array indexing.\n"
104        << "Generated SPIR-V:\n"
105        << spirv;
106}
107
108// Test 2: Indexing an array with a variable index of type uint8_t should generate a zero extension.
109TEST_F(SpvPatternTest, Uint8VariableIndexGeneratesUConvert)
110{
111    const std::string shaderSource = R"(
112        #version 450 core
113        #extension GL_EXT_shader_explicit_arithmetic_types : enable
114
115        layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
116
117        void main() {
118            uint8_t u8 = uint8_t(150);
119            float arr[200];
120            float x = arr[u8];  // Variable uint8_t index
121        }
122        )";
123
124    std::string spirv = compileShaderToSpirv(shaderSource, EShLangCompute);
125
126    // Check that the SPIR-V contains OpUConvert instruction for variable uint8_t index.
127    EXPECT_TRUE(containsUConvert(spirv))
128        << "SPIR-V should contain OpUConvert instruction for variable uint8_t array indexing.\n"
129        << "Generated SPIR-V:\n"
130        << spirv;
131}
132
133// Test 2: Indexing an array with a variable index of type uint16_t should generate a zero extension.
134TEST_F(SpvPatternTest, Uint16VariableIndexGeneratesUConvert)
135{
136    const std::string shaderSource = R"(
137        #version 450 core
138        #extension GL_EXT_shader_explicit_arithmetic_types : enable
139
140        layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
141
142        void main() {
143            uint16_t u16 = uint16_t(150);
144            float arr[200];
145            float x = arr[u16];  // Variable uint16_t index
146        }
147        )";
148
149    std::string spirv = compileShaderToSpirv(shaderSource, EShLangCompute);
150
151    // Check that the SPIR-V contains OpUConvert instruction for variable uint16_t index.
152    EXPECT_TRUE(containsUConvert(spirv))
153        << "SPIR-V should contain OpUConvert instruction for variable uint16_t array indexing.\n"
154        << "Generated SPIR-V:\n"
155        << spirv;
156}
157
158// Test 3: Indexing an array with a constant index of type uint8_t should NOT generate a zero extension.
159// Glslang generates small constants as regular 32-bit integers.
160TEST_F(SpvPatternTest, Uint8ConstantIndexNoConversion)
161{
162    const std::string shaderSource = R"(
163        #version 450 core
164        #extension GL_EXT_shader_explicit_arithmetic_types : enable
165
166        layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
167
168        void main() {
169            float arr[200];
170            float x = arr[uint8_t(150)];  // Constant uint8_t index
171        }
172        )";
173
174    std::string spirv = compileShaderToSpirv(shaderSource, EShLangCompute);
175
176    // Check that the SPIR-V does NOT contain OpUConvert instruction for constant uint8_t index.
177    // Glslang generates small constants as regular 32-bit integers, so no conversion is needed.
178    EXPECT_FALSE(containsUConvert(spirv))
179        << "SPIR-V should not contain OpUConvert instruction for constant uint8_t array indexing.\n"
180        << "Generated SPIR-V:\n"
181        << spirv;
182}
183
184// Test 3: Indexing an array with a constant index of type uint16_t should NOT generate a zero extension.
185// (Glslang generates small constants as regular 32-bit integers.)
186TEST_F(SpvPatternTest, Uint16ConstantIndexNoConversion)
187{
188    const std::string shaderSource = R"(
189        #version 450 core
190        #extension GL_EXT_shader_explicit_arithmetic_types : enable
191
192        layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
193
194        void main() {
195            float arr[200];
196            float x = arr[uint16_t(150)];  // Constant uint16_t index
197        }
198        )";
199
200    std::string spirv = compileShaderToSpirv(shaderSource, EShLangCompute);
201
202    // Check that the SPIR-V does NOT contain OpUConvert instruction for constant uint16_t index.
203    // Glslang generates small constants as regular 32-bit integers, so no conversion is needed.
204    EXPECT_FALSE(containsUConvert(spirv))
205        << "SPIR-V should not contain OpUConvert instruction for constant uint16_t array indexing.\n"
206        << "Generated SPIR-V:\n"
207        << spirv;
208}
209
210} // namespace glslangtest