glsl2: Move ir_to_mesa handling to driver CompileShader and LinkShader hooks.

This lets drivers override ir_to_mesa with their own codegen, or at
least have a native alternative.
This commit is contained in:
Eric Anholt 2010-08-10 20:11:44 -07:00
parent 013bbbbb0a
commit d19eecef54
4 changed files with 99 additions and 52 deletions

View file

@ -595,6 +595,27 @@ struct dd_function_table {
/*@}*/
/**
* \name GLSL shader/program functions.
*/
/*@{*/
/**
* Called when a shader is compiled.
*
* Note that not all shader objects get ShaderCompile called on
* them. Notably, the shaders containing builtin functions do not
* have CompileShader() called, so if lowering passes are done they
* need to also be performed in LinkShader().
*/
GLboolean (*CompileShader)(GLcontext *ctx, struct gl_shader *shader);
/**
* Called when a shader program is linked.
*
* This gives drivers an opportunity to clone the IR and make their
* own transformations on it for the purposes of code generation.
*/
GLboolean (*LinkShader)(GLcontext *ctx, struct gl_shader_program *shader);
/*@}*/
/**
* \name State-changing functions.

View file

@ -387,4 +387,6 @@ _mesa_init_shader_object_functions(struct dd_function_table *driver)
driver->DeleteShader = __mesa_delete_shader;
driver->NewShaderProgram = _mesa_new_shader_program;
driver->DeleteShaderProgram = __mesa_delete_shader_program;
driver->CompileShader = _mesa_ir_compile_shader;
driver->LinkShader = _mesa_ir_link_shader;
}

View file

@ -2543,6 +2543,72 @@ get_mesa_program(GLcontext *ctx, struct gl_shader_program *shader_program,
}
extern "C" {
GLboolean
_mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader)
{
assert(shader->CompileStatus);
return GL_TRUE;
}
GLboolean
_mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
{
assert(prog->LinkStatus);
for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
bool progress;
exec_list *ir = prog->_LinkedShaders[i]->ir;
do {
progress = false;
/* Lowering */
do_mat_op_to_vec(ir);
do_mod_to_fract(ir);
do_div_to_mul_rcp(ir);
do_explog_to_explog2(ir);
progress = do_common_optimization(ir, true) || progress;
if (ctx->Shader.EmitNoIfs)
progress = do_if_to_cond_assign(ir) || progress;
progress = do_vec_index_to_cond_assign(ir) || progress;
} while (progress);
validate_ir_tree(ir);
}
for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
struct gl_program *linked_prog;
bool ok = true;
linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog);
switch (prog->_LinkedShaders[i]->Type) {
case GL_VERTEX_SHADER:
_mesa_reference_vertprog(ctx, &prog->VertexProgram,
(struct gl_vertex_program *)linked_prog);
ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
linked_prog);
break;
case GL_FRAGMENT_SHADER:
_mesa_reference_fragprog(ctx, &prog->FragmentProgram,
(struct gl_fragment_program *)linked_prog);
ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
linked_prog);
break;
}
if (!ok) {
return GL_FALSE;
}
}
return GL_TRUE;
}
void
_mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
@ -2604,7 +2670,12 @@ _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *shader)
reparent_ir(shader->ir, shader);
talloc_free(state);
}
if (shader->CompileStatus) {
if (!ctx->Driver.CompileShader(ctx, shader))
shader->CompileStatus = GL_FALSE;
}
}
void
_mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
@ -2639,57 +2710,8 @@ _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
}
if (prog->LinkStatus) {
for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
bool progress;
exec_list *ir = prog->_LinkedShaders[i]->ir;
do {
progress = false;
/* Lowering */
do_mat_op_to_vec(ir);
do_mod_to_fract(ir);
do_div_to_mul_rcp(ir);
do_explog_to_explog2(ir);
progress = do_common_optimization(ir, true) || progress;
if (ctx->Shader.EmitNoIfs)
progress = do_if_to_cond_assign(ir) || progress;
progress = do_vec_index_to_cond_assign(ir) || progress;
} while (progress);
}
}
if (prog->LinkStatus) {
for (i = 0; i < prog->_NumLinkedShaders; i++) {
struct gl_program *linked_prog;
bool ok = true;
linked_prog = get_mesa_program(ctx, prog,
prog->_LinkedShaders[i]);
link_uniforms_to_shared_uniform_list(prog->Uniforms, linked_prog);
switch (prog->_LinkedShaders[i]->Type) {
case GL_VERTEX_SHADER:
_mesa_reference_vertprog(ctx, &prog->VertexProgram,
(struct gl_vertex_program *)linked_prog);
ok = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,
linked_prog);
break;
case GL_FRAGMENT_SHADER:
_mesa_reference_fragprog(ctx, &prog->FragmentProgram,
(struct gl_fragment_program *)linked_prog);
ok = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,
linked_prog);
break;
}
if (!ok) {
prog->LinkStatus = GL_FALSE;
}
}
if (!ctx->Driver.LinkShader(ctx, prog))
prog->LinkStatus = GL_FALSE;
}
}

View file

@ -30,6 +30,8 @@ extern "C" {
void _mesa_glsl_compile_shader(GLcontext *ctx, struct gl_shader *sh);
void _mesa_glsl_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
GLboolean _mesa_ir_compile_shader(GLcontext *ctx, struct gl_shader *shader);
GLboolean _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog);
#ifdef __cplusplus
}