summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/mesa/main/dd.h21
-rw-r--r--src/mesa/main/shaderobj.c2
-rw-r--r--src/mesa/program/ir_to_mesa.cpp126
-rw-r--r--src/mesa/program/ir_to_mesa.h2
4 files changed, 99 insertions, 52 deletions
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
index 825073ca886..71d0f570e4b 100644
--- a/src/mesa/main/dd.h
+++ b/src/mesa/main/dd.h
@@ -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.
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 129d9742247..863d50fbe55 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -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;
}
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index c8c655b2967..7490ffa4fe7 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -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;
}
}
diff --git a/src/mesa/program/ir_to_mesa.h b/src/mesa/program/ir_to_mesa.h
index e832f84e754..ecaacde4bb0 100644
--- a/src/mesa/program/ir_to_mesa.h
+++ b/src/mesa/program/ir_to_mesa.h
@@ -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
}