16std::string read(
const char *filename )
18 std::stringbuf source;
19 std::ifstream in(filename);
20 if(in.good() ==
false)
21 printf(
"[error] loading program '%s'...\n", filename);
23 printf(
"loading program '%s'...\n", filename);
31std::string prepare_source( std::string file,
const std::string& definitions )
41 size_t b= file.find(
"#version");
42 if(b != std::string::npos)
44 size_t e = file.find(
'\n', b );
45 if(e != std::string::npos)
47 version= file.substr(0, e +1);
50 if(file.find(
"#version") != std::string::npos)
52 printf(
"[error] found several #version directives. failed.\n");
59 printf(
"[error] no #version directive found. failed.\n");
64 if(definitions.empty() ==
false)
66 source.append(version);
67 source.append(definitions).append(
"\n");
72 source.append(version);
81const char *shader_string(
const GLenum type )
85 case GL_VERTEX_SHADER:
return "vertex shader";
86 case GL_FRAGMENT_SHADER:
return "fragment shader";
87 case GL_GEOMETRY_SHADER:
return "geometry shader";
89 case GL_TESS_CONTROL_SHADER:
return "control shader";
90 case GL_TESS_EVALUATION_SHADER:
return "evaluation shader";
93 case GL_COMPUTE_SHADER:
return "compute shader";
95 #ifdef GL_EXT_mesh_shader
96 case GL_MESH_SHADER_EXT:
return "mesh shader";
97 case GL_TASK_SHADER_EXT:
return "task mesh shader";
100 default:
return "shader";
105const char *shader_keys[] =
110 "TESSELATION_CONTROL",
111 "EVALUATION_CONTROL",
116const int shader_keys_max= 8;
119GLenum shader_types[] =
125 GL_TESS_CONTROL_SHADER,
126 GL_TESS_EVALUATION_SHADER,
136#ifdef GL_EXT_mesh_shader
146GLuint compile_shader(
const GLuint program,
const GLenum shader_type,
const std::string& source )
148 if(source.size() == 0 || shader_type == 0)
151 GLuint shader= glCreateShader(shader_type);
152 glAttachShader(program, shader);
154 const char *sources= source.c_str();
155 glShaderSource(shader, 1, &sources, NULL);
156 glCompileShader(shader);
159 glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
160 return (status == GL_TRUE) ? shader : 0;
164int update_program(
const GLuint program,
const char *filename,
const char *definitions )
170 glGetProgramiv(program, GL_ATTACHED_SHADERS, &shaders_max);
173 std::vector<GLuint> shaders(shaders_max, 0);
174 glGetAttachedShaders(program, shaders_max, NULL, &shaders.front());
175 for (
int i = 0; i < shaders_max; i++)
177 glDetachShader(program, shaders[i]);
178 glDeleteShader(shaders[i]);
183 glObjectLabel(GL_PROGRAM, program, -1, filename);
187 std::string common_source= read(filename);
188 for(
int i = 0; i < shader_keys_max; i++)
190 if(common_source.find(shader_keys[i]) != std::string::npos)
193 std::string source= prepare_source(common_source, std::string(definitions).append(
"\n#define ").append(shader_keys[i]).append(
"\n"));
194 GLuint shader= compile_shader(program, shader_types[i], source);
196 printf(
"[error] compiling %s...\n%s\n", shader_string(shader_types[i]), definitions);
201 glLinkProgram(program);
205 glGetProgramiv(program, GL_LINK_STATUS, &status);
206 if(status == GL_FALSE)
208 printf(
"[error] linking program %u '%s'...\n", program, filename);
213 glUseProgram(program);
219 GLuint program= glCreateProgram();
228int reload_program(
const GLuint program,
const char *filename,
const char *definitions )
230 return update_program(program, filename, definitions);
247 glGetProgramiv(program, GL_ATTACHED_SHADERS, &shaders_max);
251 std::vector<GLuint> shaders(shaders_max, 0);
252 glGetAttachedShaders(program, shaders_max, NULL, &shaders.front());
253 for(
int i= 0; i < shaders_max; i++)
255 glDetachShader(program, shaders[i]);
256 glDeleteShader(shaders[i]);
260 glDeleteProgram(program);
270 GLint status= GL_FALSE;
271 glGetProgramiv(program, GL_LINK_STATUS, &status);
274 #ifdef GL_VERSION_4_3
276 glGetObjectLabel(GL_PROGRAM, program,
sizeof(label),
nullptr, label);
278 if(status == GL_FALSE)
279 printf(
"program %u '%s' %s...\n", program, label, (status == GL_TRUE) ?
"ready" :
"not ready");
281 printf(
"program %u %s...\n", program, (status == GL_TRUE) ?
"ready" :
"not ready");
285 return (status == GL_TRUE);
294 glGetProgramiv(program, GL_LINK_STATUS, &status);
297 #ifdef GL_VERSION_4_3
299 glGetObjectLabel(GL_PROGRAM, program,
sizeof(label),
nullptr, label);
301 if(status == GL_FALSE)
302 printf(
"program %u '%s' %s...\n", program, label, (status == GL_TRUE) ?
"ready" :
"not ready");
304 printf(
"program %u %s...\n", program, (status == GL_TRUE) ?
"ready" :
"not ready");
308 return (status == GL_FALSE);
315void print_line( std::string& errors,
const char *source,
const int begin_id,
const int line_id )
319 for(
unsigned int i= 0; source[i] != 0; i++)
327 if(line >= begin_id && line <= line_id)
330 errors.push_back(
'0' + (line / 1000) % 10);
331 errors.push_back(
'0' + (line / 100) % 10);
332 errors.push_back(
'0' + (line / 10) % 10);
333 errors.push_back(
'0' + (line / 1) % 10);
338 if(line >= begin_id && line <= line_id)
340 if(source[i] ==
'\t')
343 errors.push_back(source[i]);
350int print_errors( std::string& errors,
const char *log,
const char *source )
352 printf(
"[error log]\n%s\n", log);
354 int first_error= INT_MAX;
357 for(
int i= 0; log[i] != 0; i++)
360 int string_id= 0, line_id= 0, position= 0;
361 if(sscanf(&log[i],
"%d ( %d ) : %n", &string_id, &line_id, &position) == 2
362 || sscanf(&log[i],
"%d : %d (%*d) : %n", &string_id, &line_id, &position) == 2
363 || sscanf(&log[i],
"ERROR : %d : %d : %n", &string_id, &line_id, &position) == 2
364 || sscanf(&log[i],
"WARNING : %d : %d : %n", &string_id, &line_id, &position) == 2)
366 if(string_id != last_string || line_id != last_line)
369 first_error= std::min(first_error, line_id);
373 print_line(errors, source, last_line +1, line_id);
378 for(i+= position; log[i] != 0; i++)
380 errors.push_back(log[i]);
385 last_string= string_id;
389 print_line(errors, source, last_line +1, 1000);
401 errors.append(
"[error] no program...\n");
406 glGetProgramiv(program, GL_LINK_STATUS, &status);
407 if(status == GL_TRUE)
410 int first_error= INT_MAX;
413 glGetProgramiv(program, GL_ATTACHED_SHADERS, &shaders_max);
416 errors.append(
"[error] no shaders...\n");
420 std::vector<GLuint> shaders(shaders_max, 0);
421 glGetAttachedShaders(program, shaders_max, NULL, &shaders.front());
422 for(
int i= 0; i < shaders_max; i++)
425 glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &value);
426 if(value == GL_FALSE)
429 glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &value);
430 std::vector<char>log(value+1, 0);
431 glGetShaderInfoLog(shaders[i], (GLsizei) log.size(), NULL, &log.front());
434 glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &value);
435 std::vector<char> source(value+1, 0);
436 glGetShaderSource(shaders[i], (GLsizei) source.size(), NULL, &source.front());
438 glGetShaderiv(shaders[i], GL_SHADER_TYPE, &value);
439 errors.append(
"[error] compiling ").append(shader_string(value)).append(
"...\n");
442 int last_error= print_errors(errors, &log.front(), &source.front());
443 first_error= std::min(first_error, last_error);
450 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &value);
452 std::vector<char>log(value+1, 0);
453 glGetProgramInfoLog(program, (GLsizei) log.size(), NULL, &log.front());
455 errors.append(
"[error] linking program...\n").append(log.begin(), log.end());
465 if(errors.size() > 0)
467 if(filename !=
nullptr && filename[0] != 0)
468 printf(
"[error] compiling '%s'...\n%s\n", filename, errors.c_str());
470 printf(
"%s\n", errors.c_str());
PipelineProgram * reload(const GLuint program)
recharge et recompile un programme du cache.
PipelineProgram * insert(const char *filename, const char *definitions="")
ajoute un shader dans le cache
static PipelineCache & manager()
acces au singleton.
void printf(Text &text, const int px, const int py, const char *format,...)
affiche un texte a la position x, y. meme utilisation que printf().
GLuint read_program(const char *filename, const char *definitions)
int program_print_errors(const GLuint program, const char *filename)
affiche les erreurs de compilation.
int release_program(const GLuint program)
detruit les shaders et le program.
bool program_errors(const GLuint program)
renvoie vrai si le programme n'est pas pret.
int reload_program(const GLuint program, const char *filename, const char *definitions)
bool program_ready(const GLuint program)
renvoie vrai si le programme est pret. (pas d'erreurs de compilation des shaders, pas d'erreur de lin...
int program_format_errors(const GLuint program, std::string &errors)
renvoie les erreurs de compilation.