#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());
}
const std::string expectedOutputFname = GlobalTestSettings.testRoot + "/baseResults/" + fileName + ".out";
std::string expectedOutput;
tryLoadFile(expectedOutputFname, "expected output", &expectedOutput);
checkEqAndUpdateIfRequested(expectedOutput, stream.str(), expectedOutputFname, result.spirvWarningsErrors);
}
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"}},
}))
);
}
}