Fix crash when cleaning up GLSL shader

This commit is contained in:
rdb 2009-06-29 13:48:43 +00:00
parent 99df904c89
commit ab2737ac1a
5 changed files with 54 additions and 53 deletions

View File

@ -28,8 +28,7 @@ valid() {
#ifdef HAVE_CG
if (_cg_context) return true;
#endif
if (_shader->get_language() == Shader::SL_GLSL &&
_shader->_glsl_program != 0) {
if (_shader->get_language() == Shader::SL_GLSL && _glsl_program != 0) {
return true;
}
return false;

View File

@ -33,6 +33,10 @@ TypeHandle CLP(ShaderContext)::_type_handle;
CLP(ShaderContext)::
CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
_last_gsg = gsg;
_glsl_program = 0;
_glsl_vshader = 0;
_glsl_fshader = 0;
_glsl_gshader = 0;
#ifdef HAVE_CG
_cg_context = 0;
if (s->get_language() == Shader::SL_Cg) {
@ -93,24 +97,25 @@ CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
if (s->get_language() == Shader::SL_GLSL) {
// We compile and analyze the shader here, instead of in shader.cxx, to avoid gobj getting a dependency on GL stuff.
if (s->_glsl_program == 0) {
if (_glsl_program == 0) {
if (!glsl_compile_shader(gsg)) {
release_resources(gsg);
s->_error_flag = true;
return;
}
s->_glsl_parameter_map.clear();
}
// Analyze the uniforms and put them in _glsl_parameter_map
if (s->_glsl_parameter_map.size() == 0) {
int seqno = 0, texunitno = 0;
int num_uniforms, uniform_maxlength;
gsg->_glGetProgramiv(s->_glsl_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
gsg->_glGetProgramiv(s->_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_maxlength);
gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORMS, &num_uniforms);
gsg->_glGetProgramiv(_glsl_program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniform_maxlength);
for (int i = 0; i < num_uniforms; ++i) {
int param_size;
GLenum param_type;
char param_name[uniform_maxlength];
gsg->_glGetActiveUniform(_shader->_glsl_program, i, uniform_maxlength, NULL, &param_size, &param_type, param_name);
GLint p = gsg->_glGetUniformLocation(_shader->_glsl_program, param_name);
gsg->_glGetActiveUniform(_glsl_program, i, uniform_maxlength, NULL, &param_size, &param_type, param_name);
GLint p = gsg->_glGetUniformLocation(_glsl_program, param_name);
if (p > -1) {
Shader::ShaderArgId arg_id;
arg_id._name = param_name;
@ -259,24 +264,24 @@ release_resources(const GSG *gsg) {
if (!gsg) {
return;
}
if (_shader->_glsl_program != 0) {
if (!_shader->_glsl_vshader != 0) {
gsg->_glDetachShader(_shader->_glsl_program, _shader->_glsl_vshader);
gsg->_glDeleteShader(_shader->_glsl_vshader);
_shader->_glsl_vshader = 0;
if (_glsl_program != 0) {
if (!_glsl_vshader != 0) {
gsg->_glDetachShader(_glsl_program, _glsl_vshader);
gsg->_glDeleteShader(_glsl_vshader);
_glsl_vshader = 0;
}
if (!_shader->_glsl_fshader != 0) {
gsg->_glDetachShader(_shader->_glsl_program, _shader->_glsl_fshader);
gsg->_glDeleteShader(_shader->_glsl_fshader);
_shader->_glsl_fshader = 0;
if (!_glsl_fshader != 0) {
gsg->_glDetachShader(_glsl_program, _glsl_fshader);
gsg->_glDeleteShader(_glsl_fshader);
_glsl_fshader = 0;
}
if (!_shader->_glsl_gshader != 0) {
gsg->_glDetachShader(_shader->_glsl_program, _shader->_glsl_gshader);
gsg->_glDeleteShader(_shader->_glsl_gshader);
_shader->_glsl_gshader = 0;
if (!_glsl_gshader != 0) {
gsg->_glDetachShader(_glsl_program, _glsl_gshader);
gsg->_glDeleteShader(_glsl_gshader);
_glsl_gshader = 0;
}
gsg->_glDeleteProgram(_shader->_glsl_program);
_shader->_glsl_program = 0;
gsg->_glDeleteProgram(_glsl_program);
_glsl_program = 0;
}
}
@ -310,7 +315,7 @@ bind(GSG *gsg) {
#endif
if (_shader->get_language() == Shader::SL_GLSL && !_shader->get_error_flag()) {
gsg->_glUseProgram(_shader->_glsl_program);
gsg->_glUseProgram(_glsl_program);
}
if (glGetError() != GL_NO_ERROR) {
GLCAT.error() << "GL error in ShaderContext::bind\n";
@ -789,48 +794,48 @@ glsl_compile_shader(GSG *gsg) {
// Terribly hacky. I hope this will go away when we
// add support for separated shader programs later.
_shader->_glsl_program = gsg->_glCreateProgram();
if (!_shader->_glsl_program) return false;
_glsl_program = gsg->_glCreateProgram();
if (!_glsl_program) return false;
if (_shader->_text.find("vshader") != -1) {
_shader->_glsl_vshader = glsl_compile_entry_point(gsg, "vshader", Shader::ST_VERTEX);
if (!_shader->_glsl_vshader) return false;
gsg->_glAttachShader(_shader->_glsl_program, _shader->_glsl_vshader);
_glsl_vshader = glsl_compile_entry_point(gsg, "vshader", Shader::ST_VERTEX);
if (!_glsl_vshader) return false;
gsg->_glAttachShader(_glsl_program, _glsl_vshader);
} else {
GLCAT.warning() << "Could not locate function 'vshader' in shader text!\n";
}
if (_shader->_text.find("fshader") != -1) {
_shader->_glsl_fshader = glsl_compile_entry_point(gsg, "fshader", Shader::ST_FRAGMENT);
if (!_shader->_glsl_fshader) return false;
gsg->_glAttachShader(_shader->_glsl_program, _shader->_glsl_fshader);
_glsl_fshader = glsl_compile_entry_point(gsg, "fshader", Shader::ST_FRAGMENT);
if (!_glsl_fshader) return false;
gsg->_glAttachShader(_glsl_program, _glsl_fshader);
} else {
GLCAT.warning() << "Could not locate function 'fshader' in shader text!\n";
}
if (_shader->_text.find("gshader") != -1) {
_shader->_glsl_gshader = glsl_compile_entry_point(gsg, "gshader", Shader::ST_GEOMETRY);
if (!_shader->_glsl_gshader) return false;
gsg->_glAttachShader(_shader->_glsl_program, _shader->_glsl_gshader);
_glsl_gshader = glsl_compile_entry_point(gsg, "gshader", Shader::ST_GEOMETRY);
if (!_glsl_gshader) return false;
gsg->_glAttachShader(_glsl_program, _glsl_gshader);
}
gsg->_glLinkProgram(_shader->_glsl_program);
gsg->_glLinkProgram(_glsl_program);
int status;
gsg->_glGetProgramiv(_shader->_glsl_program, GL_LINK_STATUS, &status);
gsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status);
if (status != GL_TRUE) {
GLCAT.error() << "An error occurred while linking shader program!\n";
glsl_report_program_errors(gsg, _shader->_glsl_program);
glsl_report_program_errors(gsg, _glsl_program);
return false;
}
// There might be warnings. Only report them for one shader program.
if (_shader->_glsl_vshader != 0) {
glsl_report_shader_errors(gsg, _shader->_glsl_vshader);
} else if (_shader->_glsl_fshader != 0) {
glsl_report_shader_errors(gsg, _shader->_glsl_fshader);
} else if (_shader->_glsl_gshader != 0) {
glsl_report_shader_errors(gsg, _shader->_glsl_gshader);
if (_glsl_vshader != 0) {
glsl_report_shader_errors(gsg, _glsl_vshader);
} else if (_glsl_fshader != 0) {
glsl_report_shader_errors(gsg, _glsl_fshader);
} else if (_glsl_gshader != 0) {
glsl_report_shader_errors(gsg, _glsl_gshader);
}
if (glGetError() != GL_NO_ERROR) {

View File

@ -62,6 +62,11 @@ private:
void cg_report_errors();
#endif
GLuint _glsl_program;
GLuint _glsl_vshader;
GLuint _glsl_fshader;
GLuint _glsl_gshader;
int _stage_offset;
// Avoid using this! It merely exists so the
// destructor has access to the extension functions.

View File

@ -1589,10 +1589,6 @@ Shader(const Filename &filename, const string &text, const ShaderLanguage &lang)
_language(lang)
{
_error_flag = false;
_glsl_program = 0;
_glsl_vshader = 0;
_glsl_fshader = 0;
_glsl_gshader = 0;
#ifdef HAVE_CG
_cg_context = 0;

View File

@ -281,10 +281,6 @@ public:
void clear_parameters();
public:
unsigned int _glsl_program;
unsigned int _glsl_vshader;
unsigned int _glsl_fshader;
unsigned int _glsl_gshader;
pvector<int> _glsl_parameter_map;
#ifdef HAVE_CG