yum-mirror/glslang

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

Zackery Mason-BlaugLiveTraverser no longer traverses switch cases that are statically not accessed0b3e8560

main
4.2 KiB111 linesraw
1// Copyright (c) 2025 The Khronos Group Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include <gtest/gtest.h>
16
17#include "TestFixture.h"
18
19#include "glslang/MachineIndependent/LiveTraverser.h"
20
21namespace glslangtest {
22namespace {
23
24struct LiveTraverserTestParams {
25    std::string fileName;
26    std::vector<std::string> liveVars;
27};
28
29using LiveTraverserTest = GlslangTest<::testing::TestWithParam<LiveTraverserTestParams>>;
30
31TEST_P(LiveTraverserTest, FromFile)
32{
33    const auto& fileName = GetParam().fileName;
34    const auto& expectedLiveVars = GetParam().liveVars;
35    const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::Vulkan, Target::AST);
36    GlslangResult result;
37    result.validationResult = true;
38
39    std::string contents;
40    tryLoadFile(GlobalTestSettings.testRoot + "/" + fileName, "input", &contents);
41    std::unique_ptr<glslang::TShader> shader = std::make_unique<glslang::TShader>(GetShaderStage(GetSuffix(fileName)));
42
43    bool success = compile(shader.get(), contents, "", controls);
44    result.shaderResults.push_back({fileName, shader->getInfoLog(), shader->getInfoDebugLog()});
45
46    std::ostringstream stream;
47    outputResultToStream(&stream, result, controls);
48
49    class TLiveSymbolTraverser : public glslang::TLiveTraverser {
50    public:
51        TLiveSymbolTraverser(const glslang::TIntermediate& i, std::vector<std::string>& liveVars)
52            : glslang::TLiveTraverser(i), liveVars(liveVars)
53        {
54        }
55
56        virtual void visitSymbol(glslang::TIntermSymbol* symbol)
57        {
58            if (symbol->getAsSymbolNode()->getAccessName().compare(0, 3, "gl_") == 0)
59                return;
60
61            if (symbol->getQualifier().storage == glslang::TStorageQualifier::EvqVaryingIn ||
62                symbol->getQualifier().storage == glslang::TStorageQualifier::EvqVaryingOut ||
63                symbol->getQualifier().storage == glslang::TStorageQualifier::EvqUniform ||
64                symbol->getQualifier().storage == glslang::TStorageQualifier::EvqBuffer) {
65                liveVars.push_back(symbol->getAccessName().c_str());
66            }
67        }
68
69    private:
70        std::vector<std::string>& liveVars;
71    };
72
73    if (success) {
74        std::vector<std::string> actualLiveVars;
75        TLiveSymbolTraverser liveTraverser(*shader->getIntermediate(), actualLiveVars);
76        liveTraverser.pushFunction(shader->getIntermediate()->getEntryPointMangledName().c_str());
77        while (!liveTraverser.destinations.empty()) {
78            TIntermNode* destination = liveTraverser.destinations.back();
79            liveTraverser.destinations.pop_back();
80            destination->traverse(&liveTraverser);
81        }
82
83        for (const auto& expectedVar : expectedLiveVars) {
84            auto it = std::find(actualLiveVars.begin(), actualLiveVars.end(), expectedVar);
85            EXPECT_NE(it, actualLiveVars.end());
86            if (it != actualLiveVars.end())
87                actualLiveVars.erase(it);
88        }
89        EXPECT_TRUE(actualLiveVars.empty());
90    }
91
92    // Check with expected results.
93    const std::string expectedOutputFname = GlobalTestSettings.testRoot + "/baseResults/" + fileName + ".out";
94    std::string expectedOutput;
95    tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
96
97    checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname, result.spirvWarningsErrors);
98}
99
100// clang-format off
101INSTANTIATE_TEST_SUITE_P(
102    Glsl, LiveTraverserTest,
103    ::testing::ValuesIn(std::vector<LiveTraverserTestParams>({
104        {"liveTraverser.switch.vert", {"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10"}},
105        // TODO: implement test for if statements
106    }))
107);
108// clang-format on
109
110} // anonymous namespace
111} // namespace glslangtest