X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fmesa%2Fshader%2Fprogram.c;h=4623ff60de6b5c5a7fe64f11ec44a314b8fa9cbb;hb=4c5879ff3185e03b3baf0ed2765e06a951b35e9e;hp=9f9d5955eaf5faccc0456c9648a3b46f92d64c83;hpb=bbd287103dad776d8a45c87c4e51fbc26d9b80d5;p=mesa.git diff --git a/src/mesa/shader/program.c b/src/mesa/shader/program.c index 9f9d5955eaf..4623ff60de6 100644 --- a/src/mesa/shader/program.c +++ b/src/mesa/shader/program.c @@ -33,6 +33,7 @@ #include "main/context.h" #include "main/hash.h" #include "program.h" +#include "prog_cache.h" #include "prog_parameter.h" #include "prog_instruction.h" @@ -52,12 +53,25 @@ _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)); + ctx->Program.ErrorPos = -1; ctx->Program.ErrorString = _mesa_strdup(""); #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program ctx->VertexProgram.Enabled = GL_FALSE; +#if FEATURE_es2_glsl + ctx->VertexProgram.PointSizeEnabled = GL_TRUE; +#else ctx->VertexProgram.PointSizeEnabled = GL_FALSE; +#endif ctx->VertexProgram.TwoSideEnabled = GL_FALSE; _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, ctx->Shared->DefaultVertexProgram); @@ -66,6 +80,7 @@ _mesa_init_program(GLcontext *ctx) ctx->VertexProgram.TrackMatrix[i] = GL_NONE; ctx->VertexProgram.TrackMatrixTransform[i] = GL_IDENTITY_NV; } + ctx->VertexProgram.Cache = _mesa_new_program_cache(); #endif #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program @@ -73,8 +88,10 @@ _mesa_init_program(GLcontext *ctx) _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, ctx->Shared->DefaultFragmentProgram); assert(ctx->FragmentProgram.Current); + ctx->FragmentProgram.Cache = _mesa_new_program_cache(); #endif + /* XXX probably move this stuff */ #if FEATURE_ATI_fragment_shader ctx->ATIFragmentShader.Enabled = GL_FALSE; @@ -93,9 +110,11 @@ _mesa_free_program_data(GLcontext *ctx) { #if FEATURE_NV_vertex_program || FEATURE_ARB_vertex_program _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, NULL); + _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache); #endif #if FEATURE_NV_fragment_program || FEATURE_ARB_fragment_program _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, NULL); + _mesa_delete_program_cache(ctx, ctx->FragmentProgram.Cache); #endif /* XXX probably move this stuff */ #if FEATURE_ATI_fragment_shader @@ -277,6 +296,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; @@ -362,7 +382,11 @@ _mesa_reference_program(GLcontext *ctx, assert(ptr); if (*ptr && prog) { /* sanity check */ - ASSERT((*ptr)->Target == prog->Target); + if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB) + ASSERT(prog->Target == GL_VERTEX_PROGRAM_ARB); + else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB) + ASSERT(prog->Target == GL_FRAGMENT_PROGRAM_ARB || + prog->Target == GL_FRAGMENT_PROGRAM_NV); } if (*ptr == prog) { return; /* no change */ @@ -507,7 +531,7 @@ _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count) for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (inst->BranchTarget > 0) { - if (inst->BranchTarget >= start) { + if ((GLuint)inst->BranchTarget >= start) { inst->BranchTarget += count; } } @@ -540,7 +564,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. @@ -557,7 +580,7 @@ _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count) for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (inst->BranchTarget > 0) { - if (inst->BranchTarget >= start) { + if (inst->BranchTarget > start) { inst->BranchTarget -= count; } } @@ -677,17 +700,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 " @@ -696,16 +749,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; @@ -766,3 +820,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 + } + + } +}