diff options
Diffstat (limited to 'src/mesa/shader/program.c')
-rw-r--r-- | src/mesa/shader/program.c | 124 |
1 files changed, 115 insertions, 9 deletions
diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index d114828ec6..963478fccd 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -53,6 +53,21 @@ _mesa_init_program(GLcontext *ctx) { GLuint i; + /* + * If this assertion fails, we need to increase the field + * size for register indexes. + */ + ASSERT(ctx->Const.VertexProgram.MaxUniformComponents / 4 + <= (1 << INST_INDEX_BITS)); + ASSERT(ctx->Const.FragmentProgram.MaxUniformComponents / 4 + <= (1 << INST_INDEX_BITS)); + + /* If this fails, increase prog_instruction::TexSrcUnit size */ + ASSERT(MAX_TEXTURE_UNITS < (1 << 5)); + + /* If this fails, increase prog_instruction::TexSrcTarget size */ + ASSERT(NUM_TEXTURE_TARGETS < (1 << 3)); + ctx->Program.ErrorPos = -1; ctx->Program.ErrorString = _mesa_strdup(""); @@ -287,6 +302,7 @@ _mesa_new_program(GLcontext *ctx, GLenum target, GLuint id) struct gl_program *prog; switch (target) { case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */ + case GL_VERTEX_STATE_PROGRAM_NV: prog = _mesa_init_vertex_program(ctx, CALLOC_STRUCT(gl_vertex_program), target, id ); break; @@ -554,7 +570,6 @@ _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) return GL_TRUE; } - /** * Delete 'count' instructions at 'start' in the given program. * Adjust branch targets accordingly. @@ -691,17 +706,47 @@ _mesa_combine_programs(GLcontext *ctx, if (newProg->Target == GL_FRAGMENT_PROGRAM_ARB) { struct gl_fragment_program *fprogA, *fprogB, *newFprog; + GLbitfield progB_inputsRead = progB->InputsRead; + GLint progB_colorFile, progB_colorIndex; + fprogA = (struct gl_fragment_program *) progA; fprogB = (struct gl_fragment_program *) progB; newFprog = (struct gl_fragment_program *) newProg; newFprog->UsesKill = fprogA->UsesKill || fprogB->UsesKill; + /* We'll do a search and replace for instances + * of progB_colorFile/progB_colorIndex below... + */ + progB_colorFile = PROGRAM_INPUT; + progB_colorIndex = FRAG_ATTRIB_COL0; + + /* + * The fragment program may get color from a state var rather than + * a fragment input (vertex output) if it's constant. + * See the texenvprogram.c code. + * So, search the program's parameter list now to see if the program + * gets color from a state var instead of a conventional fragment + * input register. + */ + for (i = 0; i < progB->Parameters->NumParameters; i++) { + struct gl_program_parameter *p = &progB->Parameters->Parameters[i]; + if (p->Type == PROGRAM_STATE_VAR && + p->StateIndexes[0] == STATE_INTERNAL && + p->StateIndexes[1] == STATE_CURRENT_ATTRIB && + p->StateIndexes[2] == VERT_ATTRIB_COLOR0) { + progB_inputsRead |= FRAG_BIT_COL0; + progB_colorFile = PROGRAM_STATE_VAR; + progB_colorIndex = i; + break; + } + } + /* Connect color outputs of fprogA to color inputs of fprogB, via a * new temporary register. */ - if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) && - (progB->InputsRead & (1 << FRAG_ATTRIB_COL0))) { + if ((progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) && + (progB_inputsRead & FRAG_BIT_COL0)) { GLint tempReg = _mesa_find_free_register(newProg, PROGRAM_TEMPORARY); if (tempReg < 0) { _mesa_problem(ctx, "No free temp regs found in " @@ -710,16 +755,17 @@ _mesa_combine_programs(GLcontext *ctx, } /* replace writes to result.color[0] with tempReg */ replace_registers(newInst, lenA, - PROGRAM_OUTPUT, FRAG_RESULT_COLR, + PROGRAM_OUTPUT, FRAG_RESULT_COLOR, PROGRAM_TEMPORARY, tempReg); - /* replace reads from input.color[0] with tempReg */ + /* replace reads from the input color with tempReg */ replace_registers(newInst + lenA, lenB, - PROGRAM_INPUT, FRAG_ATTRIB_COL0, - PROGRAM_TEMPORARY, tempReg); + progB_colorFile, progB_colorIndex, /* search for */ + PROGRAM_TEMPORARY, tempReg /* replace with */ ); } - inputsB = progB->InputsRead; - if (progA->OutputsWritten & (1 << FRAG_RESULT_COLR)) { + /* compute combined program's InputsRead */ + inputsB = progB_inputsRead; + if (progA->OutputsWritten & (1 << FRAG_RESULT_COLOR)) { inputsB &= ~(1 << FRAG_ATTRIB_COL0); } newProg->InputsRead = progA->InputsRead | inputsB; @@ -780,3 +826,63 @@ _mesa_find_free_register(const struct gl_program *prog, GLuint regFile) return -1; } + + + +/** + * "Post-process" a GPU program. This is intended to be used for debugging. + * Example actions include no-op'ing instructions or changing instruction + * behaviour. + */ +void +_mesa_postprocess_program(GLcontext *ctx, struct gl_program *prog) +{ + static const GLfloat white[4] = { 0.5, 0.5, 0.5, 0.5 }; + GLuint i; + GLuint whiteSwizzle; + GLint whiteIndex = _mesa_add_unnamed_constant(prog->Parameters, + white, 4, &whiteSwizzle); + + (void) whiteIndex; + + for (i = 0; i < prog->NumInstructions; i++) { + struct prog_instruction *inst = prog->Instructions + i; + const GLuint n = _mesa_num_inst_src_regs(inst->Opcode); + + (void) n; + + if (_mesa_is_tex_instruction(inst->Opcode)) { +#if 0 + /* replace TEX/TXP/TXB with MOV */ + inst->Opcode = OPCODE_MOV; + inst->DstReg.WriteMask = WRITEMASK_XYZW; + inst->SrcReg[0].Swizzle = SWIZZLE_XYZW; + inst->SrcReg[0].Negate = NEGATE_NONE; +#endif + +#if 0 + /* disable shadow texture mode */ + inst->TexShadow = 0; +#endif + } + + if (inst->Opcode == OPCODE_TXP) { +#if 0 + inst->Opcode = OPCODE_MOV; + inst->DstReg.WriteMask = WRITEMASK_XYZW; + inst->SrcReg[0].File = PROGRAM_CONSTANT; + inst->SrcReg[0].Index = whiteIndex; + inst->SrcReg[0].Swizzle = SWIZZLE_XYZW; + inst->SrcReg[0].Negate = NEGATE_NONE; +#endif +#if 0 + inst->TexShadow = 0; +#endif +#if 0 + inst->Opcode = OPCODE_TEX; + inst->TexShadow = 0; +#endif + } + + } +} |