'Using glslang to extract all uniform delcarations in a glsl file?
I want to do some glsl parsing, in particular I want to find all uniform declarations, that includes SSBOS, samplers and images.
To my understanding glslang provides access to the AST, meaning it can be a a robust time saver to avoid writing a brittle parser yourself.
However I don't see a lot of documentation for the library on the git repo. There are some unit tests which gives me some generic idea of how it works but I am still not sure how I would iterate over the AST to find the text blocks corresponding to uniforms.
I basically need to export them to a different file.
Solution 1:[1]
TIntermTraverser is the way to go.
In practice, you will define your custom traverser class by inheriting TIntermTraverser.
For more details, read the doc comments on the top of the definition of TIntermTraverser.
TIntermTraverser is used globally in the glslang project, so examining how it is used in the project will be a good help to understand the usage.
glslang/MachineIndependent/intermOut.cpp is a good starting point, I think.
I wrote the sample code for you, which is shown below.
void glslang_refrection(const std::string& fpath) {
glslang::InitializeProcess();
{
auto src = file::read_file(fpath);
const char* const sources[] = {src.c_str()};
const int sourceLengths[] = {static_cast<int>(src.size())};
const char* sourceNames[] = {""};
const int sources_num = 1;
const auto shader_stage = EShLanguage::EShLangCompute;
glslang::TShader shader{shader_stage};
shader.setStringsWithLengthsAndNames(sources, sourceLengths, sourceNames, sources_num);
shader.setEnvClient(glslang::EShClientOpenGL, glslang::EShTargetOpenGL_450);
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
TBuiltInResource default_builtin_resources{};
shader.parse(&default_builtin_resources, 450, ECoreProfile, false, true, EShMsgDefault);
class RefrectionTraverser : public glslang::TIntermTraverser {
public:
virtual void visitSymbol(glslang::TIntermSymbol* symbol) override {
if (symbol->getQualifier().isUniformOrBuffer()) {
auto name = symbol->getName();
auto qualifier = symbol->getQualifier();
fprintf(stderr, "%s: %s\n", name.c_str(),
glslang::GetStorageQualifierString(qualifier.storage));
if (qualifier.hasLocation()) {
fprintf(stderr, " loc: %d\n", qualifier.layoutLocation);
}
if (qualifier.hasBinding()) {
fprintf(stderr, " binding: %d\n", qualifier.layoutBinding);
}
if (qualifier.hasPacking()) {
fprintf(stderr, " packing: %s\n",
glslang::TQualifier::getLayoutPackingString(
qualifier.layoutPacking));
}
}
}
};
RefrectionTraverser traverser;
auto root = shader.getIntermediate()->getTreeRoot();
root->traverse(&traverser);
}
glslang::FinalizeProcess();
}
For the following compute shader, you will get the result below.
#version 450 core
layout(std430, binding = 2) buffer TestBuffer {
int type;
float value;
};
layout(location = 2) uniform float u_time;
layout(binding = 1, std140) uniform MainBlock { vec3 data; } u_block;
void main() {}
anon@0: buffer
binding: 2
packing: std430
u_time: uniform
loc: 2
u_block: uniform
binding: 1
packing: std140
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
