Rewrite vertex and fragment programs so that we don't have to do any hacks on lower level.
struct r300_vertex_program_key {
GLuint FpReads;
+ GLuint FogAttr;
+ GLuint WPosAttr;
} key;
struct r300_vertex_shader_hw_code {
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];
};
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 {
}
}
- 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);
{
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
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;
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++;
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;
}
}
+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) {
insert_WPOS_trailer(&compiler);
+ rewriteFog(&compiler);
+
if (r300->radeon.radeonScreen->chip_family >= CHIP_FAMILY_RV515) {
struct radeon_program_transformation transformations[] = {
{ &r500_transform_TEX, &compiler },
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:
++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);
++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);
}
}
- /* 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);
r300ContextPtr rmesa = R300_CONTEXT( ctx );
r300ChooseRenderState(ctx);
+
+ r300UpdateShaders(rmesa);
+
r300PrepareVertices(ctx);
r300ValidateBuffers(ctx);
- r300UpdateShaders(rmesa);
r300UpdateShaderStates(rmesa);
r300EmitCacheFlush(rmesa);
}
}
-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;
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;
++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;
}
}
- 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)
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;
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);
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;