1
\$\begingroup\$

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;
        break;
    case ShaderStage::FRAGMENT_SHADER:
        stage = EShLangFragment;
        break;
    case ShaderStage::GEOMETRY_SHADER:
        stage = EShLangGeometry;
        break;
    case ShaderStage::COMPUTE_SHADER:
        stage = EShLangCompute;
        break;
    default:
        return std::vector<char>();
    }

    if (!m_glslangInitialized)
    {
        glslang::InitializeProcess();
        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)),
        std::istreambuf_iterator<char>());

    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);
    Includer.pushExternalLocalDirectory(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;
    Program.addShader(&Shader);

    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
\$\endgroup\$

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.