使用 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