#include "macros.h" #include "shader/prog_parameter.h" #include "brw_context.h" #include "brw_eu.h" #include "brw_wm.h" /* Only guess, need a flag in gl_fragment_program later */ GLboolean brw_wm_is_glsl(const struct gl_fragment_program *fp) { int i; for (i = 0; i < fp->Base.NumInstructions; i++) { struct prog_instruction *inst = &fp->Base.Instructions[i]; switch (inst->Opcode) { case OPCODE_IF: case OPCODE_INT: case OPCODE_ENDIF: case OPCODE_CAL: case OPCODE_BRK: case OPCODE_RET: case OPCODE_DDX: case OPCODE_DDY: case OPCODE_BGNLOOP: return GL_TRUE; default: break; } } return GL_FALSE; } static void set_reg(struct brw_wm_compile *c, int file, int index, int component, struct brw_reg reg) { c->wm_regs[file][index][component].reg = reg; c->wm_regs[file][index][component].inited = GL_TRUE; } static int get_scalar_dst_index(struct prog_instruction *inst) { int i; for (i = 0; i < 4; i++) if (inst->DstReg.WriteMask & (1<tmp_index--, 0); return reg; } static void release_tmps(struct brw_wm_compile *c) { c->tmp_index = 127; } static struct brw_reg get_reg(struct brw_wm_compile *c, int file, int index, int component, int nr, GLuint neg, GLuint abs) { struct brw_reg reg; switch (file) { case PROGRAM_STATE_VAR: case PROGRAM_CONSTANT: case PROGRAM_UNIFORM: file = PROGRAM_STATE_VAR; break; case PROGRAM_UNDEFINED: return brw_null_reg(); default: break; } if(c->wm_regs[file][index][component].inited) reg = c->wm_regs[file][index][component].reg; else reg = brw_vec8_grf(c->reg_index, 0); if(!c->wm_regs[file][index][component].inited) { set_reg(c, file, index, component, reg); c->reg_index++; } if (neg & (1<< component)) { reg = negate(reg); } if (abs) reg = brw_abs(reg); return reg; } static void prealloc_reg(struct brw_wm_compile *c) { int i, j; struct brw_reg reg; int nr_interp_regs = 0; GLuint inputs = FRAG_BIT_WPOS | c->fp_interp_emitted | c->fp_deriv_emitted; for (i = 0; i < 4; i++) { reg = (i < c->key.nr_depth_regs) ? brw_vec8_grf(i*2, 0) : brw_vec8_grf(0, 0); set_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, i, reg); } c->reg_index += 2*c->key.nr_depth_regs; { int nr_params = c->fp->program.Base.Parameters->NumParameters; struct gl_program_parameter_list *plist = c->fp->program.Base.Parameters; int index = 0; c->prog_data.nr_params = 4*nr_params; for (i = 0; i < nr_params; i++) { for (j = 0; j < 4; j++, index++) { reg = brw_vec1_grf(c->reg_index + index/8, index%8); c->prog_data.param[index] = &plist->ParameterValues[i][j]; set_reg(c, PROGRAM_STATE_VAR, i, j, reg); } } c->nr_creg = 2*((4*nr_params+15)/16); c->reg_index += c->nr_creg; } for (i = 0; i < FRAG_ATTRIB_MAX; i++) { if (inputs & (1<reg_index, 0); for (j = 0; j < 4; j++) set_reg(c, PROGRAM_PAYLOAD, i, j, reg); c->reg_index += 2; } } c->prog_data.first_curbe_grf = c->key.nr_depth_regs * 2; c->prog_data.urb_read_length = nr_interp_regs * 2; c->prog_data.curb_read_length = c->nr_creg; c->emit_mask_reg = brw_uw1_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0); c->reg_index++; c->stack = brw_uw16_reg(BRW_GENERAL_REGISTER_FILE, c->reg_index, 0); c->reg_index += 2; } static struct brw_reg get_dst_reg(struct brw_wm_compile *c, struct prog_instruction *inst, int component, int nr) { return get_reg(c, inst->DstReg.File, inst->DstReg.Index, component, nr, 0, 0); } static struct brw_reg get_src_reg(struct brw_wm_compile *c, struct prog_src_register *src, int index, int nr) { int component = GET_SWZ(src->Swizzle, index); return get_reg(c, src->File, src->Index, component, nr, src->NegateBase, src->Abs); } static void emit_abs( struct brw_wm_compile *c, struct prog_instruction *inst) { int i; struct brw_compile *p = &c->func; brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); for (i = 0; i < 4; i++) { if (inst->DstReg.WriteMask & (1<SrcReg[0], i, 1); brw_MOV(p, dst, brw_abs(src)); } } brw_set_saturate(p, 0); } static void emit_int( struct brw_wm_compile *c, struct prog_instruction *inst) { int i; struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); brw_RNDD(p, dst, src); } } brw_set_saturate(p, 0); } static void emit_mov( struct brw_wm_compile *c, struct prog_instruction *inst) { int i; struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); brw_MOV(p, dst, src); } } brw_set_saturate(p, 0); } static void emit_pixel_xy(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_reg r1 = brw_vec1_grf(1, 0); struct brw_reg r1_uw = retype(r1, BRW_REGISTER_TYPE_UW); struct brw_reg dst0, dst1; struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; dst0 = get_dst_reg(c, inst, 0, 1); dst1 = get_dst_reg(c, inst, 1, 1); /* Calculate pixel centers by adding 1 or 0 to each of the * micro-tile coordinates passed in r1. */ if (mask & WRITEMASK_X) { brw_ADD(p, vec8(retype(dst0, BRW_REGISTER_TYPE_UW)), stride(suboffset(r1_uw, 4), 2, 4, 0), brw_imm_v(0x10101010)); } if (mask & WRITEMASK_Y) { brw_ADD(p, vec8(retype(dst1, BRW_REGISTER_TYPE_UW)), stride(suboffset(r1_uw, 5), 2, 4, 0), brw_imm_v(0x11001100)); } } static void emit_delta_xy(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_reg r1 = brw_vec1_grf(1, 0); struct brw_reg dst0, dst1, src0, src1; struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; dst0 = get_dst_reg(c, inst, 0, 1); dst1 = get_dst_reg(c, inst, 1, 1); src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); src1 = get_src_reg(c, &inst->SrcReg[0], 1, 1); /* Calc delta X,Y by subtracting origin in r1 from the pixel * centers. */ if (mask & WRITEMASK_X) { brw_ADD(p, dst0, retype(src0, BRW_REGISTER_TYPE_UW), negate(r1)); } if (mask & WRITEMASK_Y) { brw_ADD(p, dst1, retype(src1, BRW_REGISTER_TYPE_UW), negate(suboffset(r1,1))); } } static void fire_fb_write( struct brw_wm_compile *c, GLuint base_reg, GLuint nr ) { struct brw_compile *p = &c->func; /* Pass through control information: */ /* mov (8) m1.0<1>:ud r1.0<8;8,1>:ud { Align1 NoMask } */ { brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); /* ? */ brw_MOV(p, brw_message_reg(base_reg + 1), brw_vec8_grf(1, 0)); brw_pop_insn_state(p); } /* Send framebuffer write message: */ brw_fb_WRITE(p, retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW), base_reg, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW), 0, /* render surface always 0 */ nr, 0, 1); } static void emit_fb_write(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; int nr = 2; int channel; struct brw_reg src0;//, src1, src2, dst; /* Reserve a space for AA - may not be needed: */ if (c->key.aa_dest_stencil_reg) nr += 1; { brw_push_insn_state(p); for (channel = 0; channel < 4; channel++) { src0 = get_src_reg(c, &inst->SrcReg[0], channel, 1); /* mov (8) m2.0<1>:ud r28.0<8;8,1>:ud { Align1 } */ /* mov (8) m6.0<1>:ud r29.0<8;8,1>:ud { Align1 SecHalf } */ brw_MOV(p, brw_message_reg(nr + channel), src0); } /* skip over the regs populated above: */ nr += 8; brw_pop_insn_state(p); } if (c->key.source_depth_to_render_target) { if (c->key.computes_depth) { src0 = get_src_reg(c, &inst->SrcReg[2], 2, 1); brw_MOV(p, brw_message_reg(nr), src0); } else { src0 = get_src_reg(c, &inst->SrcReg[1], 1, 1); brw_MOV(p, brw_message_reg(nr), src0); } nr += 2; } fire_fb_write(c, 0, nr); } static void emit_pixel_w( struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; if (mask & WRITEMASK_W) { struct brw_reg dst, src0, delta0, delta1; struct brw_reg interp3; dst = get_dst_reg(c, inst, 3, 1); src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); delta0 = get_src_reg(c, &inst->SrcReg[1], 0, 1); delta1 = get_src_reg(c, &inst->SrcReg[1], 1, 1); interp3 = brw_vec1_grf(src0.nr+1, 4); /* Calc 1/w - just linterp wpos[3] optimized by putting the * result straight into a message reg. */ brw_LINE(p, brw_null_reg(), interp3, delta0); brw_MAC(p, brw_message_reg(2), suboffset(interp3, 1), delta1); /* Calc w */ brw_math_16( p, dst, BRW_MATH_FUNCTION_INV, BRW_MATH_SATURATE_NONE, 2, brw_null_reg(), BRW_MATH_PRECISION_FULL); } } static void emit_linterp(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg interp[4]; struct brw_reg dst, delta0, delta1; struct brw_reg src0; src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); delta0 = get_src_reg(c, &inst->SrcReg[1], 0, 1); delta1 = get_src_reg(c, &inst->SrcReg[1], 1, 1); GLuint nr = src0.nr; int i; interp[0] = brw_vec1_grf(nr, 0); interp[1] = brw_vec1_grf(nr, 4); interp[2] = brw_vec1_grf(nr+1, 0); interp[3] = brw_vec1_grf(nr+1, 4); for(i = 0; i < 4; i++ ) { if (mask & (1<func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg interp[4]; struct brw_reg dst, src0; src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); GLuint nr = src0.nr; int i; interp[0] = brw_vec1_grf(nr, 0); interp[1] = brw_vec1_grf(nr, 4); interp[2] = brw_vec1_grf(nr+1, 0); interp[3] = brw_vec1_grf(nr+1, 4); for(i = 0; i < 4; i++ ) { if (mask & (1<func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg interp[4]; struct brw_reg dst, delta0, delta1; struct brw_reg src0, w; src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); delta0 = get_src_reg(c, &inst->SrcReg[1], 0, 1); delta1 = get_src_reg(c, &inst->SrcReg[1], 1, 1); w = get_src_reg(c, &inst->SrcReg[2], 3, 1); GLuint nr = src0.nr; int i; interp[0] = brw_vec1_grf(nr, 0); interp[1] = brw_vec1_grf(nr, 4); interp[2] = brw_vec1_grf(nr+1, 0); interp[3] = brw_vec1_grf(nr+1, 4); for(i = 0; i < 4; i++ ) { if (mask & (1<func; GLuint mask = inst->DstReg.WriteMask; for (i = 0; i < 4; i++) { GLuint i2 = (i+2)%3; GLuint i1 = (i+1)%3; if (mask & (1<SrcReg[0], i2, 1)); src1 = get_src_reg(c, &inst->SrcReg[1], i1, 1); brw_MUL(p, brw_null_reg(), src0, src1); src0 = get_src_reg(c, &inst->SrcReg[0], i1, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i2, 1); brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); brw_MAC(p, dst, src0, src1); brw_set_saturate(p, 0); } } brw_set_saturate(p, 0); } static void emit_dp3(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_reg src0[3], src1[3], dst; int i; struct brw_compile *p = &c->func; for (i = 0; i < 3; i++) { src0[i] = get_src_reg(c, &inst->SrcReg[0], i, 1); src1[i] = get_src_reg(c, &inst->SrcReg[1], i, 1); } dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1); brw_MUL(p, brw_null_reg(), src0[0], src1[0]); brw_MAC(p, brw_null_reg(), src0[1], src1[1]); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_MAC(p, dst, src0[2], src1[2]); brw_set_saturate(p, 0); } static void emit_dp4(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_reg src0[4], src1[4], dst; int i; struct brw_compile *p = &c->func; for (i = 0; i < 4; i++) { src0[i] = get_src_reg(c, &inst->SrcReg[0], i, 1); src1[i] = get_src_reg(c, &inst->SrcReg[1], i, 1); } dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1); brw_MUL(p, brw_null_reg(), src0[0], src1[0]); brw_MAC(p, brw_null_reg(), src0[1], src1[1]); brw_MAC(p, brw_null_reg(), src0[2], src1[2]); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_MAC(p, dst, src0[3], src1[3]); brw_set_saturate(p, 0); } static void emit_dph(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_reg src0[4], src1[4], dst; int i; struct brw_compile *p = &c->func; for (i = 0; i < 4; i++) { src0[i] = get_src_reg(c, &inst->SrcReg[0], i, 1); src1[i] = get_src_reg(c, &inst->SrcReg[1], i, 1); } dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1); brw_MUL(p, brw_null_reg(), src0[0], src1[0]); brw_MAC(p, brw_null_reg(), src0[1], src1[1]); brw_MAC(p, dst, src0[2], src1[2]); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_ADD(p, dst, src0[3], src1[3]); brw_set_saturate(p, 0); } static void emit_math1(struct brw_wm_compile *c, struct prog_instruction *inst, GLuint func) { struct brw_compile *p = &c->func; struct brw_reg src0, dst; src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1); brw_MOV(p, brw_message_reg(2), src0); brw_math(p, dst, func, (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE, 2, brw_null_reg(), BRW_MATH_DATA_VECTOR, BRW_MATH_PRECISION_FULL); } static void emit_rcp(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_math1(c, inst, BRW_MATH_FUNCTION_INV); } static void emit_rsq(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_math1(c, inst, BRW_MATH_FUNCTION_RSQ); } static void emit_sin(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_math1(c, inst, BRW_MATH_FUNCTION_SIN); } static void emit_cos(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_math1(c, inst, BRW_MATH_FUNCTION_COS); } static void emit_ex2(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_math1(c, inst, BRW_MATH_FUNCTION_EXP); } static void emit_lg2(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_math1(c, inst, BRW_MATH_FUNCTION_LOG); } static void emit_add(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg src0, src1, dst; GLuint mask = inst->DstReg.WriteMask; int i; brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); for (i = 0 ; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); brw_ADD(p, dst, src0, src1); } } brw_set_saturate(p, 0); } static void emit_sub(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg src0, src1, dst; GLuint mask = inst->DstReg.WriteMask; int i; brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); for (i = 0 ; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); brw_ADD(p, dst, src0, negate(src1)); } } brw_set_saturate(p, 0); } static void emit_mul(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg src0, src1, dst; GLuint mask = inst->DstReg.WriteMask; int i; brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); for (i = 0 ; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); brw_MUL(p, dst, src0, src1); } } brw_set_saturate(p, 0); } static void emit_frc(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg src0, dst; GLuint mask = inst->DstReg.WriteMask; int i; brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); for (i = 0 ; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); brw_FRC(p, dst, src0); } } if (inst->SaturateMode != SATURATE_OFF) brw_set_saturate(p, 0); } static void emit_flr(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg src0, dst; GLuint mask = inst->DstReg.WriteMask; int i; brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); for (i = 0 ; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); brw_RNDD(p, dst, src0); } } brw_set_saturate(p, 0); } static void emit_max(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg src0, src1, dst; int i; brw_push_insn_state(p); for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_MOV(p, dst, src0); brw_set_saturate(p, 0); brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src0, src1); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); brw_MOV(p, dst, src1); brw_set_saturate(p, 0); brw_set_predicate_control_flag_value(p, 0xff); } } brw_pop_insn_state(p); } static void emit_min(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg src0, src1, dst; int i; brw_push_insn_state(p); for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_MOV(p, dst, src0); brw_set_saturate(p, 0); brw_CMP(p, brw_null_reg(), BRW_CONDITIONAL_L, src1, src0); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); brw_MOV(p, dst, src1); brw_set_saturate(p, 0); brw_set_predicate_control_flag_value(p, 0xff); } } brw_pop_insn_state(p); } static void emit_pow(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg dst, src0, src1; dst = get_dst_reg(c, inst, get_scalar_dst_index(inst), 1); src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); src1 = get_src_reg(c, &inst->SrcReg[1], 0, 1); brw_MOV(p, brw_message_reg(2), src0); brw_MOV(p, brw_message_reg(3), src1); brw_math(p, dst, BRW_MATH_FUNCTION_POW, (inst->SaturateMode != SATURATE_OFF) ? BRW_MATH_SATURATE_SATURATE : BRW_MATH_SATURATE_NONE, 2, brw_null_reg(), BRW_MATH_DATA_VECTOR, BRW_MATH_PRECISION_FULL); } static void emit_lrp(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg dst, tmp1, tmp2, src0, src1, src2; int i; for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); if (src1.nr == dst.nr) { tmp1 = alloc_tmp(c); brw_MOV(p, tmp1, src1); } else tmp1 = src1; src2 = get_src_reg(c, &inst->SrcReg[2], i, 1); if (src2.nr == dst.nr) { tmp2 = alloc_tmp(c); brw_MOV(p, tmp2, src2); } else tmp2 = src2; brw_ADD(p, dst, negate(src0), brw_imm_f(1.0)); brw_MUL(p, brw_null_reg(), dst, tmp2); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_MAC(p, dst, src0, tmp1); brw_set_saturate(p, 0); } release_tmps(c); } } static void emit_kil(struct brw_wm_compile *c) { struct brw_compile *p = &c->func; struct brw_reg depth = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW); brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); brw_NOT(p, c->emit_mask_reg, brw_mask_reg(1)); //IMASK brw_AND(p, depth, c->emit_mask_reg, depth); brw_pop_insn_state(p); } static void emit_mad(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg dst, src0, src1, src2; int i; for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); src2 = get_src_reg(c, &inst->SrcReg[2], i, 1); brw_MUL(p, dst, src0, src1); brw_set_saturate(p, (inst->SaturateMode != SATURATE_OFF) ? 1 : 0); brw_ADD(p, dst, dst, src2); brw_set_saturate(p, 0); } } } static void emit_sop(struct brw_wm_compile *c, struct prog_instruction *inst, GLuint cond) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg dst, src0, src1; int i; brw_push_insn_state(p); for (i = 0; i < 4; i++) { if (mask & (1<SrcReg[0], i, 1); src1 = get_src_reg(c, &inst->SrcReg[1], i, 1); brw_CMP(p, brw_null_reg(), cond, src0, src1); brw_set_predicate_control(p, BRW_PREDICATE_NONE); brw_MOV(p, dst, brw_imm_f(0.0)); brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); brw_MOV(p, dst, brw_imm_f(1.0)); } } brw_pop_insn_state(p); } static void emit_slt(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_sop(c, inst, BRW_CONDITIONAL_L); } static void emit_sle(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_sop(c, inst, BRW_CONDITIONAL_LE); } static void emit_sgt(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_sop(c, inst, BRW_CONDITIONAL_G); } static void emit_sge(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_sop(c, inst, BRW_CONDITIONAL_GE); } static void emit_seq(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_sop(c, inst, BRW_CONDITIONAL_EQ); } static void emit_sne(struct brw_wm_compile *c, struct prog_instruction *inst) { emit_sop(c, inst, BRW_CONDITIONAL_NEQ); } static void emit_ddx(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg interp[4]; struct brw_reg dst; struct brw_reg src0, w; GLuint nr, i; src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); w = get_src_reg(c, &inst->SrcReg[1], 3, 1); nr = src0.nr; interp[0] = brw_vec1_grf(nr, 0); interp[1] = brw_vec1_grf(nr, 4); interp[2] = brw_vec1_grf(nr+1, 0); interp[3] = brw_vec1_grf(nr+1, 4); brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); for(i = 0; i < 4; i++ ) { if (mask & (1<func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg interp[4]; struct brw_reg dst; struct brw_reg src0, w; GLuint nr, i; src0 = get_src_reg(c, &inst->SrcReg[0], 0, 1); nr = src0.nr; w = get_src_reg(c, &inst->SrcReg[1], 3, 1); interp[0] = brw_vec1_grf(nr, 0); interp[1] = brw_vec1_grf(nr, 4); interp[2] = brw_vec1_grf(nr+1, 0); interp[3] = brw_vec1_grf(nr+1, 4); brw_set_saturate(p, inst->SaturateMode != SATURATE_OFF); for(i = 0; i < 4; i++ ) { if (mask & (1<func; GLuint mask = inst->DstReg.WriteMask; struct brw_reg src0[2], dst[2]; dst[0] = get_dst_reg(c, inst, 0, 1); dst[1] = get_dst_reg(c, inst, 1, 1); src0[0] = get_src_reg(c, &inst->SrcReg[0], 0, 1); src0[1] = get_src_reg(c, &inst->SrcReg[0], 1, 1); /* Calc delta X,Y by subtracting origin in r1 from the pixel * centers. */ if (mask & WRITEMASK_X) { brw_MOV(p, dst[0], retype(src0[0], BRW_REGISTER_TYPE_UW)); } if (mask & WRITEMASK_Y) { /* TODO -- window_height - Y */ brw_MOV(p, dst[1], retype(src0[1], BRW_REGISTER_TYPE_UW)); } } /* TODO BIAS on SIMD8 not workind yet... */ static void emit_txb(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg dst[4], src[4], payload_reg; GLuint i; payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0); for (i = 0; i < 4; i++) dst[i] = get_dst_reg(c, inst, i, 1); for (i = 0; i < 4; i++) src[i] = get_src_reg(c, &inst->SrcReg[0], i, 1); switch (inst->TexSrcTarget) { case TEXTURE_1D_INDEX: brw_MOV(p, brw_message_reg(2), src[0]); brw_MOV(p, brw_message_reg(3), brw_imm_f(0)); brw_MOV(p, brw_message_reg(4), brw_imm_f(0)); break; case TEXTURE_2D_INDEX: case TEXTURE_RECT_INDEX: brw_MOV(p, brw_message_reg(2), src[0]); brw_MOV(p, brw_message_reg(3), src[1]); brw_MOV(p, brw_message_reg(4), brw_imm_f(0)); break; default: brw_MOV(p, brw_message_reg(2), src[0]); brw_MOV(p, brw_message_reg(3), src[1]); brw_MOV(p, brw_message_reg(4), src[2]); break; } brw_MOV(p, brw_message_reg(5), src[3]); brw_MOV(p, brw_message_reg(6), brw_imm_f(0)); brw_SAMPLE(p, retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW), 1, retype(payload_reg, BRW_REGISTER_TYPE_UW), inst->TexSrcUnit + 1, /* surface */ inst->TexSrcUnit, /* sampler */ inst->DstReg.WriteMask, BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS, 4, 4, 0); } static void emit_tex(struct brw_wm_compile *c, struct prog_instruction *inst) { struct brw_compile *p = &c->func; struct brw_reg dst[4], src[4], payload_reg; GLuint msg_len; GLuint i, nr; GLuint emit; GLboolean shadow = (c->key.shadowtex_mask & (1<TexSrcUnit)) ? 1 : 0; payload_reg = get_reg(c, PROGRAM_PAYLOAD, PAYLOAD_DEPTH, 0, 1, 0, 0); for (i = 0; i < 4; i++) dst[i] = get_dst_reg(c, inst, i, 1); for (i = 0; i < 4; i++) src[i] = get_src_reg(c, &inst->SrcReg[0], i, 1); switch (inst->TexSrcTarget) { case TEXTURE_1D_INDEX: emit = WRITEMASK_X; nr = 1; break; case TEXTURE_2D_INDEX: case TEXTURE_RECT_INDEX: emit = WRITEMASK_XY; nr = 2; break; default: emit = WRITEMASK_XYZ; nr = 3; break; } msg_len = 1; for (i = 0; i < nr; i++) { static const GLuint swz[4] = {0,1,2,2}; if (emit & (1<TexSrcUnit + 1, /* surface */ inst->TexSrcUnit, /* sampler */ inst->DstReg.WriteMask, BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE, 4, shadow ? 6 : 4, 0); if (shadow) brw_MOV(p, dst[3], brw_imm_f(1.0)); } static void post_wm_emit( struct brw_wm_compile *c ) { GLuint nr_insns = c->fp->program.Base.NumInstructions; GLuint insn, target_insn; struct prog_instruction *inst1, *inst2; struct brw_instruction *brw_inst1, *brw_inst2; int offset; for (insn = 0; insn < nr_insns; insn++) { inst1 = &c->fp->program.Base.Instructions[insn]; brw_inst1 = inst1->Data; switch (inst1->Opcode) { case OPCODE_CAL: target_insn = inst1->BranchTarget; inst2 = &c->fp->program.Base.Instructions[target_insn]; brw_inst2 = inst2->Data; offset = brw_inst2 - brw_inst1; brw_set_src1(brw_inst1, brw_imm_d(offset*16)); break; default: break; } } } static void brw_wm_emit_glsl(struct brw_wm_compile *c) { #define MAX_IFSN 32 #define MAX_LOOP_DEPTH 32 struct brw_instruction *if_inst[MAX_IFSN], *loop_inst[MAX_LOOP_DEPTH]; struct brw_instruction *inst0, *inst1; int i, if_insn = 0, loop_insn = 0; struct brw_compile *p = &c->func; struct brw_indirect stack_index = brw_indirect(0, 0); brw_init_compile(&c->func); c->reg_index = 0; prealloc_reg(c); brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack)); for (i = 0; i < c->nr_fp_insns; i++) { struct prog_instruction *inst = &c->prog_instructions[i]; struct prog_instruction *orig_inst; if ((orig_inst = inst->Data) != 0) orig_inst->Data = current_insn(p); if (inst->CondUpdate) brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ); else brw_set_conditionalmod(p, BRW_CONDITIONAL_NONE); switch (inst->Opcode) { case WM_PIXELXY: emit_pixel_xy(c, inst); break; case WM_DELTAXY: emit_delta_xy(c, inst); break; case WM_PIXELW: emit_pixel_w(c, inst); break; case WM_LINTERP: emit_linterp(c, inst); break; case WM_PINTERP: emit_pinterp(c, inst); break; case WM_CINTERP: emit_cinterp(c, inst); break; case WM_WPOSXY: emit_wpos_xy(c, inst); break; case WM_FB_WRITE: emit_fb_write(c, inst); break; case OPCODE_ABS: emit_abs(c, inst); break; case OPCODE_ADD: emit_add(c, inst); break; case OPCODE_SUB: emit_sub(c, inst); break; case OPCODE_FRC: emit_frc(c, inst); break; case OPCODE_FLR: emit_flr(c, inst); break; case OPCODE_LRP: emit_lrp(c, inst); break; case OPCODE_INT: emit_int(c, inst); break; case OPCODE_MOV: emit_mov(c, inst); break; case OPCODE_DP3: emit_dp3(c, inst); break; case OPCODE_DP4: emit_dp4(c, inst); break; case OPCODE_XPD: emit_xpd(c, inst); break; case OPCODE_DPH: emit_dph(c, inst); break; case OPCODE_RCP: emit_rcp(c, inst); break; case OPCODE_RSQ: emit_rsq(c, inst); break; case OPCODE_SIN: emit_sin(c, inst); break; case OPCODE_COS: emit_cos(c, inst); break; case OPCODE_EX2: emit_ex2(c, inst); break; case OPCODE_LG2: emit_lg2(c, inst); break; case OPCODE_MAX: emit_max(c, inst); break; case OPCODE_MIN: emit_min(c, inst); break; case OPCODE_DDX: emit_ddx(c, inst); break; case OPCODE_DDY: emit_ddy(c, inst); break; case OPCODE_SLT: emit_slt(c, inst); break; case OPCODE_SLE: emit_sle(c, inst); break; case OPCODE_SGT: emit_sgt(c, inst); break; case OPCODE_SGE: emit_sge(c, inst); break; case OPCODE_SEQ: emit_seq(c, inst); break; case OPCODE_SNE: emit_sne(c, inst); break; case OPCODE_MUL: emit_mul(c, inst); break; case OPCODE_POW: emit_pow(c, inst); break; case OPCODE_MAD: emit_mad(c, inst); break; case OPCODE_TEX: emit_tex(c, inst); break; case OPCODE_TXB: emit_txb(c, inst); break; case OPCODE_KIL_NV: emit_kil(c); break; case OPCODE_IF: assert(if_insn < MAX_IFSN); if_inst[if_insn++] = brw_IF(p, BRW_EXECUTE_8); break; case OPCODE_ELSE: if_inst[if_insn-1] = brw_ELSE(p, if_inst[if_insn-1]); break; case OPCODE_ENDIF: assert(if_insn > 0); brw_ENDIF(p, if_inst[--if_insn]); break; case OPCODE_BGNSUB: case OPCODE_ENDSUB: break; case OPCODE_CAL: brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); brw_set_access_mode(p, BRW_ALIGN_1); brw_ADD(p, deref_1ud(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16)); brw_set_access_mode(p, BRW_ALIGN_16); brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(4)); orig_inst = inst->Data; orig_inst->Data = &p->store[p->nr_insn]; brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); brw_pop_insn_state(p); break; case OPCODE_RET: brw_push_insn_state(p); brw_set_mask_control(p, BRW_MASK_DISABLE); brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(-4)); brw_set_access_mode(p, BRW_ALIGN_1); brw_MOV(p, brw_ip_reg(), deref_1ud(stack_index, 0)); brw_set_access_mode(p, BRW_ALIGN_16); brw_pop_insn_state(p); break; case OPCODE_BGNLOOP: loop_inst[loop_insn++] = brw_DO(p, BRW_EXECUTE_8); break; case OPCODE_BRK: brw_BREAK(p); brw_set_predicate_control(p, BRW_PREDICATE_NONE); break; case OPCODE_CONT: brw_CONT(p); brw_set_predicate_control(p, BRW_PREDICATE_NONE); break; case OPCODE_ENDLOOP: loop_insn--; inst0 = inst1 = brw_WHILE(p, loop_inst[loop_insn]); /* patch all the BREAK instructions from last BEGINLOOP */ while (inst0 > loop_inst[loop_insn]) { inst0--; if (inst0->header.opcode == BRW_OPCODE_BREAK) { inst0->bits3.if_else.jump_count = inst1 - inst0 + 1; inst0->bits3.if_else.pop_count = 0; } else if (inst0->header.opcode == BRW_OPCODE_CONTINUE) { inst0->bits3.if_else.jump_count = inst1 - inst0; inst0->bits3.if_else.pop_count = 0; } } break; default: _mesa_printf("unsupported IR in fragment shader %d\n", inst->Opcode); } if (inst->CondUpdate) brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); else brw_set_predicate_control(p, BRW_PREDICATE_NONE); } post_wm_emit(c); for (i = 0; i < c->fp->program.Base.NumInstructions; i++) c->fp->program.Base.Instructions[i].Data = NULL; } void brw_wm_glsl_emit(struct brw_wm_compile *c) { brw_wm_pass_fp(c); c->tmp_index = 127; brw_wm_emit_glsl(c); c->prog_data.total_grf = c->reg_index; c->prog_data.total_scratch = 0; }