static void emit_fb_write( struct brw_wm_compile *c ) { struct brw_fp_src payload_r0_depth = src_reg(BRW_FILE_PAYLOAD, PAYLOAD_DEPTH); struct brw_fp_src outdepth = find_output_by_semantic(c, TGSI_SEMANTIC_POSITION, 0); GLuint i; outdepth = src_scalar(outdepth, Z); for (i = 0 ; i < c->key.nr_cbufs; i++) { struct brw_fp_src outcolor; outcolor = find_output_by_semantic(c, TGSI_SEMANTIC_COLOR, i); /* Use emit_tex_op so that we can specify the inst->target * field, which is abused to contain the FB write target and the * EOT marker */ emit_tex_op(c, WM_FB_WRITE, dst_undef(), (i == c->key.nr_cbufs - 1), /* EOT */ i, 0, /* no sampler */ outcolor, payload_r0_depth, outdepth); } }
static void emit_render_target_writes( 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_DEPTH); struct prog_src_register outcolor; GLuint i; struct prog_instruction *inst, *last_inst; /* The inst->Aux field is used for FB write target and the EOT marker */ if (c->key.nr_color_regions > 1) { for (i = 0 ; i < c->key.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 = INST_AUX_TARGET(i); 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 = INST_AUX_TARGET(i); } } last_inst->Aux |= INST_AUX_EOT; } else { /* if gl_FragData[0] is written, use it, else use gl_FragColor */ if (c->fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DATA0)) outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0); else outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLOR); inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), 0, outcolor, payload_r0_depth, outdepth); inst->Aux = INST_AUX_EOT | INST_AUX_TARGET(0); } }
static void emit_fb_write( struct brw_wm_compile *c ) { struct prog_src_register outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR); 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); emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0, outcolor, payload_r0_depth, outdepth); }
/** * 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, struct brw_fp_dst dst, unsigned target, unsigned unit, struct brw_fp_src src0, struct brw_fp_src sampler ) { struct brw_fp_src coord; struct brw_fp_dst tmp = dst_undef(); assert(unit < BRW_MAX_TEX_UNIT); /* Cubemap: find longest component of coord vector and normalize * it. */ if (target == TGSI_TEXTURE_CUBE) { struct brw_fp_src tmpsrc; tmp = get_temp(c); tmpsrc = src_reg_from_dst(tmp); /* tmp = abs(src0) */ emit_op1(c, TGSI_OPCODE_MOV, tmp, src_abs(src0)); /* tmp.X = MAX(tmp.X, tmp.Y) */ emit_op2(c, TGSI_OPCODE_MAX, dst_mask(tmp, BRW_WRITEMASK_X), src_scalar(tmpsrc, X), src_scalar(tmpsrc, Y)); /* tmp.X = MAX(tmp.X, tmp.Z) */ emit_op2(c, TGSI_OPCODE_MAX, dst_mask(tmp, BRW_WRITEMASK_X), tmpsrc, src_scalar(tmpsrc, Z)); /* tmp.X = 1 / tmp.X */ emit_op1(c, TGSI_OPCODE_RCP, dst_mask(tmp, BRW_WRITEMASK_X), tmpsrc); /* tmp = src0 * tmp.xxxx */ emit_op2(c, TGSI_OPCODE_MUL, tmp, src0, src_scalar(tmpsrc, X)); coord = tmpsrc; } else if (target == TGSI_TEXTURE_RECT || target == TGSI_TEXTURE_SHADOWRECT) { /* XXX: need a mechanism for internally generated constants. */ coord = src0; } else { coord = src0; } /* Need to emit YUV texture conversions by hand. Probably need to * do this here - the alternative is in brw_wm_emit.c, but the * 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)) { /* convert ycbcr to RGBA */ GLboolean swap_uv = c->key.yuvtex_swap_mask & (1<<unit); struct brw_fp_dst tmp = get_temp(c); struct brw_fp_src tmpsrc = src_reg_from_dst(tmp); struct brw_fp_src C0 = src_imm4f( c, -.5, -.0625, -.5, 1.164 ); struct brw_fp_src C1 = src_imm4f( c, 1.596, -0.813, 2.018, -.391 ); /* tmp = TEX ... */ emit_tex_op(c, TGSI_OPCODE_TEX, dst_saturate(tmp, dst.saturate), unit, target, sampler.index, coord, src_undef(), src_undef()); /* tmp.xyz = ADD TMP, C0 */ emit_op2(c, TGSI_OPCODE_ADD, dst_mask(tmp, BRW_WRITEMASK_XYZ), tmpsrc, C0); /* YUV.y = MUL YUV.y, C0.w */ emit_op2(c, TGSI_OPCODE_MUL, dst_mask(tmp, BRW_WRITEMASK_Y), tmpsrc, src_scalar(C0, W)); /* * if (UV swaped) * RGB.xyz = MAD YUV.zzx, C1, YUV.y * else * RGB.xyz = MAD YUV.xxz, C1, YUV.y */ emit_op3(c, TGSI_OPCODE_MAD, dst_mask(dst, BRW_WRITEMASK_XYZ), ( swap_uv ? src_swizzle(tmpsrc, Z,Z,X,X) : src_swizzle(tmpsrc, X,X,Z,Z)), C1, src_scalar(tmpsrc, Y)); /* RGB.y = MAD YUV.z, C1.w, RGB.y */ emit_op3(c, TGSI_OPCODE_MAD, dst_mask(dst, BRW_WRITEMASK_Y), src_scalar(tmpsrc, Z), src_scalar(C1, W), src_scalar(src_reg_from_dst(dst), Y)); release_temp(c, tmp); } else { /* ordinary RGBA tex instruction */ emit_tex_op(c, TGSI_OPCODE_TEX, dst, unit, target, sampler.index, coord, src_undef(), src_undef()); } /* XXX: add GL_EXT_texture_swizzle support to gallium -- by * generating shader variants in mesa state tracker. */ /* Release this temp if we ended up allocating it: */ if (!dst_is_undef(tmp)) release_temp(c, tmp); }
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; } }