mirror of
https://github.com/libretro/ppsspp.git
synced 2025-02-25 11:20:55 +00:00
Do not crash on broken shaders, allow error message return
This commit is contained in:
parent
a25169dc4c
commit
d19cef2395
@ -7,6 +7,10 @@
|
||||
// Disable annoying warnings in VS
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable:4996) //strcpy may be dangerous
|
||||
|
||||
#if !defined(snprintf)
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef Crash
|
||||
@ -66,10 +70,10 @@ inline void Crash() {
|
||||
|
||||
void OutputDebugStringUTF8(const char *p);
|
||||
|
||||
#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);}
|
||||
#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);}
|
||||
#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);}
|
||||
#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += sprintf(p, "F: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();}
|
||||
#define ILOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "I: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "I: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);}
|
||||
#define WLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "W: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "W: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);}
|
||||
#define ELOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "E: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "E: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp);}
|
||||
#define FLOG(...) {char temp[512]; char *p = temp; p += sprintf(p, "F: %s:%i: ", __FILE__, __LINE__); p += snprintf(p, 450, "F: " __VA_ARGS__); p += sprintf(p, "\n"); OutputDebugStringUTF8(temp); Crash();}
|
||||
|
||||
// TODO: Win32 version using OutputDebugString
|
||||
#else
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
static std::set<GLSLProgram *> active_programs;
|
||||
|
||||
bool CompileShader(const char *source, GLuint shader, const char *filename) {
|
||||
bool CompileShader(const char *source, GLuint shader, const char *filename, std::string *error_message) {
|
||||
glShaderSource(shader, 1, &source, NULL);
|
||||
glCompileShader(shader);
|
||||
GLint success;
|
||||
@ -24,12 +24,14 @@ bool CompileShader(const char *source, GLuint shader, const char *filename) {
|
||||
ELOG("Error in shader compilation of %s!\n", filename);
|
||||
ELOG("Info log: %s\n", infoLog);
|
||||
ELOG("Shader source:\n%s\n", (const char *)source);
|
||||
if (error_message)
|
||||
*error_message = infoLog;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GLSLProgram *glsl_create(const char *vshader, const char *fshader) {
|
||||
GLSLProgram *glsl_create(const char *vshader, const char *fshader, std::string *error_message) {
|
||||
GLSLProgram *program = new GLSLProgram();
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
@ -39,18 +41,18 @@ GLSLProgram *glsl_create(const char *vshader, const char *fshader) {
|
||||
strcpy(program->name, vshader + strlen(vshader) - 15);
|
||||
strcpy(program->vshader_filename, vshader);
|
||||
strcpy(program->fshader_filename, fshader);
|
||||
if (glsl_recompile(program)) {
|
||||
if (glsl_recompile(program, error_message)) {
|
||||
active_programs.insert(program);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLOG("Failed building GLSL program: %s %s", vshader, fshader);
|
||||
} else {
|
||||
ELOG("Failed compiling GLSL program: %s %s", vshader, fshader);
|
||||
delete program;
|
||||
return 0;
|
||||
}
|
||||
register_gl_resource_holder(program);
|
||||
return program;
|
||||
}
|
||||
|
||||
GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src) {
|
||||
GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src, std::string *error_message) {
|
||||
GLSLProgram *program = new GLSLProgram();
|
||||
program->program_ = 0;
|
||||
program->vsh_ = 0;
|
||||
@ -60,8 +62,12 @@ GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src
|
||||
strcpy(program->name, "[srcshader]");
|
||||
strcpy(program->vshader_filename, "");
|
||||
strcpy(program->fshader_filename, "");
|
||||
if (glsl_recompile(program)) {
|
||||
if (glsl_recompile(program, error_message)) {
|
||||
active_programs.insert(program);
|
||||
} else {
|
||||
ELOG("Failed compiling GLSL program from source strings");
|
||||
delete program;
|
||||
return 0;
|
||||
}
|
||||
register_gl_resource_holder(program);
|
||||
return program;
|
||||
@ -89,7 +95,7 @@ void glsl_refresh() {
|
||||
}
|
||||
}
|
||||
|
||||
bool glsl_recompile(GLSLProgram *program) {
|
||||
bool glsl_recompile(GLSLProgram *program, std::string *error_message) {
|
||||
struct stat vs, fs;
|
||||
if (0 == stat(program->vshader_filename, &vs))
|
||||
program->vshader_mtime = vs.st_mtime;
|
||||
@ -125,14 +131,14 @@ bool glsl_recompile(GLSLProgram *program) {
|
||||
|
||||
GLuint vsh = glCreateShader(GL_VERTEX_SHADER);
|
||||
const GLchar *vsh_str = program->vshader_source ? program->vshader_source : (const GLchar *)(vsh_src);
|
||||
if (!CompileShader(vsh_str, vsh, program->vshader_filename)) {
|
||||
if (!CompileShader(vsh_str, vsh, program->vshader_filename, error_message)) {
|
||||
return false;
|
||||
}
|
||||
delete [] vsh_src;
|
||||
|
||||
const GLchar *fsh_str = program->fshader_source ? program->fshader_source : (const GLchar *)(fsh_src);
|
||||
GLuint fsh = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!CompileShader(fsh_str, fsh, program->fshader_filename)) {
|
||||
if (!CompileShader(fsh_str, fsh, program->fshader_filename, error_message)) {
|
||||
glDeleteShader(vsh);
|
||||
return false;
|
||||
}
|
||||
@ -150,14 +156,20 @@ bool glsl_recompile(GLSLProgram *program) {
|
||||
GLint bufLength = 0;
|
||||
glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &bufLength);
|
||||
if (bufLength) {
|
||||
char* buf = new char[bufLength];
|
||||
char* buf = new char[bufLength + 1]; // safety
|
||||
glGetProgramInfoLog(prog, bufLength, NULL, buf);
|
||||
ILOG("vsh: %i fsh: %i", vsh, fsh);
|
||||
FLOG("Could not link shader program (linkstatus=%i):\n %s \n", linkStatus, buf);
|
||||
delete [] buf; // we're dead!
|
||||
ELOG("Could not link shader program (linkstatus=%i):\n %s \n", linkStatus, buf);
|
||||
if (error_message) {
|
||||
*error_message = buf;
|
||||
}
|
||||
delete [] buf;
|
||||
} else {
|
||||
ILOG("vsh: %i fsh: %i", vsh, fsh);
|
||||
FLOG("Could not link shader program (linkstatus=%i). No OpenGL error log was available.", linkStatus);
|
||||
ELOG("Could not link shader program (linkstatus=%i). No OpenGL error log was available.", linkStatus);
|
||||
if (error_message) {
|
||||
*error_message = "(no error message available)";
|
||||
}
|
||||
}
|
||||
glDeleteShader(vsh);
|
||||
glDeleteShader(fsh);
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Utility code for loading GLSL shaders.
|
||||
// Has support for auto-reload, see glsl_refresh
|
||||
|
||||
#ifndef _RENDER_UTIL
|
||||
#define _RENDER_UTIL
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
|
||||
#include "gfx/gl_lost_manager.h"
|
||||
@ -46,18 +46,17 @@ struct GLSLProgram : public GfxResourceHolder {
|
||||
void GLLost();
|
||||
};
|
||||
|
||||
|
||||
// C API, old skool
|
||||
// C API, old skool. Not much point either...
|
||||
|
||||
// From files (VFS)
|
||||
GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file);
|
||||
GLSLProgram *glsl_create(const char *vshader_file, const char *fshader_file, std::string *error_message = 0);
|
||||
// Directly from source code
|
||||
GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src);
|
||||
GLSLProgram *glsl_create_source(const char *vshader_src, const char *fshader_src, std::string *error_message = 0);
|
||||
void glsl_destroy(GLSLProgram *program);
|
||||
|
||||
// If recompilation of the program fails, the program is untouched and error messages
|
||||
// are logged and the function returns false.
|
||||
bool glsl_recompile(GLSLProgram *program);
|
||||
bool glsl_recompile(GLSLProgram *program, std::string *error_message = 0);
|
||||
void glsl_bind(const GLSLProgram *program);
|
||||
void glsl_unbind();
|
||||
int glsl_attrib_loc(const GLSLProgram *program, const char *name);
|
||||
@ -67,7 +66,3 @@ int glsl_uniform_loc(const GLSLProgram *program, const char *name);
|
||||
// fstat-s all the source files of all the shaders to see if they
|
||||
// should be recompiled, and recompiles them if so.
|
||||
void glsl_refresh();
|
||||
|
||||
// Use glUseProgramObjectARB(NULL); to unset.
|
||||
|
||||
#endif // _RENDER_UTIL
|
||||
|
Loading…
x
Reference in New Issue
Block a user