使用 glslang 提取 glsl 文件中的所有统一声明?
Using glslang to extract all uniform delcarations in a glsl file?
我想做一些 glsl 解析,特别是我想找到所有统一声明,包括 SSBOS、采样器和图像。
据我所知,glslang 提供了对 AST 的访问,这意味着它可以成为一种强大的节省时间的方法,可以避免您自己编写脆弱的解析器。
但是我在 git repo 上没有看到很多关于库的文档。有一些单元测试让我对它的工作原理有了一些大致的了解,但我仍然不确定我将如何遍历 AST 以找到与制服对应的文本块。
我基本上需要将它们导出到不同的文件。
TIntermTraverser
是要走的路。
实际上,您将通过继承 TIntermTraverser
来定义自定义遍历器 class。
有关详细信息,请阅读 TIntermTraverser
定义顶部的文档注释。
TIntermTraverser
在glslang项目中是全局使用的,所以研究一下它在项目中是如何使用的,对于理解用法会有很好的帮助。
我认为 glslang/MachineIndependent/intermOut.cpp
是一个很好的起点。
我给你写了示例代码,如下所示。
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();
}
对于以下计算着色器,您将得到以下结果。
#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
我想做一些 glsl 解析,特别是我想找到所有统一声明,包括 SSBOS、采样器和图像。
据我所知,glslang 提供了对 AST 的访问,这意味着它可以成为一种强大的节省时间的方法,可以避免您自己编写脆弱的解析器。
但是我在 git repo 上没有看到很多关于库的文档。有一些单元测试让我对它的工作原理有了一些大致的了解,但我仍然不确定我将如何遍历 AST 以找到与制服对应的文本块。
我基本上需要将它们导出到不同的文件。
TIntermTraverser
是要走的路。
实际上,您将通过继承 TIntermTraverser
来定义自定义遍历器 class。
有关详细信息,请阅读 TIntermTraverser
定义顶部的文档注释。
TIntermTraverser
在glslang项目中是全局使用的,所以研究一下它在项目中是如何使用的,对于理解用法会有很好的帮助。
我认为 glslang/MachineIndependent/intermOut.cpp
是一个很好的起点。
我给你写了示例代码,如下所示。
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();
}
对于以下计算着色器,您将得到以下结果。
#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