syntax error: unexpected $end at token "<EOF>" GLSL with any shader - c++

I've seen other similar questions, and I now that it's usually due to wrong shader loading code, but I've tried with lots of different ways to load them, and I always get this error. Here is the loading code I'm currently using (for the Vertex shader, i do the same for the fragment shader):
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
std::string VertexShaderCode;
std::ifstream VertexShaderStream(vertex_file_path, std::ios::in);
if(VertexShaderStream.is_open()){
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
GLint Result = GL_FALSE;
int InfoLogLength;
// Compile Vertex Shader
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
I've also tried this:
GLuint VertexShaderID = glCreateShader(GL_FRAGMENT_SHADER);
std::ifstream shaderFile(vertex_file_path);
//Error out here.
stringstream shaderData;
shaderData << shaderFile.rdbuf(); //Loads the entire string into a string stream.
shaderFile.close();
const std::string &VertexShaderCode = shaderData.str(); //Get the string stream as a std::string.
GLint Result = GL_FALSE;
int InfoLogLength;
printf("Compiling shader : %s\n", vertex_file_path);
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
// Check Vertex Shader
glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> VertexShaderErrorMessage(InfoLogLength);
glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
And this is the linking code:
// Link the program
fprintf(stdout, "Linking program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ProgramErrorMessage( max(InfoLogLength, int(1)) );
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
I have also tried passing (GLint *)VertexShaderCode.size() instead of NULL to the length parameter of glShaderSource(), but I get the same errors. I get those errors both when compiling and when linking
In case it helps, I'm using Opengl 3.3, GLEW, GLFW, Visual c++ 2010, and windows 7 64 bits

How did you pass the length parameter to glShaderSource. The typecast you performed should trigger you a thick fat warning. The proper way would have been to put the result of size() into a variable. And then you give the pointer to that variable to glShaderSource.

Related

OpenGL Shader binaries not linking in C++

I am currently working on a OpenGL Shader class, that uses SPIR-V to compile the shaders. Getting the compiled binaries from SPIR-V works fine, the problem is, that my program crashes with the OpenGL exception GL_INVALID_OPERATION error generated. <program> has not been linked, or is not a program object. when trying to bind the Shader with glUseProgram(m_RendererID).
This is my shader creation function:
void OpenGLShader::LoadAndCreateShaders(const std::unordered_map<GLenum, std::vector<uint32>> &shaderData)
{
if (m_RendererID)
glDeleteProgram(m_RendererID);
GLuint program = glCreateProgram();
m_RendererID = program;
std::vector<GLuint> shaderRendererIds;
shaderRendererIds.reserve(shaderData.size());
for (auto &[stage, data] : shaderData)
{
GLuint shaderId = glCreateShader(stage);
glShaderBinary(1, &shaderId, GL_SHADER_BINARY_FORMAT_SPIR_V, data.data(), (uint32)data.size());
glSpecializeShader(shaderId, "main", 0, nullptr, nullptr);
glAttachShader(program, shaderId);
GLint status;
glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status);
if (status == GL_FALSE)
{
std::cout << "Shader compilation failed" << std::endl;
}
shaderRendererIds.emplace_back(shaderId);
}
// Link shader program
glLinkProgram(program);
int32 isLinked = 0;
glGetProgramiv(program, GL_LINK_STATUS, (int32*)&isLinked);
if (isLinked == GL_FALSE)
{
int32 maxLength = 0;
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
if (maxLength > 0)
{
std::vector<GLchar> infoLog(maxLength);
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
std::cout << "Shader linking failed: " << &infoLog[0] << std::endl;
glDeleteProgram(program);
for (auto id : shaderRendererIds)
glDeleteShader(id);
}
}
for (auto id : shaderRendererIds)
glDetachShader(program, id);
}
This function basically takes in the compiled sources from SPIR-V and tries to create the OpenGL shader. When I debugged the program, I found out that after glLinkProgram() isLinked stays 0, but the maxLength variable stays also 0. So the linking process failed, but didn't give an error. Did anyone have the same issue before?

Why does glGetProgramInfoLog return an empty string?

I'm working off a code base that I know compiles correctly. Currently, I've introduced a purposeful spelling mistake into my shader to simulate an error. At this point, the code refuses to compile. I can then call
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &params);
to find that params is now 108 where is was previously 0, so I know that there is a log associated with this shader (which I have tried to compile). However, when I call
glGetProgramInfoLog(shader, 512, &size, ErrorLog);
size returns 0, and ErrorLog is still empty.
Here's the important code in this situation:
void Shader::AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
GLuint ShaderObj = glCreateShader(ShaderType);
if (ShaderObj == 0) {
fprintf(stderr, "Error creating shader type %d\n", ShaderType);
exit(1);
}
const char* pShaderSource = readShaderSource(pShaderText);
glShaderSource(ShaderObj, 1, (const GLchar**)&pShaderSource, NULL);
glCompileShader(ShaderObj);
checkCompileError(ShaderObj, ShaderType);
glAttachShader(ShaderProgram, ShaderObj);
}
bool Shader::checkCompileError(GLuint shader, GLenum ShaderType)
{
GLint params = -1;
GLchar ErrorLog[512] = { 0 };
GLint size = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &params);
if (GL_TRUE != params) {
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &params);
glGetProgramInfoLog(shader, 512, &size, ErrorLog);
fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, ErrorLog);
exit(1);
}
return true;
}
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &params);
glGetProgramInfoLog(shader, 512, &size, ErrorLog);
^^^^^^^ should be Shader
You're compiling & checking a shader so you should use glGetShaderInfoLog().
glGetProgramInfoLog() is for grabbing the link log of the complete shader program object you get from glCreateProgram()

