diff options
Diffstat (limited to 'src/mesa/shader')
-rw-r--r-- | src/mesa/shader/arbprogparse.c | 11 | ||||
-rw-r--r-- | src/mesa/shader/prog_execute.c | 8 | ||||
-rw-r--r-- | src/mesa/shader/prog_instruction.c | 6 | ||||
-rw-r--r-- | src/mesa/shader/prog_optimize.c | 6 | ||||
-rw-r--r-- | src/mesa/shader/prog_parameter.c | 19 | ||||
-rw-r--r-- | src/mesa/shader/prog_statevars.c | 136 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_builtin.c | 24 | ||||
-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 | 5 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_emit.c | 7 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_link.c | 141 | ||||
-rw-r--r-- | src/mesa/shader/slang/slang_typeinfo.c | 1 |
13 files changed, 267 insertions, 117 deletions
diff --git a/src/mesa/shader/arbprogparse.c b/src/mesa/shader/arbprogparse.c index a4d0fc3efc..35253daa2e 100644 --- a/src/mesa/shader/arbprogparse.c +++ b/src/mesa/shader/arbprogparse.c @@ -1840,7 +1840,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst, if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_length++; - Program->Base.NumParameters++; } } else { @@ -1849,7 +1848,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst, if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_length++; - Program->Base.NumParameters++; } break; @@ -1860,7 +1858,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst, if (param_var->param_binding_begin == ~0U) param_var->param_binding_begin = idx; param_var->param_binding_length++; - Program->Base.NumParameters++; /* Check if there is more: 0 -> we're done, else its an integer */ if (**inst) { @@ -1896,7 +1893,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst, idx = _mesa_add_state_reference(Program->Base.Parameters, state_tokens); param_var->param_binding_length++; - Program->Base.NumParameters++; } } else { @@ -1918,7 +1914,6 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst, * instruction register type appropriately. */ param_var->param_binding_length++; - Program->Base.NumParameters++; break; default: @@ -1927,12 +1922,14 @@ parse_param_elements (GLcontext * ctx, const GLubyte ** inst, return 1; } + Program->Base.NumParameters = Program->Base.Parameters->NumParameters; + /* Make sure we haven't blown past our parameter limits */ if (((Program->Base.Target == GL_VERTEX_PROGRAM_ARB) && - (Program->Base.NumParameters >= + (Program->Base.NumParameters > ctx->Const.VertexProgram.MaxLocalParams)) || ((Program->Base.Target == GL_FRAGMENT_PROGRAM_ARB) - && (Program->Base.NumParameters >= + && (Program->Base.NumParameters > ctx->Const.FragmentProgram.MaxLocalParams))) { program_error(ctx, Program->Position, "Too many parameter variables"); return 1; diff --git a/src/mesa/shader/prog_execute.c b/src/mesa/shader/prog_execute.c index a60cda674b..bdac1d4f8a 100644 --- a/src/mesa/shader/prog_execute.c +++ b/src/mesa/shader/prog_execute.c @@ -836,7 +836,7 @@ _mesa_execute_program(GLcontext * ctx, * result.z = result.x * APPX(result.y) * We do what the ARB extension says. */ - q[2] = (GLfloat) pow(2.0, t[0]); + q[2] = (GLfloat) _mesa_pow(2.0, t[0]); } q[1] = t[0] - floor_t0; q[3] = 1.0F; @@ -949,7 +949,7 @@ _mesa_execute_program(GLcontext * ctx, if (a[1] == 0.0 && a[3] == 0.0) result[2] = 1.0; else - result[2] = EXPF(a[3] * LOGF(a[1])); + result[2] = (GLfloat) _mesa_pow(a[1], a[3]); } else { result[2] = 0.0; @@ -1540,8 +1540,8 @@ _mesa_execute_program(GLcontext * ctx, case OPCODE_TXB: /* GL_ARB_fragment_program only */ /* Texel lookup with LOD bias */ { - const struct gl_texture_unit *texUnit - = &ctx->Texture.Unit[inst->TexSrcUnit]; + const GLuint unit = machine->Samplers[inst->TexSrcUnit]; + const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; GLfloat texcoord[4], color[4], lodBias; fetch_vector4(&inst->SrcReg[0], machine, texcoord); diff --git a/src/mesa/shader/prog_instruction.c b/src/mesa/shader/prog_instruction.c index 6a21152c60..ca7565c091 100644 --- a/src/mesa/shader/prog_instruction.c +++ b/src/mesa/shader/prog_instruction.c @@ -291,7 +291,9 @@ _mesa_is_tex_instruction(gl_inst_opcode opcode) const char * _mesa_opcode_string(gl_inst_opcode opcode) { - ASSERT(opcode < MAX_OPCODE); - return InstInfo[opcode].Name; + if (opcode < MAX_OPCODE) + return InstInfo[opcode].Name; + else + return "OP?"; } diff --git a/src/mesa/shader/prog_optimize.c b/src/mesa/shader/prog_optimize.c index 458a69f70b..5f35dbf128 100644 --- a/src/mesa/shader/prog_optimize.c +++ b/src/mesa/shader/prog_optimize.c @@ -803,11 +803,11 @@ _mesa_optimize_program(GLcontext *ctx, struct gl_program *program) if (1) _mesa_remove_dead_code(program); - if (0) /* not test much yet */ + if (0) /* not tested much yet */ _mesa_remove_extra_moves(program); - if (1) + if (0) _mesa_consolidate_registers(program); - else /*NEW*/ + else _mesa_reallocate_registers(program); } diff --git a/src/mesa/shader/prog_parameter.c b/src/mesa/shader/prog_parameter.c index 66edae9001..e9ed3985ee 100644 --- a/src/mesa/shader/prog_parameter.c +++ b/src/mesa/shader/prog_parameter.c @@ -178,15 +178,20 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList, const char *name, const GLfloat values[4], GLuint size) { -#if 0 /* disable this for now -- we need to save the name! */ + /* first check if this is a duplicate constant */ GLint pos; - GLuint swizzle; - ASSERT(size == 4); /* XXX future feature */ - /* check if we already have this constant */ - if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { - return pos; + for (pos = 0; pos < paramList->NumParameters; pos++) { + const GLfloat *pvals = paramList->ParameterValues[pos]; + if (pvals[0] == values[0] && + pvals[1] == values[1] && + pvals[2] == values[2] && + pvals[3] == values[3] && + _mesa_strcmp(paramList->Parameters[pos].Name, name) == 0) { + /* Same name and value is already in the param list - reuse it */ + return pos; + } } -#endif + /* not found, add new parameter */ return _mesa_add_parameter(paramList, PROGRAM_CONSTANT, name, size, GL_NONE, values, NULL, 0x0); } diff --git a/src/mesa/shader/prog_statevars.c b/src/mesa/shader/prog_statevars.c index aeb7cf6de2..37a3f1fc8c 100644 --- a/src/mesa/shader/prog_statevars.c +++ b/src/mesa/shader/prog_statevars.c @@ -112,7 +112,7 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], value[3] = ctx->Light.Light[ln].SpotExponent; return; case STATE_SPOT_DIRECTION: - COPY_3V(value, ctx->Light.Light[ln].EyeDirection); + COPY_3V(value, ctx->Light.Light[ln].SpotDirection); value[3] = ctx->Light.Light[ln]._CosCutoff; return; case STATE_SPOT_CUTOFF: @@ -359,10 +359,10 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->FragmentProgram.Parameters[idx]); - break; + return; case STATE_LOCAL: COPY_4V(value, ctx->FragmentProgram.Current->Base.LocalParams[idx]); - break; + return; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; @@ -378,10 +378,10 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], switch (state[1]) { case STATE_ENV: COPY_4V(value, ctx->VertexProgram.Parameters[idx]); - break; + return; case STATE_LOCAL: COPY_4V(value, ctx->VertexProgram.Current->Base.LocalParams[idx]); - break; + return; default: _mesa_problem(ctx, "Bad state switch in _mesa_fetch_state()"); return; @@ -395,11 +395,12 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], case STATE_INTERNAL: switch (state[1]) { - case STATE_CURRENT_ATTRIB: { - const GLuint idx = (GLuint) state[2]; - COPY_4V(value, ctx->Current.Attrib[idx]); + case STATE_CURRENT_ATTRIB: + { + const GLuint idx = (GLuint) state[2]; + COPY_4V(value, ctx->Current.Attrib[idx]); + } return; - } case STATE_NORMAL_SCALE: ASSIGN_4V(value, @@ -408,19 +409,25 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], ctx->_ModelViewInvScale, 1); return; + case STATE_TEXRECT_SCALE: + /* Value = { 1/texWidth, 1/texHeight, 0, 1 }. + * Used to convert unnormalized texcoords to normalized texcoords. + */ { const int unit = (int) state[2]; const struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; if (texObj) { struct gl_texture_image *texImage = texObj->Image[0][0]; - ASSIGN_4V(value, (GLfloat) (1.0 / texImage->Width), - (GLfloat)(1.0 / texImage->Height), + ASSIGN_4V(value, + (GLfloat) (1.0 / texImage->Width), + (GLfloat) (1.0 / texImage->Height), 0.0f, 1.0f); } } return; + case STATE_FOG_PARAMS_OPTIMIZED: /* for simpler per-vertex/pixel fog calcs. POW (for EXP/EXP2 fog) * might be more expensive than EX2 on some hw, plus it needs @@ -437,62 +444,69 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], value[3] = (GLfloat)(ctx->Fog.Density * ONE_DIV_SQRT_LN2); return; - case STATE_LIGHT_SPOT_DIR_NORMALIZED: { - /* here, state[2] is the light number */ - /* pre-normalize spot dir */ - const GLuint ln = (GLuint) state[2]; - COPY_3V(value, ctx->Light.Light[ln]._NormDirection); - value[3] = ctx->Light.Light[ln]._CosCutoff; + case STATE_LIGHT_SPOT_DIR_NORMALIZED: + { + /* here, state[2] is the light number */ + /* pre-normalize spot dir */ + const GLuint ln = (GLuint) state[2]; + COPY_3V(value, ctx->Light.Light[ln]._NormSpotDirection); + value[3] = ctx->Light.Light[ln]._CosCutoff; + } return; - } - case STATE_LIGHT_POSITION: { - const GLuint ln = (GLuint) state[2]; - COPY_4V(value, ctx->Light.Light[ln]._Position); + case STATE_LIGHT_POSITION: + { + const GLuint ln = (GLuint) state[2]; + COPY_4V(value, ctx->Light.Light[ln]._Position); + } return; - } - case STATE_LIGHT_POSITION_NORMALIZED: { - const GLuint ln = (GLuint) state[2]; - COPY_4V(value, ctx->Light.Light[ln]._Position); - NORMALIZE_3FV( value ); + case STATE_LIGHT_POSITION_NORMALIZED: + { + const GLuint ln = (GLuint) state[2]; + COPY_4V(value, ctx->Light.Light[ln]._Position); + NORMALIZE_3FV( value ); + } return; - } - case STATE_LIGHT_HALF_VECTOR: { - const GLuint ln = (GLuint) state[2]; - GLfloat p[3]; - /* Compute infinite half angle vector: - * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) - * light.EyePosition.w should be 0 for infinite lights. - */ - COPY_3V(p, ctx->Light.Light[ln]._Position); - NORMALIZE_3FV(p); - ADD_3V(value, p, ctx->_EyeZDir); - NORMALIZE_3FV(value); - value[3] = 1.0; + case STATE_LIGHT_HALF_VECTOR: + { + const GLuint ln = (GLuint) state[2]; + GLfloat p[3]; + /* Compute infinite half angle vector: + * halfVector = normalize(normalize(lightPos) + (0, 0, 1)) + * light.EyePosition.w should be 0 for infinite lights. + */ + COPY_3V(p, ctx->Light.Light[ln]._Position); + NORMALIZE_3FV(p); + ADD_3V(value, p, ctx->_EyeZDir); + NORMALIZE_3FV(value); + value[3] = 1.0; + } return; - } - case STATE_PT_SCALE: value[0] = ctx->Pixel.RedScale; value[1] = ctx->Pixel.GreenScale; value[2] = ctx->Pixel.BlueScale; value[3] = ctx->Pixel.AlphaScale; - break; + return; + case STATE_PT_BIAS: value[0] = ctx->Pixel.RedBias; value[1] = ctx->Pixel.GreenBias; value[2] = ctx->Pixel.BlueBias; value[3] = ctx->Pixel.AlphaBias; - break; + return; + case STATE_PCM_SCALE: COPY_4V(value, ctx->Pixel.PostColorMatrixScale); - break; + return; + case STATE_PCM_BIAS: COPY_4V(value, ctx->Pixel.PostColorMatrixBias); - break; + return; + case STATE_SHADOW_AMBIENT: { const int unit = (int) state[2]; @@ -506,6 +520,7 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], } } return; + case STATE_FB_SIZE: value[0] = (GLfloat) (ctx->DrawBuffer->Width - 1); value[1] = (GLfloat) (ctx->DrawBuffer->Height - 1); @@ -522,7 +537,8 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], value[2] = 0.0; value[3] = 0.0; } - break; + return; + case STATE_ROT_MATRIX_1: { const int unit = (int) state[2]; @@ -532,14 +548,14 @@ _mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], value[2] = 0.0; value[3] = 0.0; } - break; + return; - /* XXX: make sure new tokens added here are also handled in the - * _mesa_program_state_flags() switch, below. - */ + /* XXX: make sure new tokens added here are also handled in the + * _mesa_program_state_flags() switch, below. + */ default: - /* unknown state indexes are silently ignored - * should be handled by the driver. + /* Unknown state indexes are silently ignored here. + * Drivers may do something special. */ return; } @@ -760,28 +776,28 @@ append_token(char *dst, gl_state_index k) append(dst, ".spot.cutoff"); break; case STATE_TEXGEN_EYE_S: - append(dst, "eye.s"); + append(dst, ".eye.s"); break; case STATE_TEXGEN_EYE_T: - append(dst, "eye.t"); + append(dst, ".eye.t"); break; case STATE_TEXGEN_EYE_R: - append(dst, "eye.r"); + append(dst, ".eye.r"); break; case STATE_TEXGEN_EYE_Q: - append(dst, "eye.q"); + append(dst, ".eye.q"); break; case STATE_TEXGEN_OBJECT_S: - append(dst, "object.s"); + append(dst, ".object.s"); break; case STATE_TEXGEN_OBJECT_T: - append(dst, "object.t"); + append(dst, ".object.t"); break; case STATE_TEXGEN_OBJECT_R: - append(dst, "object.r"); + append(dst, ".object.r"); break; case STATE_TEXGEN_OBJECT_Q: - append(dst, "object.q"); + append(dst, ".object.q"); break; case STATE_TEXENV_COLOR: append(dst, "texenv"); diff --git a/src/mesa/shader/slang/slang_builtin.c b/src/mesa/shader/slang/slang_builtin.c index 9858a0f7fd..83e76b77db 100644 --- a/src/mesa/shader/slang/slang_builtin.c +++ b/src/mesa/shader/slang/slang_builtin.c @@ -457,28 +457,36 @@ emit_statevars(const char *name, int array_len, tokens[0] = STATE_TEXENV_COLOR; } else if (strcmp(name, "gl_EyePlaneS") == 0) { - tokens[0] = STATE_TEXGEN_EYE_S; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_EYE_S; } else if (strcmp(name, "gl_EyePlaneT") == 0) { - tokens[0] = STATE_TEXGEN_EYE_T; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_EYE_T; } else if (strcmp(name, "gl_EyePlaneR") == 0) { - tokens[0] = STATE_TEXGEN_EYE_R; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_EYE_R; } else if (strcmp(name, "gl_EyePlaneQ") == 0) { - tokens[0] = STATE_TEXGEN_EYE_Q; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_EYE_Q; } else if (strcmp(name, "gl_ObjectPlaneS") == 0) { - tokens[0] = STATE_TEXGEN_OBJECT_S; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_OBJECT_S; } else if (strcmp(name, "gl_ObjectPlaneT") == 0) { - tokens[0] = STATE_TEXGEN_OBJECT_T; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_OBJECT_T; } else if (strcmp(name, "gl_ObjectPlaneR") == 0) { - tokens[0] = STATE_TEXGEN_OBJECT_R; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_OBJECT_R; } else if (strcmp(name, "gl_ObjectPlaneQ") == 0) { - tokens[0] = STATE_TEXGEN_OBJECT_Q; + tokens[0] = STATE_TEXGEN; + tokens[2] = STATE_TEXGEN_OBJECT_Q; } else { return -1; /* invalid array name */ 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..ba2fc4f85c 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); @@ -2799,7 +2801,8 @@ _slang_compile(GLcontext *ctx, struct gl_shader *shader) shader->CompileStatus = success; if (success) { - if (shader->Pragmas.Optimize) { + if (shader->Pragmas.Optimize && + (ctx->Shader.Flags & GLSL_NO_OPT) == 0) { _mesa_optimize_program(ctx, shader->Program); } } 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..1fdf4db054 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -534,6 +534,111 @@ _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; + } + } + + if (totalLen == 0) + return NULL; + + 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); + + if (shader) { + _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: * @@ -550,13 +655,16 @@ _slang_link(GLcontext *ctx, GLhandleARB programObj, struct gl_shader_program *shProg) { - const struct gl_vertex_program *vertProg; - const struct gl_fragment_program *fragProg; + const struct gl_vertex_program *vertProg = NULL; + const struct gl_fragment_program *fragProg = NULL; GLuint numSamplers = 0; GLuint i; _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 +676,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 diff --git a/src/mesa/shader/slang/slang_typeinfo.c b/src/mesa/shader/slang/slang_typeinfo.c index 1ef43f58c0..4a48bc8b8e 100644 --- a/src/mesa/shader/slang/slang_typeinfo.c +++ b/src/mesa/shader/slang/slang_typeinfo.c @@ -790,6 +790,7 @@ _slang_typeof_operation(slang_operation * op, return GL_FALSE; } ti->can_be_referenced = _ti.can_be_referenced; + ti->array_len = field->array_len; } else { GLuint rows; |