diff options
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_wm_fp.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm_fp.c | 469 |
1 files changed, 309 insertions, 160 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm_fp.c b/src/mesa/drivers/dri/i965/brw_wm_fp.c index 6df2c95d80..4e3edfbbff 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_fp.c +++ b/src/mesa/drivers/dri/i965/brw_wm_fp.c @@ -42,6 +42,12 @@ #include "shader/prog_statevars.h" +/** An invalid texture target */ +#define TEX_TARGET_NONE NUM_TEXTURE_TARGETS + +/** An invalid texture unit */ +#define TEX_UNIT_NONE BRW_MAX_TEX_UNIT + #define FIRST_INTERNAL_TEMP MAX_NV_FRAGMENT_PROGRAM_TEMPS #define X 0 @@ -58,7 +64,8 @@ static const char *wm_opcode_strings[] = { "PINTERP", "CINTERP", "WPOSXY", - "FB_WRITE" + "FB_WRITE", + "FRONTFACING", }; #if 0 @@ -79,9 +86,8 @@ static struct prog_src_register src_reg(GLuint file, GLuint idx) reg.Index = idx; reg.Swizzle = SWIZZLE_NOOP; reg.RelAddr = 0; - reg.NegateBase = 0; + reg.Negate = NEGATE_NONE; reg.Abs = 0; - reg.NegateAbs = 0; return reg; } @@ -111,6 +117,12 @@ static struct prog_src_register src_swizzle1( struct prog_src_register reg, int return src_swizzle(reg, x, x, x, x); } +static struct prog_src_register src_swizzle4( struct prog_src_register reg, uint swizzle ) +{ + reg.Swizzle = swizzle; + return reg; +} + /*********************************************************************** * Dest regs @@ -123,7 +135,7 @@ static struct prog_dst_register dst_reg(GLuint file, GLuint idx) reg.Index = idx; reg.WriteMask = WRITEMASK_XYZW; reg.RelAddr = 0; - reg.CondMask = 0; + reg.CondMask = COND_TR; reg.CondSwizzle = 0; reg.CondSrc = 0; reg.pad = 0; @@ -177,22 +189,31 @@ static struct prog_instruction *emit_insn(struct brw_wm_compile *c, { struct prog_instruction *inst = get_fp_inst(c); *inst = *inst0; - inst->Data = (void *)inst0; return inst; } -static struct prog_instruction * emit_op(struct brw_wm_compile *c, +static struct prog_instruction * emit_tex_op(struct brw_wm_compile *c, GLuint op, struct prog_dst_register dest, GLuint saturate, GLuint tex_src_unit, GLuint tex_src_target, + GLuint tex_shadow, struct prog_src_register src0, struct prog_src_register src1, struct prog_src_register src2 ) { struct prog_instruction *inst = get_fp_inst(c); + assert(tex_src_unit < BRW_MAX_TEX_UNIT || + tex_src_unit == TEX_UNIT_NONE); + assert(tex_src_target < NUM_TEXTURE_TARGETS || + tex_src_target == TEX_TARGET_NONE); + + /* update mask of which texture units are referenced by this program */ + if (tex_src_unit != TEX_UNIT_NONE) + c->fp->tex_units_used |= (1 << tex_src_unit); + memset(inst, 0, sizeof(*inst)); inst->Opcode = op; @@ -200,6 +221,7 @@ static struct prog_instruction * emit_op(struct brw_wm_compile *c, inst->SaturateMode = saturate; inst->TexSrcUnit = tex_src_unit; inst->TexSrcTarget = tex_src_target; + inst->TexShadow = tex_shadow; inst->SrcReg[0] = src0; inst->SrcReg[1] = src1; inst->SrcReg[2] = src2; @@ -207,6 +229,53 @@ static struct prog_instruction * emit_op(struct brw_wm_compile *c, } +static struct prog_instruction * emit_op(struct brw_wm_compile *c, + GLuint op, + struct prog_dst_register dest, + GLuint saturate, + struct prog_src_register src0, + struct prog_src_register src1, + struct prog_src_register src2 ) +{ + return emit_tex_op(c, op, dest, saturate, + TEX_UNIT_NONE, TEX_TARGET_NONE, 0, /* unit, tgt, shadow */ + src0, src1, src2); +} + + +/* Many Mesa opcodes produce the same value across all the result channels. + * We'd rather not have to support that splatting in the opcode implementations, + * and brw_wm_pass*.c wants to optimize them out by shuffling references around + * anyway. We can easily get both by emitting the opcode to one channel, and + * then MOVing it to the others, which brw_wm_pass*.c already understands. + */ +static struct prog_instruction *emit_scalar_insn(struct brw_wm_compile *c, + const struct prog_instruction *inst0) +{ + struct prog_instruction *inst; + unsigned int dst_chan; + unsigned int other_channel_mask; + + if (inst0->DstReg.WriteMask == 0) + return NULL; + + dst_chan = _mesa_ffs(inst0->DstReg.WriteMask) - 1; + inst = get_fp_inst(c); + *inst = *inst0; + inst->DstReg.WriteMask = 1 << dst_chan; + + other_channel_mask = inst0->DstReg.WriteMask & ~(1 << dst_chan); + if (other_channel_mask != 0) { + inst = emit_op(c, + OPCODE_MOV, + dst_mask(inst0->DstReg, other_channel_mask), + 0, + src_swizzle1(src_reg_from_dst(inst0->DstReg), dst_chan), + src_undef(), + src_undef()); + } + return inst; +} /*********************************************************************** @@ -228,7 +297,7 @@ static struct prog_src_register get_pixel_xy( struct brw_wm_compile *c ) emit_op(c, WM_PIXELXY, dst_mask(pixel_xy, WRITEMASK_XY), - 0, 0, 0, + 0, payload_r0_depth, src_undef(), src_undef()); @@ -251,7 +320,7 @@ static struct prog_src_register get_delta_xy( struct brw_wm_compile *c ) emit_op(c, WM_DELTAXY, dst_mask(delta_xy, WRITEMASK_XY), - 0, 0, 0, + 0, pixel_xy, payload_r0_depth, src_undef()); @@ -268,14 +337,13 @@ static struct prog_src_register get_pixel_w( struct brw_wm_compile *c ) struct prog_dst_register pixel_w = get_temp(c); struct prog_src_register deltas = get_delta_xy(c); struct prog_src_register interp_wpos = src_reg(PROGRAM_PAYLOAD, FRAG_ATTRIB_WPOS); - - + /* deltas.xyw = DELTAS2 deltas.xy, payload.interp_wpos.x */ emit_op(c, WM_PIXELW, dst_mask(pixel_w, WRITEMASK_W), - 0, 0, 0, + 0, interp_wpos, deltas, src_undef()); @@ -293,24 +361,19 @@ static void emit_interp( struct brw_wm_compile *c, struct prog_dst_register dst = dst_reg(PROGRAM_INPUT, idx); struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx); struct prog_src_register deltas = get_delta_xy(c); - struct prog_src_register arg2; - GLuint opcode; - + /* Need to use PINTERP on attributes which have been * multiplied by 1/W in the SF program, and LINTERP on those * which have not: */ switch (idx) { case FRAG_ATTRIB_WPOS: - opcode = WM_LINTERP; - arg2 = src_undef(); - /* Have to treat wpos.xy specially: */ emit_op(c, WM_WPOSXY, dst_mask(dst, WRITEMASK_XY), - 0, 0, 0, + 0, get_pixel_xy(c), src_undef(), src_undef()); @@ -322,10 +385,10 @@ static void emit_interp( struct brw_wm_compile *c, emit_op(c, WM_LINTERP, dst, - 0, 0, 0, + 0, interp, deltas, - arg2); + src_undef()); break; case FRAG_ATTRIB_COL0: case FRAG_ATTRIB_COL1: @@ -333,26 +396,95 @@ static void emit_interp( struct brw_wm_compile *c, emit_op(c, WM_CINTERP, dst, - 0, 0, 0, + 0, interp, src_undef(), src_undef()); } else { - emit_op(c, - WM_LINTERP, - dst, - 0, 0, 0, - interp, - deltas, - src_undef()); + if (c->key.linear_color) { + emit_op(c, + WM_LINTERP, + dst, + 0, + interp, + deltas, + src_undef()); + } + else { + /* perspective-corrected color interpolation */ + emit_op(c, + WM_PINTERP, + dst, + 0, + interp, + deltas, + get_pixel_w(c)); + } } break; + case FRAG_ATTRIB_FOGC: + /* Interpolate the fog coordinate */ + emit_op(c, + WM_PINTERP, + dst_mask(dst, WRITEMASK_X), + 0, + interp, + deltas, + get_pixel_w(c)); + + emit_op(c, + OPCODE_MOV, + dst_mask(dst, WRITEMASK_YZW), + 0, + src_swizzle(interp, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ONE), + src_undef(), + src_undef()); + break; + + case FRAG_ATTRIB_FACE: + /* XXX review/test this case */ + emit_op(c, + WM_FRONTFACING, + dst_mask(dst, WRITEMASK_X), + 0, + src_undef(), + src_undef(), + src_undef()); + break; + + case FRAG_ATTRIB_PNTC: + /* XXX review/test this case */ + emit_op(c, + WM_PINTERP, + dst_mask(dst, WRITEMASK_XY), + 0, + interp, + deltas, + get_pixel_w(c)); + + emit_op(c, + OPCODE_MOV, + dst_mask(dst, WRITEMASK_ZW), + 0, + src_swizzle(interp, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ZERO, + SWIZZLE_ONE), + src_undef(), + src_undef()); + break; + default: emit_op(c, WM_PINTERP, dst, - 0, 0, 0, + 0, interp, deltas, get_pixel_w(c)); @@ -362,38 +494,6 @@ static void emit_interp( struct brw_wm_compile *c, c->fp_interp_emitted |= 1<<idx; } -static void emit_ddx( struct brw_wm_compile *c, - const struct prog_instruction *inst ) -{ - GLuint idx = inst->SrcReg[0].Index; - struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx); - - c->fp_deriv_emitted |= 1<<idx; - emit_op(c, - OPCODE_DDX, - inst->DstReg, - 0, 0, 0, - interp, - get_pixel_w(c), - src_undef()); -} - -static void emit_ddy( struct brw_wm_compile *c, - const struct prog_instruction *inst ) -{ - GLuint idx = inst->SrcReg[0].Index; - struct prog_src_register interp = src_reg(PROGRAM_PAYLOAD, idx); - - c->fp_deriv_emitted |= 1<<idx; - emit_op(c, - OPCODE_DDY, - inst->DstReg, - 0, 0, 0, - interp, - get_pixel_w(c), - src_undef()); -} - /*********************************************************************** * Hacks to extend the program parameter and constant lists. */ @@ -483,13 +583,12 @@ static void precalc_dst( struct brw_wm_compile *c, emit_op(c, OPCODE_MUL, dst_mask(dst, WRITEMASK_Y), - inst->SaturateMode, 0, 0, + inst->SaturateMode, src0, src1, src_undef()); } - if (dst.WriteMask & WRITEMASK_XZ) { struct prog_instruction *swz; GLuint z = GET_SWZ(src0.Swizzle, Z); @@ -499,12 +598,12 @@ static void precalc_dst( struct brw_wm_compile *c, swz = emit_op(c, OPCODE_SWZ, dst_mask(dst, WRITEMASK_XZ), - inst->SaturateMode, 0, 0, + inst->SaturateMode, src_swizzle(src0, SWIZZLE_ONE, z, z, z), src_undef(), src_undef()); /* Avoid letting negation flag of src0 affect our 1 constant. */ - swz->SrcReg[0].NegateBase &= ~NEGATE_X; + swz->SrcReg[0].Negate &= ~NEGATE_X; } if (dst.WriteMask & WRITEMASK_W) { /* dst.w = mov src1.w @@ -512,7 +611,7 @@ static void precalc_dst( struct brw_wm_compile *c, emit_op(c, OPCODE_MOV, dst_mask(dst, WRITEMASK_W), - inst->SaturateMode, 0, 0, + inst->SaturateMode, src1, src_undef(), src_undef()); @@ -534,32 +633,40 @@ static void precalc_lit( struct brw_wm_compile *c, swz = emit_op(c, OPCODE_SWZ, dst_mask(dst, WRITEMASK_XW), - 0, 0, 0, + 0, src_swizzle1(src0, SWIZZLE_ONE), src_undef(), src_undef()); /* Avoid letting the negation flag of src0 affect our 1 constant. */ - swz->SrcReg[0].NegateBase = 0; + swz->SrcReg[0].Negate = NEGATE_NONE; } - if (dst.WriteMask & WRITEMASK_YZ) { emit_op(c, OPCODE_LIT, dst_mask(dst, WRITEMASK_YZ), - inst->SaturateMode, 0, 0, + inst->SaturateMode, src0, src_undef(), src_undef()); } } + +/** + * Some TEX instructions require extra code, cube map coordinate + * normalization, or coordinate scaling for RECT textures, etc. + * This function emits those extra instructions and the TEX + * instruction itself. + */ static void precalc_tex( struct brw_wm_compile *c, const struct prog_instruction *inst ) { struct prog_src_register coord; struct prog_dst_register tmpcoord; - GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit]; + const GLuint unit = c->fp->program.Base.SamplerUnits[inst->TexSrcUnit]; + + assert(unit < BRW_MAX_TEX_UNIT); if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) { struct prog_instruction *out; @@ -569,49 +676,56 @@ static void precalc_tex( struct brw_wm_compile *c, struct prog_src_register tmp1src = src_reg_from_dst(tmp1); struct prog_src_register src0 = inst->SrcReg[0]; + /* find longest component of coord vector and normalize it */ tmpcoord = get_temp(c); coord = src_reg_from_dst(tmpcoord); + /* tmpcoord = src0 (i.e.: coord = src0) */ out = emit_op(c, OPCODE_MOV, tmpcoord, - 0, 0, 0, + 0, src0, src_undef(), src_undef()); - out->SrcReg[0].NegateBase = 0; + out->SrcReg[0].Negate = NEGATE_NONE; out->SrcReg[0].Abs = 1; + /* tmp0 = MAX(coord.X, coord.Y) */ emit_op(c, OPCODE_MAX, tmp0, - 0, 0, 0, + 0, src_swizzle1(coord, X), src_swizzle1(coord, Y), src_undef()); + /* tmp1 = MAX(tmp0, coord.Z) */ emit_op(c, OPCODE_MAX, tmp1, - 0, 0, 0, + 0, tmp0src, src_swizzle1(coord, Z), src_undef()); + /* tmp0 = 1 / tmp1 */ emit_op(c, OPCODE_RCP, - tmp0, - 0, 0, 0, + dst_mask(tmp0, WRITEMASK_X), + 0, tmp1src, src_undef(), src_undef()); + /* tmpCoord = src0 * tmp0 */ emit_op(c, OPCODE_MUL, tmpcoord, - 0, 0, 0, + 0, src0, - tmp0src, + src_swizzle1(tmp0src, SWIZZLE_X), src_undef()); release_temp(c, tmp0); release_temp(c, tmp1); - } else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) { + } + else if (inst->TexSrcTarget == TEXTURE_RECT_INDEX) { struct prog_src_register scale = search_or_add_param5( c, STATE_INTERNAL, @@ -626,9 +740,13 @@ static void precalc_tex( struct brw_wm_compile *c, emit_op(c, OPCODE_MUL, tmpcoord, - 0, 0, 0, + 0, inst->SrcReg[0], - scale, + src_swizzle(scale, + SWIZZLE_X, + SWIZZLE_Y, + SWIZZLE_ONE, + SWIZZLE_ONE), src_undef()); coord = src_reg_from_dst(tmpcoord); @@ -642,19 +760,9 @@ static void precalc_tex( struct brw_wm_compile *c, * conversion requires allocating a temporary variable which we * don't have the facility to do that late in the compilation. */ - if (!(c->key.yuvtex_mask & (1<<unit))) { - emit_op(c, - OPCODE_TEX, - inst->DstReg, - inst->SaturateMode, - unit, - inst->TexSrcTarget, - coord, - src_undef(), - src_undef()); - } - else { - GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit); + if (c->key.yuvtex_mask & (1 << unit)) { + /* convert ycbcr to RGBA */ + GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit); /* CONST C0 = { -.5, -.0625, -.5, 1.164 } @@ -676,22 +784,23 @@ static void precalc_tex( struct brw_wm_compile *c, /* tmp = TEX ... */ - emit_op(c, - OPCODE_TEX, - tmp, - inst->SaturateMode, - unit, - inst->TexSrcTarget, - coord, - src_undef(), - src_undef()); + emit_tex_op(c, + OPCODE_TEX, + tmp, + inst->SaturateMode, + unit, + inst->TexSrcTarget, + inst->TexShadow, + coord, + src_undef(), + src_undef()); /* tmp.xyz = ADD TMP, C0 */ emit_op(c, OPCODE_ADD, dst_mask(tmp, WRITEMASK_XYZ), - 0, 0, 0, + 0, tmpsrc, C0, src_undef()); @@ -702,7 +811,7 @@ static void precalc_tex( struct brw_wm_compile *c, emit_op(c, OPCODE_MUL, dst_mask(tmp, WRITEMASK_Y), - 0, 0, 0, + 0, tmpsrc, src_swizzle1(C0, W), src_undef()); @@ -717,7 +826,7 @@ static void precalc_tex( struct brw_wm_compile *c, emit_op(c, OPCODE_MAD, dst_mask(dst, WRITEMASK_XYZ), - 0, 0, 0, + 0, swap_uv?src_swizzle(tmpsrc, Z,Z,X,X):src_swizzle(tmpsrc, X,X,Z,Z), C1, src_swizzle1(tmpsrc, Y)); @@ -727,13 +836,38 @@ static void precalc_tex( struct brw_wm_compile *c, emit_op(c, OPCODE_MAD, dst_mask(dst, WRITEMASK_Y), - 0, 0, 0, + 0, src_swizzle1(tmpsrc, Z), src_swizzle1(C1, W), src_swizzle1(src_reg_from_dst(dst), Y)); release_temp(c, tmp); } + else { + /* ordinary RGBA tex instruction */ + emit_tex_op(c, + OPCODE_TEX, + inst->DstReg, + inst->SaturateMode, + unit, + inst->TexSrcTarget, + inst->TexShadow, + coord, + src_undef(), + src_undef()); + } + + /* For GL_EXT_texture_swizzle: */ + if (c->key.tex_swizzles[unit] != SWIZZLE_NOOP) { + /* swizzle the result of the TEX instruction */ + struct prog_src_register tmpsrc = src_reg_from_dst(inst->DstReg); + emit_op(c, OPCODE_SWZ, + inst->DstReg, + SATURATE_OFF, /* saturate already done above */ + src_swizzle4(tmpsrc, c->key.tex_swizzles[unit]), + src_undef(), + src_undef()); + } if ((inst->TexSrcTarget == TEXTURE_RECT_INDEX) || (inst->TexSrcTarget == TEXTURE_CUBE_INDEX)) @@ -741,10 +875,16 @@ static void precalc_tex( struct brw_wm_compile *c, } +/** + * Check if the given TXP instruction really needs the divide-by-W step. + */ static GLboolean projtex( struct brw_wm_compile *c, const struct prog_instruction *inst ) { - struct prog_src_register src = inst->SrcReg[0]; + const struct prog_src_register src = inst->SrcReg[0]; + GLboolean retVal; + + assert(inst->Opcode == OPCODE_TXP); /* Only try to detect the simplest cases. Could detect (later) * cases where we are trying to emit code like RCP {1.0}, MUL x, @@ -754,16 +894,21 @@ static GLboolean projtex( struct brw_wm_compile *c, * user-provided fragment programs anyway: */ if (inst->TexSrcTarget == TEXTURE_CUBE_INDEX) - return 0; /* ut2004 gun rendering !?! */ + retVal = GL_FALSE; /* ut2004 gun rendering !?! */ else if (src.File == PROGRAM_INPUT && GET_SWZ(src.Swizzle, W) == W && - (c->key.projtex_mask & (1<<(src.Index + FRAG_ATTRIB_WPOS - FRAG_ATTRIB_TEX0))) == 0) - return 0; + (c->key.proj_attrib_mask & (1 << src.Index)) == 0) + retVal = GL_FALSE; else - return 1; + retVal = GL_TRUE; + + return retVal; } +/** + * Emit code for TXP. + */ static void precalc_txp( struct brw_wm_compile *c, const struct prog_instruction *inst ) { @@ -778,7 +923,7 @@ static void precalc_txp( struct brw_wm_compile *c, emit_op(c, OPCODE_RCP, dst_mask(tmp, WRITEMASK_W), - 0, 0, 0, + 0, src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)), src_undef(), src_undef()); @@ -788,7 +933,7 @@ static void precalc_txp( struct brw_wm_compile *c, emit_op(c, OPCODE_MUL, dst_mask(tmp, WRITEMASK_XYZ), - 0, 0, 0, + 0, src0, src_swizzle1(src_reg_from_dst(tmp), W), src_undef()); @@ -814,42 +959,41 @@ static void precalc_txp( struct brw_wm_compile *c, static void emit_fb_write( struct brw_wm_compile *c ) { struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH); - struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR); + struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPTH); struct prog_src_register outcolor; GLuint i; struct prog_instruction *inst, *last_inst; struct brw_context *brw = c->func.brw; - /* inst->Sampler is not used by backend, - use it for fb write target and eot */ - - if (brw->state.nr_draw_regions > 1) { - for (i = 0 ; i < brw->state.nr_draw_regions; i++) { - outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i); - last_inst = inst = emit_op(c, - WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0, - outcolor, payload_r0_depth, outdepth); - inst->Sampler = (i<<1); - if (c->fp_fragcolor_emitted) { - outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); - last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), - 0, 0, 0, outcolor, payload_r0_depth, outdepth); - inst->Sampler = (i<<1); - } - } - last_inst->Sampler |= 1; //eot + /* The inst->Aux field is used for FB write target and the EOT marker */ + + if (brw->state.nr_color_regions > 1) { + for (i = 0 ; i < brw->state.nr_color_regions; i++) { + outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i); + last_inst = inst = emit_op(c, + WM_FB_WRITE, dst_mask(dst_undef(),0), 0, + outcolor, payload_r0_depth, outdepth); + inst->Aux = (i<<1); + if (c->fp_fragcolor_emitted) { + outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR); + last_inst = inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), + 0, outcolor, payload_r0_depth, outdepth); + inst->Aux = (i<<1); + } + } + last_inst->Aux |= 1; //eot } else { /* if gl_FragData[0] is written, use it, else use gl_FragColor */ if (c->fp->program.Base.OutputsWritten & (1 << FRAG_RESULT_DATA0)) outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0); else - outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); + outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR); - inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), - 0, 0, 0, outcolor, payload_r0_depth, outdepth); - inst->Sampler = 1|(0<<1); + inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), + 0, outcolor, payload_r0_depth, outdepth); + inst->Aux = 1|(0<<1); } } @@ -880,9 +1024,9 @@ static void validate_dst_regs( struct brw_wm_compile *c, const struct prog_instruction *inst ) { if (inst->DstReg.File == PROGRAM_OUTPUT) { - GLuint idx = inst->DstReg.Index; - if (idx == FRAG_RESULT_COLR) - c->fp_fragcolor_emitted = 1; + GLuint idx = inst->DstReg.Index; + if (idx == FRAG_RESULT_COLOR) + c->fp_fragcolor_emitted = 1; } } @@ -902,11 +1046,15 @@ static void print_insns( const struct prog_instruction *insn, 3); } else - _mesa_printf("UNKNOWN\n"); - + _mesa_printf("965 Opcode %d\n", insn->Opcode); } } + +/** + * Initial pass for fragment program code generation. + * This function is used by both the GLSL and non-GLSL paths. + */ void brw_wm_pass_fp( struct brw_wm_compile *c ) { struct brw_fragment_program *fp = c->fp; @@ -922,16 +1070,21 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) c->delta_xy = src_undef(); c->pixel_w = src_undef(); c->nr_fp_insns = 0; + c->fp->tex_units_used = 0x0; - /* Emit preamble instructions: + /* Emit preamble instructions. This is where special instructions such as + * WM_CINTERP, WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to + * compute shader inputs from varying vars. */ - - for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) { const struct prog_instruction *inst = &fp->program.Base.Instructions[insn]; validate_src_regs(c, inst); validate_dst_regs(c, inst); } + + /* Loop over all instructions doing assorted simplifications and + * transformations. + */ for (insn = 0; insn < fp->program.Base.NumInstructions; insn++) { const struct prog_instruction *inst = &fp->program.Base.Instructions[insn]; struct prog_instruction *out; @@ -940,7 +1093,6 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) * necessary: */ - switch (inst->Opcode) { case OPCODE_SWZ: out = emit_insn(c, inst); @@ -950,14 +1102,14 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) case OPCODE_ABS: out = emit_insn(c, inst); out->Opcode = OPCODE_MOV; - out->SrcReg[0].NegateBase = 0; + out->SrcReg[0].Negate = NEGATE_NONE; out->SrcReg[0].Abs = 1; break; case OPCODE_SUB: out = emit_insn(c, inst); out->Opcode = OPCODE_ADD; - out->SrcReg[1].NegateBase ^= 0xf; + out->SrcReg[1].Negate ^= NEGATE_XYZW; break; case OPCODE_SCS: @@ -986,6 +1138,7 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) case OPCODE_TXB: out = emit_insn(c, inst); out->TexSrcUnit = fp->program.Base.SamplerUnits[inst->TexSrcUnit]; + assert(out->TexSrcUnit < BRW_MAX_TEX_UNIT); break; case OPCODE_XPD: @@ -1001,28 +1154,24 @@ void brw_wm_pass_fp( struct brw_wm_compile *c ) */ out->DstReg.WriteMask = 0; break; - case OPCODE_DDX: - emit_ddx(c, inst); - break; - case OPCODE_DDY: - emit_ddy(c, inst); - break; case OPCODE_END: emit_fb_write(c); break; case OPCODE_PRINT: break; - default: - emit_insn(c, inst); + if (brw_wm_is_scalar_result(inst->Opcode)) + emit_scalar_insn(c, inst); + else + emit_insn(c, inst); break; } } if (INTEL_DEBUG & DEBUG_WM) { - _mesa_printf("pass_fp:\n"); - print_insns( c->prog_instructions, c->nr_fp_insns ); - _mesa_printf("\n"); + _mesa_printf("pass_fp:\n"); + print_insns( c->prog_instructions, c->nr_fp_insns ); + _mesa_printf("\n"); } } |