glsl: better handling of linker failures
Upon link error, exit translation loop, free program instructions. Check for null pointers in calling code.
This commit is contained in:
@@ -2609,8 +2609,9 @@ set_uniform_initializers(struct gl_context *ctx,
|
|||||||
/**
|
/**
|
||||||
* Convert a shader's GLSL IR into a Mesa gl_program.
|
* Convert a shader's GLSL IR into a Mesa gl_program.
|
||||||
*/
|
*/
|
||||||
struct gl_program *
|
static struct gl_program *
|
||||||
get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program,
|
get_mesa_program(struct gl_context *ctx,
|
||||||
|
struct gl_shader_program *shader_program,
|
||||||
struct gl_shader *shader)
|
struct gl_shader *shader)
|
||||||
{
|
{
|
||||||
ir_to_mesa_visitor v;
|
ir_to_mesa_visitor v;
|
||||||
@@ -2756,6 +2757,15 @@ get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_progra
|
|||||||
|
|
||||||
mesa_inst++;
|
mesa_inst++;
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
if (!shader_program->LinkStatus)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shader_program->LinkStatus) {
|
||||||
|
free(mesa_instructions);
|
||||||
|
_mesa_reference_program(ctx, &shader->Program, NULL);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_branchtargets(&v, mesa_instructions, num_instructions);
|
set_branchtargets(&v, mesa_instructions, num_instructions);
|
||||||
@@ -2866,30 +2876,34 @@ _mesa_ir_link_shader(struct gl_context *ctx, struct gl_shader_program *prog)
|
|||||||
|
|
||||||
for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
|
for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
|
||||||
struct gl_program *linked_prog;
|
struct gl_program *linked_prog;
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (prog->_LinkedShaders[i] == NULL)
|
if (prog->_LinkedShaders[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
|
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
|
||||||
|
|
||||||
switch (prog->_LinkedShaders[i]->Type) {
|
if (linked_prog) {
|
||||||
case GL_VERTEX_SHADER:
|
bool ok = true;
|
||||||
_mesa_reference_vertprog(ctx, &prog->VertexProgram,
|
|
||||||
(struct gl_vertex_program *)linked_prog);
|
switch (prog->_LinkedShaders[i]->Type) {
|
||||||
ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
|
case GL_VERTEX_SHADER:
|
||||||
linked_prog);
|
_mesa_reference_vertprog(ctx, &prog->VertexProgram,
|
||||||
break;
|
(struct gl_vertex_program *)linked_prog);
|
||||||
case GL_FRAGMENT_SHADER:
|
ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
|
||||||
_mesa_reference_fragprog(ctx, &prog->FragmentProgram,
|
linked_prog);
|
||||||
(struct gl_fragment_program *)linked_prog);
|
break;
|
||||||
ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
|
case GL_FRAGMENT_SHADER:
|
||||||
linked_prog);
|
_mesa_reference_fragprog(ctx, &prog->FragmentProgram,
|
||||||
break;
|
(struct gl_fragment_program *)linked_prog);
|
||||||
}
|
ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
|
||||||
if (!ok) {
|
linked_prog);
|
||||||
return GL_FALSE;
|
break;
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
return GL_FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_mesa_reference_program(ctx, &linked_prog, NULL);
|
_mesa_reference_program(ctx, &linked_prog, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user