I have been working with GLSLang to convert between GLSL and SpireV for the purpose of run time shader compilation. GLSLlang compiles my shader code and I can successfully create and run a compute pipeline in Vulcan with it, but the buffers passed to it wont update. On the other hand, when I test all the same code with Pre Compiled GLSL code, it works as expected so I believe the error to come from how I am covering it.

GLSLang seems to compile the shader code into a array of unsigned int's, within my code i move the data over to a char array as this is the format that Vulkan seems to load the shader's in.

GLSL code

#version 450

#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) buffer Buffer1 {
    float[] fpn;

void main() {
    uint GIX = gl_GlobalInvocationID.x;
    fpn[GIX] *= 2.0f;

GLSL to Spir-v function

std::vector<char> VulkanCommon::glslToSpirV(const char * path, ShaderStage shader_stage)
    EShLanguage stage = EShLanguage::EShLangCount;
    switch (shader_stage)
    case ShaderStage::VERTEX_SHADER:
        stage = EShLangVertex;
    case ShaderStage::FRAGMENT_SHADER:
        stage = EShLangFragment;
    case ShaderStage::GEOMETRY_SHADER:
        stage = EShLangGeometry;
    case ShaderStage::COMPUTE_SHADER:
        stage = EShLangCompute;
        return std::vector<char>();

    if (!m_glslangInitialized)
        m_glslangInitialized = true;
    std::ifstream file(path);

    if (!file.is_open())
        throw std::runtime_error("failed to open shader file");

    std::string glsl((std::istreambuf_iterator<char>(file)),

    const char* InputCString = glsl.c_str();

    glslang::TShader Shader(stage);

    Shader.setStrings(&InputCString, 1);

    int ClientInputSemanticsVersion = 100; // maps to, say, #define VULKAN 100
    int VulkanClientVersion = 100;
    unsigned int TargetVersion = 0x00010000;

    Shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, ClientInputSemanticsVersion);
    Shader.setEnvClient(glslang::EShClientVulkan, VulkanClientVersion);
    Shader.setEnvTarget(glslang::EShTargetSpv, TargetVersion);

    TBuiltInResource Resources;
    Resources = glslang::DefaultTBuiltInResource;
    EShMessages messages = (EShMessages)(EShMsgSpvRules | EShMsgVulkanRules);

    const int DefaultVersion = 450;

    DirStackFileIncluder Includer;

    std::string Path = getFilePath(path);

    std::string PreprocessedGLSL;

    if (!Shader.preprocess(&Resources, DefaultVersion, ENoProfile, false, false, messages, &PreprocessedGLSL, Includer))
        throw std::runtime_error("GLSL Preprocessing Failed");

    const char* PreprocessedCStr = PreprocessedGLSL.c_str();
    Shader.setStrings(&PreprocessedCStr, 1);

    if (!Shader.parse(&Resources, 100, false, messages))
        throw std::runtime_error("GLSL Parsing Failed");

    glslang::TProgram Program;

    if (!Program.link(messages))
        throw std::runtime_error("GLSL Linking Failed");
    if (!Program.mapIO())
        throw std::runtime_error("GLSL Linking Failed");

    // Temp storage of SpirV after conversion 
    std::vector<unsigned int> SpirV_temp;
    spv::SpvBuildLogger logger;
    glslang::SpvOptions spvOptions;
    glslang::GlslangToSpv(*Program.getIntermediate(stage), SpirV_temp, &logger, &spvOptions);

    // SpirV in binary format
    std::vector<char> SpirV;
    SpirV.resize(sizeof(unsigned int)*SpirV_temp.size());
    // Move unsigned int version of SpirV into binary format
    memcpy(SpirV.data(), SpirV_temp.data(), sizeof(unsigned int)*SpirV_temp.size());

    return SpirV;

Update After poking around, I found that if I keep the shader main function empty there is no warnings from the logger in GLSLang, but if I have anything in the main, I get this log output

Missing functionality: unknown glslang binary operation

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.