OpenGL not reporting shader compiler errors

I'm having trouble getting OpenGL to work properly. It fails on all shaders and simply returns an info log with the length of 0.
To see if it was in fact OpenGL, I created a little piece of code to test it:
GLuint s = glCreateShader(GL_VERTEX_SHADER);
const char *src = "bad\nsource\ncode";
glShaderSource(s, 1, &src, 0);
GLint len;
glGetShaderiv(s, GL_INFO_LOG_LENGTH, &len);
std::vector<char> buffer(len+1);
glGetShaderInfoLog(s, len, 0, buffer.data());
buffer[len] = '\0';
std::cout << len << std::endl;
std::cout << buffer.data() << std::endl;
And when ran, it simply prints 0 to the console.
What's happening?
You need to compile your shader in order to get an errorlog.
Pseudo Code:
glCompileShader(shader);
GLint status;
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE) {
GLint infolog_length;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infolog_length);
GLchar[] infolog = new GLchar[infolog_length+1];
glGetShaderInfoLog(shader, infolog_length, null, infolog.ptr);
// print infolog etc.
}
From The Documentation:
glGetShaderInfoLog returns the information log for the specified shader object. The information log for a shader object is modified when the shader is compiled. The string that is returned will be null terminated.

Opengl Shader Program changes state without reason

