/** * 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"); } }
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; } }
void brw_wm_pass_fp( struct brw_wm_compile *c ) { struct brw_fragment_program *fp = c->fp; GLuint insn; if (INTEL_DEBUG & DEBUG_WM) { _mesa_printf("\n\n\npre-fp:\n"); _mesa_print_program(&fp->program.Base); _mesa_printf("\n"); } c->pixel_xy = src_undef(); c->delta_xy = src_undef(); c->pixel_w = src_undef(); c->nr_fp_insns = 0; /* Emit preamble instructions: */ 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: */ validate_src_regs(c, inst); 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].NegateBase = 0; out->SrcReg[0].Abs = 1; break; case OPCODE_SUB: out = emit_insn(c, inst); out->Opcode = OPCODE_ADD; out->SrcReg[1].NegateBase ^= 0xf; 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_TXP: precalc_txp(c, inst); 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: case OPCODE_PRINT: break; default: emit_insn(c, inst); break; } } emit_fog(c); emit_fb_write(c); if (INTEL_DEBUG & DEBUG_WM) { _mesa_printf("\n\n\npass_fp:\n"); print_insns( c->prog_instructions, c->nr_fp_insns ); _mesa_printf("\n"); } }