diff options
Diffstat (limited to 'src/mesa/shader/program.c')
-rw-r--r-- | src/mesa/shader/program.c | 272 |
1 files changed, 191 insertions, 81 deletions
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index ddfad47b89..1cf3547969 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -203,6 +203,7 @@ _mesa_init_program_struct( GLcontext *ctx, struct gl_program *prog, { (void) ctx; if (prog) { + _mesa_bzero(prog, sizeof(*prog)); prog->Id = id; prog->Target = target; prog->Resident = GL_TRUE; @@ -304,6 +305,10 @@ _mesa_delete_program(GLcontext *ctx, struct gl_program *prog) _mesa_free_parameter_list(prog->Parameters); } + if (prog->Varying) { + _mesa_free_parameter_list(prog->Varying); + } + /* XXX this is a little ugly */ if (prog->Target == GL_VERTEX_PROGRAM_ARB) { struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; @@ -364,13 +369,14 @@ _mesa_free_parameter_list(struct gl_program_parameter_list *paramList) * Add a new parameter to a parameter list. * \param paramList the list to add the parameter to * \param name the parameter name, will be duplicated/copied! - * \param values initial parameter value, 4 GLfloats + * \param values initial parameter value, up to 4 GLfloats + * \param size number of elements in 'values' vector (1..4) * \param type type of parameter, such as * \return index of new parameter in the list, or -1 if error (out of mem) */ static GLint add_parameter(struct gl_program_parameter_list *paramList, - const char *name, const GLfloat values[4], + const char *name, const GLfloat values[4], GLuint size, enum register_file type) { const GLuint n = paramList->NumParameters; @@ -425,7 +431,7 @@ GLint _mesa_add_named_parameter(struct gl_program_parameter_list *paramList, const char *name, const GLfloat values[4]) { - return add_parameter(paramList, name, values, PROGRAM_NAMED_PARAM); + return add_parameter(paramList, name, values, 4, PROGRAM_NAMED_PARAM); } @@ -445,14 +451,16 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList, GLuint size) { #if 0 /* disable this for now -- we need to save the name! */ - GLuint pos, swizzle; + 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; } #endif - return add_parameter(paramList, name, values, PROGRAM_CONSTANT); + size = 4; /** XXX fix */ + return add_parameter(paramList, name, values, size, PROGRAM_CONSTANT); } @@ -463,22 +471,87 @@ _mesa_add_named_constant(struct gl_program_parameter_list *paramList, * * \param paramList the parameter list * \param values four float values + * \param swizzleOut returns swizzle mask for accessing the constant * \return index/position of the new parameter in the parameter list. */ GLint _mesa_add_unnamed_constant(struct gl_program_parameter_list *paramList, - const GLfloat values[4], GLuint size) + const GLfloat values[4], GLuint size, + GLuint *swizzleOut) { - GLuint pos, swizzle; - ASSERT(size == 4); /* XXX future feature */ + GLint pos; + GLuint swizzle; + ASSERT(size >= 1); + ASSERT(size <= 4); + size = 4; /* XXX temporary */ /* check if we already have this constant */ - if (_mesa_lookup_parameter_constant(paramList, values, 4, &pos, &swizzle)) { + if (_mesa_lookup_parameter_constant(paramList, values, + size, &pos, &swizzle)) { return pos; } - return add_parameter(paramList, NULL, values, PROGRAM_CONSTANT); + return add_parameter(paramList, NULL, values, size, PROGRAM_CONSTANT); } +GLint +_mesa_add_uniform(struct gl_program_parameter_list *paramList, + const char *name, GLuint size) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_UNIFORM) { + /* already in list */ + return i; + } + else { + assert(size == 4); + i = add_parameter(paramList, name, NULL, size, PROGRAM_UNIFORM); + return i; + } +} + + +GLint +_mesa_add_varying(struct gl_program_parameter_list *paramList, + const char *name, GLuint size) +{ + GLint i = _mesa_lookup_parameter_index(paramList, -1, name); + if (i >= 0 && paramList->Parameters[i].Type == PROGRAM_VARYING) { + /* already in list */ + return i; + } + else { + assert(size == 4); + i = add_parameter(paramList, name, NULL, size, PROGRAM_VARYING); + return i; + } +} + + + + +#if 0 /* not used yet */ +/** + * Returns the number of 4-component registers needed to store a piece + * of GL state. For matrices this may be as many as 4 registers, + * everything else needs + * just 1 register. + */ +static GLuint +sizeof_state_reference(const GLint *stateTokens) +{ + if (stateTokens[0] == STATE_MATRIX) { + GLuint rows = stateTokens[4] - stateTokens[3] + 1; + assert(rows >= 1); + assert(rows <= 4); + return rows; + } + else { + return 1; + } +} +#endif + + /** * Add a new state reference to the parameter list. * This will be used when the program contains something like this: @@ -492,18 +565,34 @@ GLint _mesa_add_state_reference(struct gl_program_parameter_list *paramList, const GLint *stateTokens) { - /* XXX we should probably search the current parameter list to see if - * the new state reference is already present. - */ + const GLuint size = 4; /* XXX fix */ + const char *name; GLint index; - const char *name = make_state_string(stateTokens); - index = add_parameter(paramList, name, NULL, PROGRAM_STATE_VAR); + /* Check if the state reference is already in the list */ + for (index = 0; index < paramList->NumParameters; index++) { + GLuint i, match = 0; + for (i = 0; i < 6; i++) { + if (paramList->Parameters[index].StateIndexes[i] == stateTokens[i]) { + match++; + } + else { + break; + } + } + if (match == 6) { + /* this state reference is already in the parameter list */ + return index; + } + } + + name = make_state_string(stateTokens); + index = add_parameter(paramList, name, NULL, size, PROGRAM_STATE_VAR); if (index >= 0) { GLuint i; for (i = 0; i < 6; i++) { paramList->Parameters[index].StateIndexes[i] - = (enum state_index) stateTokens[i]; + = (gl_state_index) stateTokens[i]; } paramList->StateFlags |= make_state_flags(stateTokens); } @@ -523,29 +612,11 @@ GLfloat * _mesa_lookup_parameter_value(const struct gl_program_parameter_list *paramList, GLsizei nameLen, const char *name) { - GLuint i; - - if (!paramList) + GLuint i = _mesa_lookup_parameter_index(paramList, nameLen, name); + if (i < 0) return NULL; - - if (nameLen == -1) { - /* name is null-terminated */ - for (i = 0; i < paramList->NumParameters; i++) { - if (paramList->Parameters[i].Name && - _mesa_strcmp(paramList->Parameters[i].Name, name) == 0) - return paramList->ParameterValues[i]; - } - } - else { - /* name is not null-terminated, use nameLen */ - for (i = 0; i < paramList->NumParameters; i++) { - if (paramList->Parameters[i].Name && - _mesa_strncmp(paramList->Parameters[i].Name, name, nameLen) == 0 - && _mesa_strlen(paramList->Parameters[i].Name) == (size_t)nameLen) - return paramList->ParameterValues[i]; - } - } - return NULL; + else + return paramList->ParameterValues[i]; } @@ -601,7 +672,7 @@ _mesa_lookup_parameter_index(const struct gl_program_parameter_list *paramList, GLboolean _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramList, const GLfloat v[], GLsizei vSize, - GLuint *posOut, GLuint *swizzleOut) + GLint *posOut, GLuint *swizzleOut) { GLuint i; @@ -625,6 +696,8 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramLis if (paramList->ParameterValues[i][shift + j] == v[j]) { matched++; swizzle[j] = shift + j; + ASSERT(swizzle[j] >= SWIZZLE_X); + ASSERT(swizzle[j] <= SWIZZLE_W); } } if (matched == vSize) { @@ -638,6 +711,7 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramLis } } + *posOut = -1; return GL_FALSE; } @@ -650,7 +724,7 @@ _mesa_lookup_parameter_constant(const struct gl_program_parameter_list *paramLis * The program parser will produce the state[] values. */ static void -_mesa_fetch_state(GLcontext *ctx, const enum state_index state[], +_mesa_fetch_state(GLcontext *ctx, const gl_state_index state[], GLfloat *value) { switch (state[0]) { @@ -876,16 +950,16 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[], { /* state[1] = modelview, projection, texture, etc. */ /* state[2] = which texture matrix or program matrix */ - /* state[3] = first column to fetch */ - /* state[4] = last column to fetch */ + /* state[3] = first row to fetch */ + /* state[4] = last row to fetch */ /* state[5] = transpose, inverse or invtrans */ const GLmatrix *matrix; - const enum state_index mat = state[1]; + const gl_state_index mat = state[1]; const GLuint index = (GLuint) state[2]; - const GLuint first = (GLuint) state[3]; - const GLuint last = (GLuint) state[4]; - const enum state_index modifier = state[5]; + const GLuint firstRow = (GLuint) state[3]; + const GLuint lastRow = (GLuint) state[4]; + const gl_state_index modifier = state[5]; const GLfloat *m; GLuint row, i; if (mat == STATE_MODELVIEW) { @@ -920,7 +994,7 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[], } if (modifier == STATE_MATRIX_TRANSPOSE || modifier == STATE_MATRIX_INVTRANS) { - for (i = 0, row = first; row <= last; row++) { + for (i = 0, row = firstRow; row <= lastRow; row++) { value[i++] = m[row * 4 + 0]; value[i++] = m[row * 4 + 1]; value[i++] = m[row * 4 + 2]; @@ -928,7 +1002,7 @@ _mesa_fetch_state(GLcontext *ctx, const enum state_index state[], } } else { - for (i = 0, row = first; row <= last; row++) { + for (i = 0, row = firstRow; row <= lastRow; row++) { value[i++] = m[row + 0]; value[i++] = m[row + 4]; value[i++] = m[row + 8]; @@ -1101,7 +1175,7 @@ append(char *dst, const char *src) static void -append_token(char *dst, enum state_index k) +append_token(char *dst, gl_state_index k) { switch (k) { case STATE_MATERIAL: @@ -1268,17 +1342,17 @@ make_state_string(const GLint state[6]) char tmp[30]; append(str, "state."); - append_token(str, (enum state_index) state[0]); + append_token(str, (gl_state_index) state[0]); switch (state[0]) { case STATE_MATERIAL: append_face(str, state[1]); - append_token(str, (enum state_index) state[2]); + append_token(str, (gl_state_index) state[2]); break; case STATE_LIGHT: append(str, "light"); append_index(str, state[1]); /* light number [i]. */ - append_token(str, (enum state_index) state[2]); /* coefficients */ + append_token(str, (gl_state_index) state[2]); /* coefficients */ break; case STATE_LIGHTMODEL_AMBIENT: append(str, "lightmodel.ambient"); @@ -1294,11 +1368,11 @@ make_state_string(const GLint state[6]) case STATE_LIGHTPROD: append_index(str, state[1]); /* light number [i]. */ append_face(str, state[2]); - append_token(str, (enum state_index) state[3]); + append_token(str, (gl_state_index) state[3]); break; case STATE_TEXGEN: append_index(str, state[1]); /* tex unit [i] */ - append_token(str, (enum state_index) state[2]); /* plane coef */ + append_token(str, (gl_state_index) state[2]); /* plane coef */ break; case STATE_TEXENV_COLOR: append_index(str, state[1]); /* tex unit [i] */ @@ -1318,23 +1392,23 @@ make_state_string(const GLint state[6]) { /* state[1] = modelview, projection, texture, etc. */ /* state[2] = which texture matrix or program matrix */ - /* state[3] = first column to fetch */ - /* state[4] = last column to fetch */ + /* state[3] = first row to fetch */ + /* state[4] = last row to fetch */ /* state[5] = transpose, inverse or invtrans */ - const enum state_index mat = (enum state_index) state[1]; + const gl_state_index mat = (gl_state_index) state[1]; const GLuint index = (GLuint) state[2]; - const GLuint first = (GLuint) state[3]; - const GLuint last = (GLuint) state[4]; - const enum state_index modifier = (enum state_index) state[5]; + const GLuint firstRow = (GLuint) state[3]; + const GLuint lastRow = (GLuint) state[4]; + const gl_state_index modifier = (gl_state_index) state[5]; append_token(str, mat); if (index) append_index(str, index); if (modifier) append_token(str, modifier); - if (first == last) - _mesa_sprintf(tmp, ".row[%d]", first); + if (firstRow == lastRow) + _mesa_sprintf(tmp, ".row[%d]", firstRow); else - _mesa_sprintf(tmp, ".row[%d..%d]", first, last); + _mesa_sprintf(tmp, ".row[%d..%d]", firstRow, lastRow); append(str, tmp); } break; @@ -1344,7 +1418,7 @@ make_state_string(const GLint state[6]) case STATE_VERTEX_PROGRAM: /* state[1] = {STATE_ENV, STATE_LOCAL} */ /* state[2] = parameter index */ - append_token(str, (enum state_index) state[1]); + append_token(str, (gl_state_index) state[1]); append_index(str, state[2]); break; case STATE_INTERNAL: @@ -1456,7 +1530,7 @@ _mesa_realloc_instructions(struct prog_instruction *oldInst, */ struct instruction_info { - enum prog_opcode Opcode; + gl_inst_opcode Opcode; const char *Name; GLuint NumSrcRegs; }; @@ -1466,14 +1540,15 @@ struct instruction_info * \note Opcode should equal array index! */ static const struct instruction_info InstInfo[MAX_OPCODE] = { + { OPCODE_NOP, "NOP", 0 }, { OPCODE_ABS, "ABS", 1 }, { OPCODE_ADD, "ADD", 2 }, { OPCODE_ARA, "ARA", 1 }, { OPCODE_ARL, "ARL", 1 }, { OPCODE_ARL_NV, "ARL", 1 }, { OPCODE_ARR, "ARL", 1 }, - { OPCODE_BRA, "BRA", 1 }, - { OPCODE_CAL, "CAL", 1 }, + { OPCODE_BRA, "BRA", 0 }, + { OPCODE_CAL, "CAL", 0 }, { OPCODE_CMP, "CMP", 3 }, { OPCODE_COS, "COS", 1 }, { OPCODE_DDX, "DDX", 1 }, @@ -1508,7 +1583,7 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { { OPCODE_PUSHA, "PUSHA", 0 }, { OPCODE_RCC, "RCC", 1 }, { OPCODE_RCP, "RCP", 1 }, - { OPCODE_RET, "RET", 1 }, + { OPCODE_RET, "RET", 0 }, { OPCODE_RFL, "RFL", 1 }, { OPCODE_RSQ, "RSQ", 1 }, { OPCODE_SCS, "SCS", 1 }, @@ -1543,9 +1618,10 @@ static const struct instruction_info InstInfo[MAX_OPCODE] = { * Return the number of src registers for the given instruction/opcode. */ GLuint -_mesa_num_inst_src_regs(enum prog_opcode opcode) +_mesa_num_inst_src_regs(gl_inst_opcode opcode) { ASSERT(opcode == InstInfo[opcode].Opcode); + ASSERT(OPCODE_XPD == InstInfo[OPCODE_XPD].Opcode); return InstInfo[opcode].NumSrcRegs; } @@ -1554,7 +1630,7 @@ _mesa_num_inst_src_regs(enum prog_opcode opcode) * Return string name for given program opcode. */ const char * -_mesa_opcode_string(enum prog_opcode opcode) +_mesa_opcode_string(gl_inst_opcode opcode) { ASSERT(opcode < MAX_OPCODE); return InstInfo[opcode].Name; @@ -1583,12 +1659,16 @@ program_file_string(enum register_file f) return "NAMED"; case PROGRAM_CONSTANT: return "CONST"; + case PROGRAM_UNIFORM: + return "UNIFORM"; + case PROGRAM_VARYING: + return "VARYING"; case PROGRAM_WRITE_ONLY: return "WRITE_ONLY"; case PROGRAM_ADDRESS: return "ADDR"; default: - return "!unkown!"; + return "Unknown program file!"; } } @@ -1685,6 +1765,16 @@ print_src_reg(const struct prog_src_register *srcReg) srcReg->NegateBase, GL_FALSE)); } +static void +print_comment(const struct prog_instruction *inst) +{ + if (inst->Comment) + _mesa_printf("; # %s\n", inst->Comment); + else + _mesa_printf(";\n"); +} + + void _mesa_print_alu_instruction(const struct prog_instruction *inst, const char *opcode_string, @@ -1704,6 +1794,9 @@ _mesa_print_alu_instruction(const struct prog_instruction *inst, inst->DstReg.Index, writemask_string(inst->DstReg.WriteMask)); } + else { + _mesa_printf(" ???"); + } if (numRegs > 0) _mesa_printf(", "); @@ -1714,7 +1807,10 @@ _mesa_print_alu_instruction(const struct prog_instruction *inst, _mesa_printf(", "); } - _mesa_printf(";\n"); + if (inst->Comment) + _mesa_printf(" # %s", inst->Comment); + + print_comment(inst); } @@ -1735,18 +1831,21 @@ _mesa_print_instruction(const struct prog_instruction *inst) swizzle_string(inst->SrcReg[0].Swizzle, inst->SrcReg[0].NegateBase, GL_FALSE)); } - _mesa_printf(";\n"); + if (inst->Comment) + _mesa_printf(" # %s", inst->Comment); + print_comment(inst); break; case OPCODE_SWZ: _mesa_printf("SWZ"); if (inst->SaturateMode == SATURATE_ZERO_ONE) _mesa_printf("_SAT"); print_dst_reg(&inst->DstReg); - _mesa_printf("%s[%d], %s;\n", + _mesa_printf("%s[%d], %s", program_file_string((enum register_file) inst->SrcReg[0].File), inst->SrcReg[0].Index, swizzle_string(inst->SrcReg[0].Swizzle, inst->SrcReg[0].NegateBase, GL_TRUE)); + print_comment(inst); break; case OPCODE_TEX: case OPCODE_TXP: @@ -1768,17 +1867,26 @@ _mesa_print_instruction(const struct prog_instruction *inst) default: ; } - _mesa_printf("\n"); + print_comment(inst); break; case OPCODE_ARL: _mesa_printf("ARL addr.x, "); print_src_reg(&inst->SrcReg[0]); - _mesa_printf(";\n"); + print_comment(inst); + break; + case OPCODE_BRA: + _mesa_printf("BRA %u", inst->BranchTarget); + print_comment(inst); + break; + case OPCODE_CAL: + _mesa_printf("CAL %u", inst->BranchTarget); + print_comment(inst); break; case OPCODE_END: - _mesa_printf("END;\n"); + _mesa_printf("END"); + print_comment(inst); break; - /* XXX may need for other special-case instructions */ + /* XXX may need other special-case instructions */ default: /* typical alu instruction */ _mesa_print_alu_instruction(inst, @@ -1820,7 +1928,7 @@ _mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) _mesa_load_state_parameters(ctx, prog->Parameters); -#if 0 +#if 0 _mesa_printf("Local Params:\n"); for (i = 0; i < MAX_PROGRAM_LOCAL_PARAMS; i++){ const GLfloat *p = prog->LocalParams[i]; @@ -1831,8 +1939,10 @@ _mesa_print_program_parameters(GLcontext *ctx, const struct gl_program *prog) for (i = 0; i < prog->Parameters->NumParameters; i++){ struct gl_program_parameter *param = prog->Parameters->Parameters + i; const GLfloat *v = prog->Parameters->ParameterValues[i]; - _mesa_printf("param[%d] %s = {%.3f, %.3f, %.3f, %.3f};\n", - i, param->Name, v[0], v[1], v[2], v[3]); + _mesa_printf("param[%d] %s %s = {%.3f, %.3f, %.3f, %.3f};\n", + i, + program_file_string(prog->Parameters->Parameters[i].Type), + param->Name, v[0], v[1], v[2], v[3]); } } |