I've a weird problem with GLSL shaders. My program seems to not launch or launch successfully depending on the size of my shader files. If I only write a few lines of code in shader files, the program works fine. For example, the program launches successfully with this much code:
vertex.vs:
#version 460 core
layout (location = 0) in vec2 coords;
uniform float u_time;
out vec3 result_color;
void main()
{
vec3 colorA = vec3(0.514f, 0.179f, 0.900f);
vec3 colorB = vec3(0.895f, 0.359f, 0.488f);
gl_Position = vec4(coords, 0.0f, 1.0f);
result_color = colorA;
}
fragment.fs:
#version 460 core
in vec3 result_color;
out vec4 color;
void main()
{
color = vec4(result_color, 1.0f);
}
If I add more code to any of my shader files it only launches about 50% of the time:
vertex.vs:
#version 460 core
layout (location = 0) in vec2 coords;
uniform float u_time;
out vec3 result_color;
// float wave(float x)
// {
// return min(2.0f - 2.0f * fract(x / 2.0f),
// 2.0f * fract(x / 2.0f));
// }
void main()
{
vec3 colorA = vec3(0.514f, 0.179f, 0.900f);
vec3 colorB = vec3(0.895f, 0.359f, 0.488f);
// float frequency = 15.0f;
// float y = wave(coords.x * frequency cos(u_time) * 5.0f);
// float fr_y = fract(coords.y * frequency u_time);
gl_Position = vec4(coords, 0.0f, 1.0f);
result_color = colorA;
}
Note that the code I added is commented out but still the error occurs. And the more code I add the less is the chance it works. Here's the class I use to read shaders from files and create a shader program:
#include <iostream>
#include <fstream>
#include <sstream>
#include <glad/glad.h>
#include "shader_program.h"
ShaderProgram::ShaderProgram(std::string vertexShaderPath, std::string fragmentShaderPath)
{
std::ifstream vShaderFile;
std::ifstream fShaderFile;
std::stringstream vShaderStream;
std::stringstream fShaderStream;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try
{
vShaderFile.open(vertexShaderPath);
vShaderStream << vShaderFile.rdbuf();
}
catch(std::ifstream::failure e)
{
std::cout << "ERROR: FAILED TO READ SHADER FILE: VERTEX SHADER" << std::endl;
}
try
{
fShaderFile.open(fragmentShaderPath);
fShaderStream << fShaderFile.rdbuf();
}
catch(std::ifstream::failure e)
{
std::cout << "ERROR: FAILED TO READ SHADER FILE: FRAGMENT SHADER" << std::endl;
}
const char* vertexShaderSource = vShaderStream.str().c_str();
const char* fragmentShaderSource = fShaderStream.str().c_str();
CreateShaderProgram(vertexShaderSource, fragmentShaderSource);
}
unsigned int ShaderProgram::GetProgram()
{
return program;
}
void ShaderProgram::CreateShaderProgram(const char* vertexShaderSource, const char* fragmentShaderSource)
{
program = glCreateProgram();
unsigned int vertexShader = CompileShader(GL_VERTEX_SHADER, vertexShaderSource);
unsigned int fragmentShader = CompileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glLinkProgram(program);
int linkingResult;
glGetProgramiv(program, GL_LINK_STATUS, &linkingResult);
if (linkingResult == GL_FALSE)
{
char infoLog[512];
glGetProgramInfoLog(program, 512, NULL, infoLog);
std::cout << "ERROR: FAILED TO LINK PROGRAM\n" << infoLog << std::endl;
}
}
unsigned int ShaderProgram::CompileShader(GLuint type, const char* source)
{
unsigned int shader = glCreateShader(type);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
int compilationResult;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compilationResult);
if (compilationResult == GL_FALSE)
{
char infoLog[512];
glGetShaderInfoLog(shader, 512, NULL, infoLog);
std::cout << "ERROR: FAILED TO COMPILE SHADER: "
<< (type == GL_VERTEX_SHADER ? "VERTEX" : "FRAGMENT")
<< " SHADER\n" << infoLog << std::endl;
}
return shader;
}
The error message I get sometimes seems random. Most of the time it's this:
ERROR: FAILED TO LINK PROGRAM
Vertex shader(s) failed to link, fragment shader(s) failed to link.
Vertex link error: INVALID_OPERATION.
ERROR: error(#97) No program main found
fragment link error: INVALID_OPERATION.
ERROR: error(#97) No program main found
But sometimes it's about a syntax error which is nowhere to be found really:
ERROR: FAILED TO COMPILE SHADER: VERTEX SHADER
Vertex shader failed to compile with the following errors:
ERROR: 0:1: error(#132) Syntax error: "0" parse error
ERROR: error(#273) 1 compilation errors. No code generated
ERROR: FAILED TO LINK PROGRAM
Vertex shader(s) were not successfully compiled before glLinkProgram() was called. Link failed.
I use GLFW 3.3.8 and Glad. I started with OpenGL version 3.3 and tried switching to 4.6 which had no effect. Also tried to update my GPU drivers to no success either. I really have no idea where this behaviour may be coming from.
CodePudding user response:
You have undefined behaviour.
vShaderStream.str().c_str();
str()
returns string by value. So this temporary string object is destroyed at the end of full expression, and the pointer obtained by c_str()
is dangling. As a solution you could do:
CreateShaderProgram(vShaderStream.str().c_str(), fShaderStream.str().c_str());
in case above, string temporaries are still alive when CreateShaderProgram is called.