(Sorry if this is the wrong forum I haven’t found a better fitting one)
I have the problem that libglslang will segfault when I want to link my program.
I personally want to use glslang for reflection on my uniforms, but it’s not clear from the documentation how this is meant to be achieved. I also looked at the “StandAlone” solution from the glslang github repo as suggested, but it hasn’t helped.
It always segfaults on glslang::TProgram::link
. Before I tried without the linking step(as I assumed it only needs the syntax tree for reflection), but glslang::TProgram::buildReflection
returns false and subsequently segfaults on glslang::TProgram::getUniformVariables
(if I ignore return value from buildReflection).
I even simplified the shader to the absolute minimum, but still it fails.
#include <cstdio>
#include <fstream>
#include <string>
#include <glslang/Public/ResourceLimits.h>
#include <glslang/Public/ShaderLang.h>
struct ShaderData{
bool success{false};
glslang::TShader shader;
std::string source;
char* source_c_str;
ShaderData(EShLanguage shaderType):
success{false},
shader{shaderType},
source{},
source_c_str{nullptr}
{};
};
bool createShader(ShaderData& shader, std::string filePath)
{
{
std::ifstream file{filePath,std::ifstream::in};
file.seekg (0, file.end);
int length = file.tellg();
file.seekg (0, file.beg);
shader.source.reserve(length);
file.read(shader.source.data(), length);
}
shader.source_c_str = shader.source.data();
shader.shader.setStrings(&(shader.source_c_str), shader.source.length());
shader.shader.setEnvInput(glslang::EShSourceGlsl, shader.shader.getStage(), glslang::EShClientVulkan, 450);
shader.shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_6);
std::string out;
glslang::TShader::ForbidIncluder includer;
EShMessages message = (EShMessages) ( EShMessages::EShMsgVulkanRules | EShMessages::EShMsgSpvRules);
bool success = shader.shader.preprocess(GetDefaultResources(), 450,EProfile::ECoreProfile, true, false, message, &out, includer);
if(success==false) printf("Prepocessor failed");
success = shader.shader.parse(GetDefaultResources(),450,EProfile::ECoreProfile, true, false,message);
return success;
}
int main(){
glslang::InitializeProcess();
ShaderData vertexShader = {EShLanguage::EShLangVertex};
if (createShader(vertexShader, "../source/shader/shader.vert.glsl") == false){
puts("vertex shader compile failed");
glslang::FinalizeProcess();
return -1;
}
ShaderData fragmentShader{EShLanguage::EShLangFragment};
if (createShader(fragmentShader, "../source/shader/shader.frag.glsl") == false){
puts("fragment shader compile failed");
glslang::FinalizeProcess();
return -1;
}
glslang::TProgram shaderProgam{};
shaderProgam.addShader(&(vertexShader.shader));
shaderProgam.addShader(&(fragmentShader.shader));
puts("right before linking");
bool success = shaderProgam.link(EShMessages::EShMsgVulkanRules); //<- segfaults here
puts("right after linking");
if(success == false){
printf("Linking program failed");
printf("DebugLog: %s\n",shaderProgam.getInfoDebugLog());
printf("Info log: %s",shaderProgam.getInfoLog());
glslang::FinalizeProcess();
return -1;
}
shaderProgam.buildReflection();
if(success==false){
printf("Failed reflection building: %s\n",shaderProgam.getInfoDebugLog());
printf("Info log: %s",shaderProgam.getInfoLog());
glslang::FinalizeProcess();
return -1;
}
int unfiromVariables = shaderProgam.getNumUniformVariables();
for(int i = 0; i < unfiromVariables; i++){
const glslang::TObjectReflection& uniform = shaderProgam.getUniform(i);
printf("\t%s with size %d \n",uniform.name.c_str(),uniform.size);
}
shaderProgam.dumpReflection();
glslang::FinalizeProcess();
return 0;
}
#version 450
layout(location = 0) in vec3 position;
void main() {
gl_Position = vec4(position,1.0f);
}
#version 450
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(1.0f, 0.0, 0.0, 1.0f);
}
My compile flags are:
g++ -std=c++17 test.cpp -lglslang -lMachineIndependent -lGenericCodeGen -lOSDependent -lSPVRemapper -lpthread -lglslang-default-resource-limits
Do I miss something in my code or does someone know why this fails?