I'm writing an After Effects plugin for the windows platform using OpenGL. After initializing and compiling my shader program I call
glGetProgramiv(inData.mProgramObjSu, GL_ATTACHED_SHADERS, &size); and I get back the value 3 (wich is correct because i attashed a geometry shader).
Also I call glGetAttribLocation with various attribute names and get back valid values. When my render function is called later, the shader program is completely useless, every call to glGetattribLocation returns -1 with the same attribute strings I used earlier and glGetProgramiv(inData.mProgramObjSu, GL_ATTACHED_SHADERS, &size); returns a size of 2. I've got a little experience in OpenGL programming, but I never had a problem like that before.
Here is the shader initialisation code:
GLint vertCompiledB = 0;
GLint geoCompiledB = 0;
GLint fragCompiledB = 0;
GLint linkedB = 0;
// Create vertex shader
inData.mVertexShaderSu = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( inData.mVertexShaderSu, 1, &inVertexShader, nullptr );
glCompileShader( inData.mVertexShaderSu);
glGetShaderiv( inData.mVertexShaderSu, GL_COMPILE_STATUS, &vertCompiledB );
char str[4096];
if(!vertCompiledB)
{
glGetShaderInfoLog(inData.mVertexShaderSu, sizeof(str), NULL, str);
GL_CHECK(AESDK_OpenGL_ShaderInit_Err);
}
// Create geometry shader
inData.mGeometryShaderSu = glCreateShader( GL_GEOMETRY_SHADER );
glShaderSource( inData.mGeometryShaderSu, 1, &inGeometryShader, nullptr );
glCompileShader( inData.mGeometryShaderSu);
glGetShaderiv( inData.mGeometryShaderSu, GL_COMPILE_STATUS, &geoCompiledB );
if(!geoCompiledB)
{
glGetShaderInfoLog(inData.mGeometryShaderSu, sizeof(str), NULL, str);
GL_CHECK(AESDK_OpenGL_ShaderInit_Err);
}
// Create fragment shader
inData.mFragmentShaderSu = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( inData.mFragmentShaderSu, 1, &inFragmentShader, nullptr );
glCompileShader( inData.mFragmentShaderSu );
glGetShaderiv( inData.mFragmentShaderSu, GL_COMPILE_STATUS,&fragCompiledB );
if(!fragCompiledB)
{
glGetShaderInfoLog( inData.mFragmentShaderSu, sizeof(str), NULL, str );
GL_CHECK(AESDK_OpenGL_ShaderInit_Err);
}
// Create a program object and attach the two compiled shaders...
inData.mProgramObjSu = glCreateProgram();
glAttachShader( inData.mProgramObjSu, inData.mVertexShaderSu );
glAttachShader( inData.mProgramObjSu, inData.mGeometryShaderSu );
glAttachShader( inData.mProgramObjSu, inData.mFragmentShaderSu );
// Link the program object
glLinkProgram( inData.mProgramObjSu );
glGetProgramiv( inData.mProgramObjSu, GL_LINK_STATUS, &linkedB );
inData.mPosAttribLoc = glGetAttribLocation(inData.mProgramObjSu, "pos");
inData.mNormAttribLoc = glGetAttribLocation(inData.mProgramObjSu, "norm");
inData.mMVPUnifLoc = glGetUniformLocation(inData.mProgramObjSu, "mvp");
inData.mNormMatUnifLoc = glGetUniformLocation(inData.mProgramObjSu, "normMat");
inData.mLineWidthUnifLoc = glGetUniformLocation(inData.mProgramObjSu, "width");
inData.mEdgeWidthRatioUnifLoc = glGetUniformLocation(inData.mProgramObjSu, "edgeWidthRatio");
inData.mStrokeOverflowUnifLoc = glGetUniformLocation(inData.mProgramObjSu, "strokeOverflow");
int length;
int size;
GLenum type;
GLchar name[40];
glGetActiveUniform(inData.mProgramObjSu, 1, 40, &length, &size, &type, name);
glGetProgramiv(inData.mProgramObjSu, GL_ATTACHED_SHADERS, &size);
if( !linkedB )
{
int length;
glGetShaderInfoLog( inData.mProgramObjSu, 1000, &length, str );
GL_CHECK(AESDK_OpenGL_ShaderInit_Err);
}

Clearing memory after loading shaders

Although I do the suggested steps, I get a memory leak. I load and delete shaders as follows:
glCreateShader
glShaderSource
glCompileShader
glAttachShader
glLinkProgram
glUseProgram
glDetachShader
glDeleteShader
glUseProgram(0);
glDeleteProgram
glLingProgram() seems to cause the leak when I do all these steps in a loop. Below is my test code. Could you please help me find out the problem? (The code is based on the tutorials on http://opengl-tutorial.org/).
EDIT: I think this occurs only when the vertex shader includes an attribute type.
for (int i = 0; i < 1000; i++) {
GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
std::string VertexShaderCode;
std::ifstream VertexShaderStream("VertexShader.vs", std::ios::in);
if(VertexShaderStream.is_open()) {
std::string Line = "";
while(getline(VertexShaderStream, Line))
VertexShaderCode += "\n" + Line;
VertexShaderStream.close();
}
else {
printf("Cannot open vertex shader!");
getchar();
return 0;
}
std::string FragmentShaderCode;
std::ifstream FragmentShaderStream("FragmentShader.fs", std::ios::in);
if(FragmentShaderStream.is_open()) {
std::string Line = "";
while(getline(FragmentShaderStream, Line)) {
FragmentShaderCode += "\n" + Line;
}
FragmentShaderStream.close();
}
else {
printf("Cannot open fragment shader!");
getchar();
return 0;
}
char const * VertexSourcePointer = VertexShaderCode.c_str();
glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
glCompileShader(VertexShaderID);
char const * FragmentSourcePointer = FragmentShaderCode.c_str();
glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
glCompileShader(FragmentShaderID);
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
glUseProgram(ProgramID);
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
glUseProgram(0);
glDeleteProgram(ProgramID);
}
You should load the shaders only at the beginning. Only glUseProgram is intended to be used in the render loop.
Standard template of using a shader is like this:
glCreateProgram
glCreateShader
glShaderSource
glCompileShader
glAttachShader
glLinkProgram <- after this line opengl got everything it needs,
you can free shader resources
glDetachShader
glDeleteShader
for{//render loop
glUseProgram
//...drawing operations
glUseProgram(0);
}
glDeleteProgram