glsl2: Move ir_to_mesa handling to driver CompileShader and LinkShader hooks.
authorEric Anholt <eric@anholt.net>
Wed, 11 Aug 2010 03:11:44 +0000 (20:11 -0700)
committerEric Anholt <eric@anholt.net>
Sat, 14 Aug 2010 00:54:42 +0000 (17:54 -0700)
This lets drivers override ir_to_mesa with their own codegen, or at
least have a native alternative.

src/mesa/main/dd.h
src/mesa/main/shaderobj.c
src/mesa/program/ir_to_mesa.cpp
src/mesa/program/ir_to_mesa.h

index 825073ca886cd0c068f8344285ee9d7416e8a177..71d0f570e4b6138c62e71d32605f7f0d22ca9c2b 100644 (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.
index 129d97422471a581dc0010c981e7df9dc7adeea1..863d50fbe559f1e20d00961feea966c723dea5db 100644 (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;
 }
index c8c655b29675848523f0bb5f9a9a8ffd91ea1812..7490ffa4fe71cf08647bf854c3dd1b9ff3c51511 100644 (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;
    }
 }
 
index e832f84e754edbca8e7444bca0f3fb966b870250..ecaacde4bb0960b6ccd4a19e76fd17f166d711b5 100644 (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
 }