/** * Emit code for TXP. */ static void precalc_txp( struct brw_wm_compile *c, const struct prog_instruction *inst ) { struct prog_src_register src0 = inst->SrcReg[0]; if (projtex(c, inst)) { struct prog_dst_register tmp = get_temp(c); struct prog_instruction tmp_inst; /* tmp0.w = RCP inst.arg[0][3] */ emit_op(c, OPCODE_RCP, dst_mask(tmp, WRITEMASK_W), 0, src_swizzle1(src0, GET_SWZ(src0.Swizzle, W)), src_undef(), src_undef()); /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww */ emit_op(c, OPCODE_MUL, dst_mask(tmp, WRITEMASK_XYZ), 0, src0, src_swizzle1(src_reg_from_dst(tmp), W), src_undef()); /* dst = precalc(TEX tmp0) */ tmp_inst = *inst; tmp_inst.SrcReg[0] = src_reg_from_dst(tmp); precalc_tex(c, &tmp_inst); release_temp(c, tmp); } else { /* dst = precalc(TEX src0) */ precalc_tex(c, inst); } }
/** * Emit code for TXP. */ static void precalc_txp( struct brw_wm_compile *c, struct brw_fp_dst dst, unsigned target, unsigned unit, struct brw_fp_src src0, struct brw_fp_src sampler ) { if (projtex(c, target, src0)) { struct brw_fp_dst tmp = get_temp(c); /* tmp0.w = RCP inst.arg[0][3] */ emit_op1(c, TGSI_OPCODE_RCP, dst_mask(tmp, BRW_WRITEMASK_W), src_scalar(src0, W)); /* tmp0.xyz = MUL inst.arg[0], tmp0.wwww */ emit_op2(c, TGSI_OPCODE_MUL, dst_mask(tmp, BRW_WRITEMASK_XYZ), src0, src_scalar(src_reg_from_dst(tmp), W)); /* dst = TEX tmp0 */ precalc_tex(c, dst, target, unit, src_reg_from_dst(tmp), sampler ); release_temp(c, tmp); } else { /* dst = TEX src0 */ precalc_tex(c, dst, target, unit, src0, sampler); } }
static void emit_insn( struct brw_wm_compile *c, const struct tgsi_full_instruction *inst ) { unsigned opcode = inst->Instruction.Opcode; struct brw_fp_dst dst; struct brw_fp_src src[3]; int i; dst = translate_dst( c, &inst->Dst[0], inst->Instruction.Saturate ); for (i = 0; i < inst->Instruction.NumSrcRegs; i++) src[i] = translate_src( c, &inst->Src[i] ); switch (opcode) { case TGSI_OPCODE_ABS: emit_op1(c, TGSI_OPCODE_MOV, dst, src_abs(src[0])); break; case TGSI_OPCODE_SUB: emit_op2(c, TGSI_OPCODE_ADD, dst, src[0], src_negate(src[1])); break; case TGSI_OPCODE_SCS: emit_op1(c, TGSI_OPCODE_SCS, dst_mask(dst, BRW_WRITEMASK_XY), src[0]); break; case TGSI_OPCODE_DST: precalc_dst(c, dst, src[0], src[1]); break; case TGSI_OPCODE_LIT: precalc_lit(c, dst, src[0]); break; case TGSI_OPCODE_TEX: precalc_tex(c, dst, inst->Texture.Texture, src[1].index, /* use sampler unit for tex idx */ src[0], /* coord */ src[1]); /* sampler */ break; case TGSI_OPCODE_TXP: precalc_txp(c, dst, inst->Texture.Texture, src[1].index, /* use sampler unit for tex idx */ src[0], /* coord */ src[1]); /* sampler */ break; case TGSI_OPCODE_TXB: /* XXX: TXB not done */ precalc_tex(c, dst, inst->Texture.Texture, src[1].index, /* use sampler unit for tex idx*/ src[0], src[1]); break; case TGSI_OPCODE_XPD: emit_op2(c, TGSI_OPCODE_XPD, dst_mask(dst, BRW_WRITEMASK_XYZ), src[0], src[1]); break; case TGSI_OPCODE_KIL: emit_op1(c, TGSI_OPCODE_KIL, dst_mask(dst_undef(), 0), src[0]); break; case TGSI_OPCODE_END: emit_fb_write(c); break; default: if (!c->key.has_flow_control && brw_wm_is_scalar_result(opcode)) emit_scalar_insn(c, opcode, dst, src[0], src[1], src[2]); else emit_op3(c, opcode, dst, src[0], src[1], src[2]); break; } }
/** * 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; GLuint insn; if (INTEL_DEBUG & DEBUG_WM) { printf("pre-fp:\n"); _mesa_print_program(&fp->program.Base); printf("\n"); } c->pixel_xy = src_undef(); c->delta_xy = src_undef(); c->pixel_w = src_undef(); c->nr_fp_insns = 0; c->fp->tex_units_used = 0x0; /* 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; /* Check for INPUT values, emit INTERP instructions where * necessary: */ switch (inst->Opcode) { case OPCODE_SWZ: out = emit_insn(c, inst); out->Opcode = OPCODE_MOV; break; case OPCODE_ABS: out = emit_insn(c, inst); out->Opcode = OPCODE_MOV; 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].Negate ^= NEGATE_XYZW; break; case OPCODE_SCS: out = emit_insn(c, inst); /* This should probably be done in the parser. */ out->DstReg.WriteMask &= WRITEMASK_XY; break; case OPCODE_DST: precalc_dst(c, inst); break; case OPCODE_LIT: precalc_lit(c, inst); break; case OPCODE_TEX: precalc_tex(c, inst); break; case OPCODE_TXP: precalc_txp(c, inst); break; 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: out = emit_insn(c, inst); /* This should probably be done in the parser. */ out->DstReg.WriteMask &= WRITEMASK_XYZ; break; case OPCODE_KIL: out = emit_insn(c, inst); /* This should probably be done in the parser. */ out->DstReg.WriteMask = 0; break; case OPCODE_END: emit_render_target_writes(c); break; case OPCODE_PRINT: break; default: if (brw_wm_is_scalar_result(inst->Opcode)) emit_scalar_insn(c, inst); else emit_insn(c, inst); break; } } if (INTEL_DEBUG & DEBUG_WM) { printf("pass_fp:\n"); print_insns( c->prog_instructions, c->nr_fp_insns ); printf("\n"); } }