r300: rewrite FOGC and HPOS attribs handling
authorMaciej Cencora <m.cencora@gmail.com>
Sun, 5 Jul 2009 00:32:51 +0000 (02:32 +0200)
committerMaciej Cencora <m.cencora@gmail.com>
Mon, 13 Jul 2009 17:25:59 +0000 (19:25 +0200)
Rewrite vertex and fragment programs so that we don't have to do any hacks on lower level.

src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_emit.c
src/mesa/drivers/dri/r300/r300_fragprog_common.c
src/mesa/drivers/dri/r300/r300_shader.c
src/mesa/drivers/dri/r300/r300_state.c
src/mesa/drivers/dri/r300/r300_swtcl.c
src/mesa/drivers/dri/r300/r300_vertprog.c

index 6f99e490500270f7cd3935f216c534a0d61f1ef6..32104b8158b59341ec9f0f13c4cb132be2df4ed8 100644 (file)
@@ -410,6 +410,8 @@ struct r300_vertex_program {
 
        struct r300_vertex_program_key {
                GLuint FpReads;
+               GLuint FogAttr;
+               GLuint WPosAttr;
        } key;
        
        struct r300_vertex_shader_hw_code {
@@ -425,7 +427,6 @@ struct r300_vertex_program {
 
        int pos_end;
        int num_temporaries;    /* Number of temp vars used by program */
-       int wpos_idx;
        int inputs[VERT_ATTRIB_MAX];
        int outputs[VERT_RESULT_MAX];
 };
@@ -560,6 +561,11 @@ struct r300_fragment_program {
        GLuint optimization;
 
        struct r300_fragment_program *next;
+
+       /* attribute that we are sending the WPOS in */
+       gl_frag_attrib wpos_attr;
+       /* attribute that we are sending the fog coordinate in */
+       gl_frag_attrib fog_attr;
 };
 
 struct r300_fragment_program_cont {
index c3817721dc47566d25d09d375e3ae2e76978b109..707d1284edb171c673fa7da0084f03f13f2e2215 100644 (file)
@@ -116,15 +116,6 @@ GLuint r300VAPOutputCntl1(GLcontext * ctx, GLuint vp_writes, GLuint fp_reads)
                }
        }
 
-       if (fp_reads & FRAG_BIT_WPOS) {
-               ret |= (4 << (3 * first_free_texcoord));
-               ++first_free_texcoord;
-       }
-
-       if (vp_writes & (1 << VERT_RESULT_FOGC) && fp_reads & FRAG_BIT_FOGC) {
-               ret |= 4 << (3 * first_free_texcoord);
-       }
-
        if (first_free_texcoord > 8) {
                fprintf(stderr, "\tout of free texcoords\n");
                _mesa_exit(-1);
index b25cf24007a6b9479f4fc1148d36f22446475e78..e90be9b7f852df18c9b07f434d16b7bbc21111e1 100644 (file)
@@ -69,8 +69,10 @@ static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
 {
        GLuint InputsRead = compiler->fp->Base->InputsRead;
 
-       if (!(InputsRead & FRAG_BIT_WPOS))
+       if (!(InputsRead & FRAG_BIT_WPOS)) {
+               compiler->fp->wpos_attr = FRAG_ATTRIB_MAX;
                return;
+       }
 
        static gl_state_index tokens[STATE_LENGTH] = {
                STATE_INTERNAL, STATE_R300_WINDOW_DIMENSION, 0, 0, 0
@@ -78,10 +80,23 @@ static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
        struct prog_instruction *fpi;
        GLuint window_index;
        int i = 0;
+
+       for (i = FRAG_ATTRIB_TEX0; i <= FRAG_ATTRIB_TEX7; ++i)
+       {
+               if (!(InputsRead & (1 << i))) {
+                       InputsRead &= ~(1 << FRAG_ATTRIB_WPOS);
+                       InputsRead |= 1 << i;
+                       compiler->fp->Base->InputsRead = InputsRead;
+                       compiler->fp->wpos_attr = i;
+                       break;
+               }
+       }
+
        GLuint tempregi = _mesa_find_free_register(compiler->program, PROGRAM_TEMPORARY);
 
        _mesa_insert_instructions(compiler->program, 0, 3);
        fpi = compiler->program->Instructions;
+       i = 0;
 
        /* perspective divide */
        fpi[i].Opcode = OPCODE_RCP;
@@ -92,7 +107,7 @@ static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
        fpi[i].DstReg.CondMask = COND_TR;
 
        fpi[i].SrcReg[0].File = PROGRAM_INPUT;
-       fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
+       fpi[i].SrcReg[0].Index = compiler->fp->wpos_attr;
        fpi[i].SrcReg[0].Swizzle = SWIZZLE_WWWW;
        i++;
 
@@ -104,7 +119,7 @@ static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
        fpi[i].DstReg.CondMask = COND_TR;
 
        fpi[i].SrcReg[0].File = PROGRAM_INPUT;
-       fpi[i].SrcReg[0].Index = FRAG_ATTRIB_WPOS;
+       fpi[i].SrcReg[0].Index = compiler->fp->wpos_attr;
        fpi[i].SrcReg[0].Swizzle = SWIZZLE_XYZW;
 
        fpi[i].SrcReg[1].File = PROGRAM_TEMPORARY;
@@ -147,6 +162,45 @@ static void insert_WPOS_trailer(struct r300_fragment_program_compiler *compiler)
        }
 }
 
+static void rewriteFog(struct r300_fragment_program_compiler *compiler)
+{
+       struct r300_fragment_program *fp = compiler->fp;
+       GLuint InputsRead;
+       int i;
+
+       InputsRead = fp->Base->InputsRead;
+
+       if (!(InputsRead & FRAG_BIT_FOGC)) {
+               fp->fog_attr = FRAG_ATTRIB_MAX;
+               return;
+       }
+
+       for (i = FRAG_ATTRIB_TEX0; i <= FRAG_ATTRIB_TEX7; ++i)
+       {
+               if (!(InputsRead & (1 << i))) {
+                       InputsRead &= ~(1 << FRAG_ATTRIB_FOGC);
+                       InputsRead |= 1 << i;
+                       fp->Base->InputsRead = InputsRead;
+                       fp->fog_attr = i;
+                       break;
+               }
+       }
+
+       {
+               struct prog_instruction *inst;
+
+               inst = compiler->program->Instructions;
+               while (inst->Opcode != OPCODE_END) {
+                       const int src_regs = _mesa_num_inst_src_regs(inst->Opcode);
+                       for (i = 0; i < src_regs; ++i) {
+                               if (inst->SrcReg[i].File == PROGRAM_INPUT && inst->SrcReg[i].Index == FRAG_ATTRIB_FOGC)
+                                       inst->SrcReg[i].Index = fp->fog_attr;
+                       }
+                       ++inst;
+               }
+       }
+}
+
 static GLuint build_dtm(GLuint depthmode)
 {
        switch(depthmode) {
@@ -204,6 +258,8 @@ void r300TranslateFragmentShader(GLcontext *ctx, struct r300_fragment_program *f
 
        insert_WPOS_trailer(&compiler);
 
+       rewriteFog(&compiler);
+
        if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
                struct radeon_program_transformation transformations[] = {
                        { &r500_transform_TEX, &compiler },
index 854eb5d80ae668ce84b66c1beb3ebbd416cc8346..62228a3786e821913fd089f6d7e7c592a50a8899 100644 (file)
@@ -66,8 +66,7 @@ static struct gl_program *r300NewProgram(GLcontext * ctx, GLenum target,
        case GL_VERTEX_STATE_PROGRAM_NV:
        case GL_VERTEX_PROGRAM_ARB:
                vp = CALLOC_STRUCT(r300_vertex_program_cont);
-               return _mesa_init_vertex_program(ctx, &vp->mesa_program,
-                                                target, id);
+               return _mesa_init_vertex_program(ctx, &vp->mesa_program, target, id);
 
        case GL_FRAGMENT_PROGRAM_NV:
        case GL_FRAGMENT_PROGRAM_ARB:
index 0f3198e792d752497c1e679312d9ad660a503ce4..bae2f0f3cb071c8781b5bd1524828dcb789ceeaa 100644 (file)
@@ -1519,29 +1519,6 @@ static void r300SetupRSUnit(GLcontext * ctx)
                ++fp_reg;
        }
 
-       if (InputsRead & FRAG_BIT_WPOS) {
-               r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= R300_RS_SEL_S(0) | R300_RS_SEL_T(1) | R300_RS_SEL_R(2) | R300_RS_SEL_Q(3) | R300_RS_TEX_PTR(rs_tex_count);
-               r300->hw.rr.cmd[R300_RR_INST_0 + tex_ip] |= R300_RS_INST_TEX_ID(tex_ip) | R300_RS_INST_TEX_CN_WRITE | R300_RS_INST_TEX_ADDR(fp_reg);
-               InputsRead &= ~FRAG_BIT_WPOS;
-               rs_tex_count += 4;
-               ++tex_ip;
-               ++fp_reg;
-       }
-
-       if (InputsRead & FRAG_BIT_FOGC) {
-               if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_FOGC, _TNL_ATTRIB_FOG)) {
-                       r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= R300_RS_SEL_S(0) | R300_RS_SEL_T(R300_RS_SEL_K0) | R300_RS_SEL_R(R300_RS_SEL_K0);
-                       r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= R300_RS_SEL_Q(R300_RS_SEL_K1) | R300_RS_TEX_PTR(rs_tex_count);
-                       r300->hw.rr.cmd[R300_RR_INST_0 + tex_ip] |= R300_RS_INST_TEX_ID(tex_ip) | R300_RS_INST_TEX_CN_WRITE | R300_RS_INST_TEX_ADDR(fp_reg);
-                       InputsRead &= ~FRAG_BIT_FOGC;
-                       rs_tex_count += 4;
-                       ++tex_ip;
-                       ++fp_reg;
-               } else {
-                       WARN_ONCE("fragprog wants fogc, vp doesn't provide it\n");
-               }
-       }
-
        /* Setup default color if no color or tex was set */
        if (rs_tex_count == 0 && col_ip == 0) {
                r300->hw.rr.cmd[R300_RR_INST_0] = R300_RS_INST_COL_ID(0) | R300_RS_INST_COL_ADDR(0);
@@ -1640,36 +1617,6 @@ static void r500SetupRSUnit(GLcontext * ctx)
                ++fp_reg;
        }
 
-       if (InputsRead & FRAG_BIT_WPOS) {
-               r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= ((rs_tex_count + 0) << R500_RS_IP_TEX_PTR_S_SHIFT) |
-                       ((rs_tex_count + 1) << R500_RS_IP_TEX_PTR_T_SHIFT) |
-                       ((rs_tex_count + 2) << R500_RS_IP_TEX_PTR_R_SHIFT) |
-                       ((rs_tex_count + 3) << R500_RS_IP_TEX_PTR_Q_SHIFT);
-
-               r300->hw.rr.cmd[R300_RR_INST_0 + tex_ip] |= R500_RS_INST_TEX_ID(tex_ip) | R500_RS_INST_TEX_CN_WRITE | R500_RS_INST_TEX_ADDR(fp_reg);
-               InputsRead &= ~FRAG_BIT_WPOS;
-               rs_tex_count += 4;
-               ++tex_ip;
-               ++fp_reg;
-       }
-
-       if (InputsRead & FRAG_BIT_FOGC) {
-               if (R300_OUTPUTS_WRITTEN_TEST(OutputsWritten, VERT_RESULT_FOGC, _TNL_ATTRIB_FOG)) {
-                       r300->hw.ri.cmd[R300_RI_INTERP_0 + tex_ip] |= (rs_tex_count << R500_RS_IP_TEX_PTR_S_SHIFT) |
-                               (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_T_SHIFT) |
-                               (R500_RS_IP_PTR_K0 << R500_RS_IP_TEX_PTR_R_SHIFT) |
-                               (R500_RS_IP_PTR_K1 << R500_RS_IP_TEX_PTR_Q_SHIFT);
-
-                       r300->hw.rr.cmd[R300_RR_INST_0 + tex_ip] |= R500_RS_INST_TEX_ID(tex_ip) | R500_RS_INST_TEX_CN_WRITE | R500_RS_INST_TEX_ADDR(fp_reg);
-                       InputsRead &= ~FRAG_BIT_FOGC;
-                       rs_tex_count += 4;
-                       ++tex_ip;
-                       ++fp_reg;
-               } else {
-                       WARN_ONCE("fragprog wants fogc, vp doesn't provide it\n");
-               }
-       }
-
        /* Setup default color if no color or tex was set */
        if (rs_tex_count == 0 && col_ip == 0) {
                r300->hw.rr.cmd[R300_RR_INST_0] = R500_RS_INST_COL_ID(0) | R500_RS_INST_COL_ADDR(0);
index db4ccce6f1f9317bfb5fbf6fef8c1c14897e63ea..d73508d36e38874720ae7294d35372127161e67c 100644 (file)
@@ -192,31 +192,23 @@ void r300ChooseSwtclVertexFormat(GLcontext *ctx, GLuint *_InputsRead,  GLuint *_
                }
        }
 
-       /* RS can't put fragment position on the pixel stack, so stuff it in texcoord if needed */
-       if (fp_reads & FRAG_BIT_WPOS) {
-               if (first_free_tex >= ctx->Const.MaxTextureUnits) {
-                       fprintf(stderr, "\tout of free texcoords to write w pos\n");
-                       _mesa_exit(-1);
-               }
+       if (rmesa->selected_fp->wpos_attr != FRAG_ATTRIB_MAX) {
+               int tex_id = rmesa->selected_fp->wpos_attr - FRAG_ATTRIB_TEX0;
 
-               InputsRead |= 1 << (VERT_ATTRIB_TEX0 + first_free_tex);
-               OutputsWritten |= 1 << (VERT_RESULT_TEX0 + first_free_tex);
-               EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F );
-               ADD_ATTR(VERT_ATTRIB_POS, R300_DATA_TYPE_FLOAT_4, SWTCL_OVM_TEX(first_free_tex), SWIZZLE_XYZW, MASK_XYZW, 0);
-               ++first_free_tex;
+               VB->AttribPtr[VERT_ATTRIB_TEX0 + tex_id] = VB->AttribPtr[VERT_ATTRIB_POS];
+               RENDERINPUTS_SET(tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 + tex_id);
        }
 
-       if (fp_reads & FRAG_BIT_FOGC) {
-               if (first_free_tex >= ctx->Const.MaxTextureUnits) {
-                       fprintf(stderr, "\tout of free texcoords to write fog coordinate\n");
-                       _mesa_exit(-1);
-               }
+       if (rmesa->selected_fp->fog_attr != FRAG_ATTRIB_MAX) {
+               int tex_id = rmesa->selected_fp->fog_attr - FRAG_ATTRIB_TEX0;
 
-               InputsRead |= 1 << VERT_ATTRIB_FOG;
-               OutputsWritten |= 1 << VERT_RESULT_FOGC;
-               GLuint swiz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO);
-               EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1F );
-               ADD_ATTR(VERT_ATTRIB_FOG, R300_DATA_TYPE_FLOAT_1, SWTCL_OVM_TEX(first_free_tex), swiz, MASK_XYZW, 0);
+               VB->AttribPtr[VERT_ATTRIB_TEX0 + tex_id] = VB->AttribPtr[VERT_ATTRIB_FOG];
+               RENDERINPUTS_SET(tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 + tex_id);
+       }
+
+       if (first_free_tex >= ctx->Const.MaxTextureUnits) {
+               fprintf(stderr, "\tout of free texcoords to write fog coordinate\n");
+               _mesa_exit(-1);
        }
 
        R300_NEWPRIM(rmesa);
@@ -497,11 +489,13 @@ void r300RenderStart(GLcontext *ctx)
        r300ContextPtr rmesa = R300_CONTEXT( ctx );
 
        r300ChooseRenderState(ctx);
+
+       r300UpdateShaders(rmesa);
+
        r300PrepareVertices(ctx);
 
        r300ValidateBuffers(ctx);
 
-       r300UpdateShaders(rmesa);
        r300UpdateShaderStates(rmesa);
 
        r300EmitCacheFlush(rmesa);
index 0b048303508c9b68cbd3743c64965b4abfc0ca39..6f9b4db40f7201e960e171a00a892f9110abd2e0 100644 (file)
@@ -1223,8 +1223,7 @@ void r300TranslateVertexShader(struct r300_vertex_program *vp)
        }
 }
 
-static void insert_wpos(struct r300_vertex_program *vp, struct gl_program *prog,
-                       GLuint temp_index)
+static void insert_wpos(struct gl_program *prog, GLuint temp_index, int tex_id)
 {
        struct prog_instruction *vpi;
 
@@ -1248,7 +1247,7 @@ static void insert_wpos(struct r300_vertex_program *vp, struct gl_program *prog,
        vpi->Opcode = OPCODE_MOV;
 
        vpi->DstReg.File = PROGRAM_OUTPUT;
-       vpi->DstReg.Index = VERT_RESULT_TEX0 + vp->wpos_idx;
+       vpi->DstReg.Index = VERT_RESULT_TEX0 + tex_id;
        vpi->DstReg.WriteMask = WRITEMASK_XYZW;
        vpi->DstReg.CondMask = COND_TR;
 
@@ -1259,12 +1258,9 @@ static void insert_wpos(struct r300_vertex_program *vp, struct gl_program *prog,
        ++vpi;
 
        vpi->Opcode = OPCODE_END;
-
-       prog->OutputsWritten |= 1 << (VERT_RESULT_TEX0 + vp->wpos_idx);
 }
 
-static void pos_as_texcoord(struct r300_vertex_program *vp,
-                           struct gl_program *prog)
+static void pos_as_texcoord(struct gl_program *prog, int tex_id)
 {
        struct prog_instruction *vpi;
        GLuint tempregi = prog->NumTemporaries;
@@ -1278,7 +1274,37 @@ static void pos_as_texcoord(struct r300_vertex_program *vp,
                }
        }
 
-       insert_wpos(vp, prog, tempregi);
+       insert_wpos(prog, tempregi, tex_id);
+
+       prog->OutputsWritten |= 1 << (VERT_RESULT_TEX0 + tex_id);
+}
+
+/**
+ @TODO
+  We can put X001 swizzle only if input components are directly mapped from output components.
+  For some insts we need to skip source swizzles and add: MOV OUTPUT[fog_attr].yzw, CONST[0].0001
+ */
+static void fog_as_texcoord(struct gl_program *prog, int tex_id)
+{
+       struct prog_instruction *vpi;
+       int i;
+
+       vpi = prog->Instructions;
+       while (vpi->Opcode != OPCODE_END) {
+               if (vpi->DstReg.File == PROGRAM_OUTPUT && vpi->DstReg.Index == VERT_RESULT_FOGC) {
+                       vpi->DstReg.Index = VERT_RESULT_TEX0 + tex_id;
+                       vpi->DstReg.WriteMask = WRITEMASK_XYZW;
+
+                       for (i = 0; i < _mesa_num_inst_src_regs(vpi->Opcode); ++i) {
+                               vpi->SrcReg[i].Swizzle = combineSwizzles(vpi->SrcReg[i].Swizzle, SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE);
+                       }
+               }
+
+               ++vpi;
+       }
+
+       prog->OutputsWritten &= ~(1 << VERT_RESULT_FOGC);
+       prog->OutputsWritten |= 1 << (VERT_RESULT_TEX0 + tex_id);
 }
 
 static int translateABS(struct gl_program *prog, int pos)
@@ -1513,16 +1539,15 @@ static void addArtificialOutputs(GLcontext *ctx, struct gl_program *prog)
 
 static struct r300_vertex_program *build_program(GLcontext *ctx,
                                                 struct r300_vertex_program_key *wanted_key,
-                                                const struct gl_vertex_program *mesa_vp,
-                                                GLint wpos_idx)
+                                                const struct gl_vertex_program *mesa_vp)
 {
+       r300ContextPtr r300 = R300_CONTEXT(ctx);
        struct r300_vertex_program *vp;
        struct gl_program *prog;
 
        vp = _mesa_calloc(sizeof(*vp));
        vp->Base = (struct gl_vertex_program *) _mesa_clone_program(ctx, &mesa_vp->Base);
        _mesa_memcpy(&vp->key, wanted_key, sizeof(vp->key));
-       vp->wpos_idx = wpos_idx;
 
        prog = &vp->Base->Base;
 
@@ -1532,12 +1557,16 @@ static struct r300_vertex_program *build_program(GLcontext *ctx,
                fflush(stdout);
        }
 
-       if (mesa_vp->IsPositionInvariant) {
+       if (vp->Base->IsPositionInvariant) {
                _mesa_insert_mvp_code(ctx, vp->Base);
        }
 
-       if (wpos_idx > -1) {
-               pos_as_texcoord(vp, prog);
+       if (r300->selected_fp->wpos_attr != FRAG_ATTRIB_MAX) {
+               pos_as_texcoord(&vp->Base->Base, r300->selected_fp->wpos_attr - FRAG_ATTRIB_TEX0);
+       }
+
+       if (r300->selected_fp->fog_attr != FRAG_ATTRIB_MAX) {
+               fog_as_texcoord(&vp->Base->Base, r300->selected_fp->fog_attr - FRAG_ATTRIB_TEX0);
        }
 
        addArtificialOutputs(ctx, prog);
@@ -1562,34 +1591,20 @@ struct r300_vertex_program * r300SelectVertexShader(GLcontext *ctx)
        struct r300_vertex_program_key wanted_key = { 0 };
        struct r300_vertex_program_cont *vpc;
        struct r300_vertex_program *vp;
-       GLint wpos_idx;
 
        vpc = (struct r300_vertex_program_cont *)ctx->VertexProgram._Current;
        wanted_key.FpReads = r300->selected_fp->Base->InputsRead;
+       wanted_key.FogAttr = r300->selected_fp->fog_attr;
+       wanted_key.WPosAttr = r300->selected_fp->wpos_attr;
 
-       for (vp = vpc->progs; vp; vp = vp->next)
+       for (vp = vpc->progs; vp; vp = vp->next) {
                if (_mesa_memcmp(&vp->key, &wanted_key, sizeof(wanted_key))
                    == 0) {
                        return r300->selected_vp = vp;
                }
-
-       wpos_idx = -1;
-       if (wanted_key.FpReads & FRAG_BIT_WPOS) {
-               GLint i;
-
-               for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
-                       if (!(wanted_key.FpReads & (FRAG_BIT_TEX(i))))
-                               break;
-
-                       if (i == ctx->Const.MaxTextureUnits) {
-                               fprintf(stderr, "\tno free texcoord found\n");
-                               _mesa_exit(-1);
-                       }
-
-                       wpos_idx = i;
        }
 
-       vp = build_program(ctx, &wanted_key, &vpc->mesa_program, wpos_idx);
+       vp = build_program(ctx, &wanted_key, &vpc->mesa_program);
        vp->next = vpc->progs;
        vpc->progs = vp;