diff options
Diffstat (limited to 'src/glsl')
| -rw-r--r-- | src/glsl/linker.cpp | 81 | ||||
| -rw-r--r-- | src/glsl/main.cpp | 22 | 
2 files changed, 89 insertions, 14 deletions
| diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index eb10f90a91..e70fa31a2b 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -77,9 +77,8 @@ extern "C" {  #include "ir.h"  #include "ir_optimization.h"  #include "program.h" -extern "C" {  #include "hash_table.h" -} +#include "shader_api.h"  /**   * Visitor that determines whether or not a variable is ever written. @@ -399,6 +398,53 @@ cross_validate_outputs_to_inputs(struct gl_shader_program *prog,  } +/** + * Populates a shaders symbol table with all global declarations + */ +static void +populate_symbol_table(gl_shader *sh) +{ +   sh->symbols = new(sh) glsl_symbol_table; + +   foreach_list(node, sh->ir) { +      ir_instruction *const inst = (ir_instruction *) node; +      ir_variable *var; +      ir_function *func; + +      if ((func = inst->as_function()) != NULL) { +	 sh->symbols->add_function(func->name, func); +      } else if ((var = inst->as_variable()) != NULL) { +	 sh->symbols->add_variable(var->name, var); +      } +   } +} + + +/** + * Combine a group of shaders for a single stage to generate a linked shader + * + * \note + * If this function is supplied a single shader, it is cloned, and the new + * shader is returned. + */ +static struct gl_shader * +link_intrastage_shaders(struct gl_shader_program *prog, +			struct gl_shader **shader_list, +			unsigned num_shaders) +{ +   (void) prog; +   assert(num_shaders == 1); + +   gl_shader *const linked = _mesa_new_shader(NULL, 0, shader_list[0]->Type); +   linked->ir = new(linked) exec_list; +   clone_ir_list(linked->ir, shader_list[0]->ir); + +   populate_symbol_table(linked); + +   return linked; +} + +  struct uniform_node {     exec_node link;     struct gl_uniform *u; @@ -807,25 +853,32 @@ link_shaders(struct gl_shader_program *prog)     }     /* FINISHME: Implement intra-stage linking. */ -   assert(num_vert_shaders <= 1); -   assert(num_frag_shaders <= 1); - -   /* Verify that each of the per-target executables is valid. -    */ -   if (!validate_vertex_shader_executable(prog, vert_shader_list[0]) -       || !validate_fragment_shader_executable(prog, frag_shader_list[0])) -      goto done; +   prog->_NumLinkedShaders = 0; +   if (num_vert_shaders > 0) { +      gl_shader *const sh = +	 link_intrastage_shaders(prog, vert_shader_list, num_vert_shaders); +      if (sh == NULL) +	 goto done; -   prog->_NumLinkedShaders = 0; +      if (!validate_vertex_shader_executable(prog, sh)) +	  goto done; -   if (num_vert_shaders > 0) { -      prog->_LinkedShaders[prog->_NumLinkedShaders] = vert_shader_list[0]; +      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;        prog->_NumLinkedShaders++;     }     if (num_frag_shaders > 0) { -      prog->_LinkedShaders[prog->_NumLinkedShaders] = frag_shader_list[0]; +      gl_shader *const sh = +	 link_intrastage_shaders(prog, frag_shader_list, num_frag_shaders); + +      if (sh == NULL) +	 goto done; + +      if (!validate_fragment_shader_executable(prog, sh)) +	  goto done; + +      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;        prog->_NumLinkedShaders++;     } diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp index dd43d12474..8b0bccdcb7 100644 --- a/src/glsl/main.cpp +++ b/src/glsl/main.cpp @@ -36,6 +36,25 @@  #include "ir_print_visitor.h"  #include "program.h" +extern "C" struct gl_shader * +_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type); + +/* Copied from shader_api.c for the stand-alone compiler. + */ +struct gl_shader * +_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type) +{ +   struct gl_shader *shader; +   assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER); +   shader = talloc_zero(NULL, struct gl_shader); +   if (shader) { +      shader->Type = type; +      shader->Name = name; +      shader->RefCount = 1; +   } +   return shader; +} +  /* Returned string will have 'ctx' as its talloc owner. */  static char *  load_text_file(void *ctx, const char *file_name) @@ -271,6 +290,9 @@ main(int argc, char **argv)  	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);     } +   for (unsigned i = 0; i < whole_program->_NumLinkedShaders; i++) +      talloc_free(whole_program->_LinkedShaders[i]); +     talloc_free(whole_program);     _mesa_glsl_release_types(); | 
