diff options
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/main/mtypes.h | 1 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.c | 19 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_codegen.h | 1 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_compile.c | 2 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 7 | ||||
| -rw-r--r-- | src/mesa/shader/slang/slang_link.c | 132 | 
6 files changed, 139 insertions, 23 deletions
| diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index a5d3be3543..e77dd1d226 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1974,6 +1974,7 @@ struct gl_shader     GLboolean DeletePending;     GLboolean CompileStatus;     GLboolean Main;  /**< shader defines main() */ +   GLboolean UnresolvedRefs;     const GLchar *Source;  /**< Source code string */     struct gl_program *Program;  /**< Post-compile assembly code */     GLchar *InfoLog; diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index a7cfc45e6f..6d693c9027 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -2199,12 +2199,13 @@ _slang_gen_function_call_name(slang_assemble_ctx *A, const char *name,                             name);        return NULL;     } +     if (!fun->body) { -      slang_info_log_error(A->log, -                           "Function '%s' prototyped but not defined.  " -                           "Separate compilation units not supported.", -                           name); -      return NULL; +      /* The function body may be in another compilation unit. +       * We'll try concatenating the shaders and recompile at link time. +       */ +      A->UnresolvedRefs = GL_TRUE; +      return new_node1(IR_NOP, NULL);     }     /* type checking to be sure function's return type matches 'dest' type */ @@ -4648,6 +4649,14 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)     printf("************* End codegen function ************\n\n");  #endif +   if (A->UnresolvedRefs) { +      /* Can't codegen at this time. +       * At link time we'll concatenate all the vertex shaders and/or all +       * the fragment shaders and try recompiling. +       */ +      return GL_TRUE; +   } +     /* Emit program instructions */     success = _slang_emit_code(n, A->vartable, A->program, A->pragmas, GL_TRUE, A->log);     _slang_free_ir_tree(n); diff --git a/src/mesa/shader/slang/slang_codegen.h b/src/mesa/shader/slang/slang_codegen.h index e812c1f7ea..d80013ad34 100644 --- a/src/mesa/shader/slang/slang_codegen.h +++ b/src/mesa/shader/slang/slang_codegen.h @@ -43,6 +43,7 @@ typedef struct slang_assemble_ctx_     struct slang_ir_node_ *CurLoop;     struct slang_function_ *CurFunction;     GLuint UnrollLoop; +   GLboolean UnresolvedRefs;  } slang_assemble_ctx; diff --git a/src/mesa/shader/slang/slang_compile.c b/src/mesa/shader/slang/slang_compile.c index fb7128841c..6348f799aa 100644 --- a/src/mesa/shader/slang/slang_compile.c +++ b/src/mesa/shader/slang/slang_compile.c @@ -2435,6 +2435,8 @@ parse_code_unit(slang_parse_ctx * C, slang_code_unit * unit,        _slang_codegen_function(&A, mainFunc);        shader->Main = GL_TRUE; /* this shader defines main() */ + +      shader->UnresolvedRefs = A.UnresolvedRefs;     }     _slang_pop_var_table(o.vartable); diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 1b1edb4460..8493c490fb 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -62,6 +62,8 @@ typedef struct     GLuint MaxInstructions;  /**< size of prog->Instructions[] buffer */ +   GLboolean UnresolvedFunctions; +     /* code-gen options */     GLboolean EmitHighLevelInstructions;     GLboolean EmitCondCodes; @@ -872,6 +874,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)     emit(emitInfo, n->Children[1]);     if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) { +      /* XXX this error should have been caught in slang_codegen.c */        slang_info_log_error(emitInfo->log, "invalid operands to == or !=");        n->Store = NULL;        return NULL; @@ -1356,7 +1359,8 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n)     inst = emit(emitInfo, n->Children[1]);     if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) { -      if (!emitInfo->log->text) { +      if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) { +         /* XXX this error should have been caught in slang_codegen.c */           slang_info_log_error(emitInfo->log, "invalid assignment");        }        return NULL; @@ -2155,6 +2159,7 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n)        if (index < 0) {           /* error */           char s[100]; +         /* XXX isn't this really an out of memory/resources error? */           _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'",                          (char *) n->Var->a_name);           slang_info_log_error(emitInfo->log, s); diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index f98434892b..e2daf72e7d 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -534,6 +534,106 @@ _slang_update_inputs_outputs(struct gl_program *prog)  } + + + +/** + * Return a new shader whose source code is the concatenation of + * all the shader sources of the given type. + */ +static struct gl_shader * +concat_shaders(struct gl_shader_program *shProg, GLenum shaderType) +{ +   struct gl_shader *newShader; +   const struct gl_shader *firstShader = NULL; +   GLuint shaderLengths[100]; +   GLchar *source; +   GLuint totalLen = 0, len = 0; +   GLuint i; + +   /* compute total size of new shader source code */ +   for (i = 0; i < shProg->NumShaders; i++) { +      const struct gl_shader *shader = shProg->Shaders[i]; +      if (shader->Type == shaderType) { +         shaderLengths[i] = _mesa_strlen(shader->Source); +         totalLen += shaderLengths[i]; +         if (!firstShader) +            firstShader = shader; +      } +   } + +   source = (GLchar *) _mesa_malloc(totalLen + 1); +   if (!source) +      return NULL; + +   /* concatenate shaders */ +   for (i = 0; i < shProg->NumShaders; i++) { +      const struct gl_shader *shader = shProg->Shaders[i]; +      if (shader->Type == shaderType) { +         _mesa_memcpy(source + len, shader->Source, shaderLengths[i]); +         len += shaderLengths[i]; +      } +   } +   source[len] = '\0'; +   /* +   _mesa_printf("---NEW CONCATENATED SHADER---:\n%s\n------------\n", source); +   */ + +   newShader = CALLOC_STRUCT(gl_shader); +   newShader->Type = shaderType; +   newShader->Source = source; +   newShader->Pragmas = firstShader->Pragmas; + +   return newShader; +} + + +/** + * Search the shader program's list of shaders to find the one that + * defines main(). + * This will involve shader concatenation and recompilation if needed. + */ +static struct gl_shader * +get_main_shader(GLcontext *ctx, +                struct gl_shader_program *shProg, GLenum type) +{ +   struct gl_shader *shader = NULL; +   GLuint i; + +   /* +    * Look for a shader that defines main() and has no unresolved references. +    */ +   for (i = 0; i < shProg->NumShaders; i++) { +      shader = shProg->Shaders[i]; +      if (shader->Type == type && +          shader->Main && +          !shader->UnresolvedRefs) { +         /* All set! */ +         return shader; +      } +   } + +   /* +    * There must have been unresolved references during the original +    * compilation.  Try concatenating all the shaders of the given type +    * and recompile that. +    */ +   shader = concat_shaders(shProg, type); + +   _slang_compile(ctx, shader); + +   /* Finally, check if recompiling failed */ +   if (!shader->CompileStatus || +       !shader->Main || +       shader->UnresolvedRefs) { +      link_error(shProg, "Unresolved symbols"); +      return NULL; +   } + +   return shader; +} + +  /**   * Shader linker.  Currently:   * @@ -557,6 +657,9 @@ _slang_link(GLcontext *ctx,     _mesa_clear_shader_program_data(ctx, shProg); +   /* Initialize LinkStatus to "success".  Will be cleared if error. */ +   shProg->LinkStatus = GL_TRUE; +     /* check that all programs compiled successfully */     for (i = 0; i < shProg->NumShaders; i++) {        if (!shProg->Shaders[i]->CompileStatus) { @@ -568,24 +671,19 @@ _slang_link(GLcontext *ctx,     shProg->Uniforms = _mesa_new_uniform_list();     shProg->Varying = _mesa_new_parameter_list(); -   /** -    * Find attached vertex, fragment shaders defining main() +   /* +    * Find the vertex and fragment shaders which define main()      */ -   vertProg = NULL; -   fragProg = NULL; -   for (i = 0; i < shProg->NumShaders; i++) { -      struct gl_shader *shader = shProg->Shaders[i]; -      if (shader->Type == GL_VERTEX_SHADER) { -         if (shader->Main) -            vertProg = vertex_program(shader->Program); -      } -      else if (shader->Type == GL_FRAGMENT_SHADER) { -         if (shader->Main) -            fragProg = fragment_program(shader->Program); -      } -      else { -         _mesa_problem(ctx, "unexpected shader target in slang_link()"); -      } +   { +      struct gl_shader *vertShader, *fragShader; +      vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER); +      fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER); +      if (vertShader) +         vertProg = vertex_program(vertShader->Program); +      if (fragShader) +         fragProg = fragment_program(fragShader->Program); +      if (!shProg->LinkStatus) +         return;     }  #if FEATURE_es2_glsl | 
