xemu/subprojects/glslang/gtests/LiveTraverser.FromFile.cpp

112 lines
4.2 KiB
C++

// Copyright (c) 2025 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <gtest/gtest.h>
#include "TestFixture.h"
#include "glslang/MachineIndependent/LiveTraverser.h"
namespace glslangtest {
namespace {
struct LiveTraverserTestParams {
std::string fileName;
std::vector<std::string> liveVars;
};
using LiveTraverserTest = GlslangTest<::testing::TestWithParam<LiveTraverserTestParams>>;
TEST_P(LiveTraverserTest, FromFile)
{
const auto& fileName = GetParam().fileName;
const auto& expectedLiveVars = GetParam().liveVars;
const EShMessages controls = DeriveOptions(Source::GLSL, Semantics::Vulkan, Target::AST);
GlslangResult result;
result.validationResult = true;
std::string contents;
tryLoadFile(GlobalTestSettings.testRoot + "/" + fileName, "input", &contents);
std::unique_ptr<glslang::TShader> shader = std::make_unique<glslang::TShader>(GetShaderStage(GetSuffix(fileName)));
bool success = compile(shader.get(), contents, "", controls);
result.shaderResults.push_back({fileName, shader->getInfoLog(), shader->getInfoDebugLog()});
std::ostringstream stream;
outputResultToStream(&stream, result, controls);
class TLiveSymbolTraverser : public glslang::TLiveTraverser {
public:
TLiveSymbolTraverser(const glslang::TIntermediate& i, std::vector<std::string>& liveVars)
: glslang::TLiveTraverser(i), liveVars(liveVars)
{
}
virtual void visitSymbol(glslang::TIntermSymbol* symbol)
{
if (symbol->getAsSymbolNode()->getAccessName().compare(0, 3, "gl_") == 0)
return;
if (symbol->getQualifier().storage == glslang::TStorageQualifier::EvqVaryingIn ||
symbol->getQualifier().storage == glslang::TStorageQualifier::EvqVaryingOut ||
symbol->getQualifier().storage == glslang::TStorageQualifier::EvqUniform ||
symbol->getQualifier().storage == glslang::TStorageQualifier::EvqBuffer) {
liveVars.push_back(symbol->getAccessName().c_str());
}
}
private:
std::vector<std::string>& liveVars;
};
if (success) {
std::vector<std::string> actualLiveVars;
TLiveSymbolTraverser liveTraverser(*shader->getIntermediate(), actualLiveVars);
liveTraverser.pushFunction(shader->getIntermediate()->getEntryPointMangledName().c_str());
while (!liveTraverser.destinations.empty()) {
TIntermNode* destination = liveTraverser.destinations.back();
liveTraverser.destinations.pop_back();
destination->traverse(&liveTraverser);
}
for (const auto& expectedVar : expectedLiveVars) {
auto it = std::find(actualLiveVars.begin(), actualLiveVars.end(), expectedVar);
EXPECT_NE(it, actualLiveVars.end());
if (it != actualLiveVars.end())
actualLiveVars.erase(it);
}
EXPECT_TRUE(actualLiveVars.empty());
}
// Check with expected results.
const std::string expectedOutputFname = GlobalTestSettings.testRoot + "/baseResults/" + fileName + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname, result.spirvWarningsErrors);
}
// clang-format off
INSTANTIATE_TEST_SUITE_P(
Glsl, LiveTraverserTest,
::testing::ValuesIn(std::vector<LiveTraverserTestParams>({
{"liveTraverser.switch.vert", {"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10"}},
// TODO: implement test for if statements
}))
);
// clang-format on
} // anonymous namespace
} // namespace glslangtest