On Fri, Jul 11, 2014 at 8:20 PM, Chris Forbes <chr...@ijw.co.nz> wrote: > SIMD8-only for now. > > Signed-off-by: Chris Forbes <chr...@ijw.co.nz> > --- > src/mesa/drivers/dri/i965/brw_fs.h | 1 + > src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 135 > ++++++++++++++++++++++++++- > 2 files changed, 134 insertions(+), 2 deletions(-) > > diff --git a/src/mesa/drivers/dri/i965/brw_fs.h > b/src/mesa/drivers/dri/i965/brw_fs.h > index 48f1069..0bb328a 100644 > --- a/src/mesa/drivers/dri/i965/brw_fs.h > +++ b/src/mesa/drivers/dri/i965/brw_fs.h > @@ -390,6 +390,7 @@ public: > const fs_reg &src0, const fs_reg &src1); > bool try_emit_saturate(ir_expression *ir); > bool try_emit_mad(ir_expression *ir); > + void emit_interpolate_expression(ir_expression *ir);
Seems like a weird place to list the prototype, among the peephole functions. > void try_replace_with_sel(); > bool opt_peephole_sel(); > bool opt_peephole_predicated_break(); > diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp > b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp > index 8e8affa..2f37986 100644 > --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp > +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp > @@ -344,6 +344,118 @@ fs_visitor::try_emit_mad(ir_expression *ir) > return true; > } > > +static int > +pack_pixel_offset(float x) > +{ > + int n = MIN2((int)(x * 16), 7); > + return n & 0xf; > +} > + > +void > +fs_visitor::emit_interpolate_expression(ir_expression *ir) > +{ > + /* in SIMD16 mode, the pixel interpolator returns coords interleaved > + * 8 channels at a time, same as the barycentric coords presented in > + * the FS payload. this requires a bit of extra work to support. > + */ > + no16("interpolate_at_* not yet supported in SIMD16 mode."); > + > + ir_dereference * deref = ir->operands[0]->as_dereference(); > + ir_swizzle * swiz = NULL; > + if (!deref) { > + /* the api does not allow a swizzle here, but the varying packing code > + * may have pushed one into here. > + */ > + swiz = ir->operands[0]->as_swizzle(); > + assert(swiz); > + deref = swiz->val->as_dereference(); > + } > + assert(deref); > + ir_variable * var = deref->variable_referenced(); > + assert(var); > + > + /* 1. collect interpolation factors */ > + > + fs_reg dst_x = fs_reg(this, glsl_type::get_instance(ir->type->base_type, > 2, 1)); > + fs_reg dst_y = dst_x; > + dst_y.reg_offset++; > + > + /* for most messages, we need one reg of ignored data; the hardware > requires mlen==1 > + * even when there is no payload. in the per-slot offset case, we'll > replace this with > + * the proper source data. */ > + fs_reg src = fs_reg(this, glsl_type::float_type); > + int mlen = 1; /* one reg unless overriden */ > + int msg_type = 0; /* message type to be packed into the descriptor */ > + int imm_data = 0; /* data to be packed into the message descriptor */ > + > + switch (ir->operation) { > + case ir_unop_interpolate_at_centroid: > + { > + msg_type = GEN7_PIXEL_INTERPOLATOR_LOC_CENTROID; > + } break; > + > + case ir_binop_interpolate_at_sample: > + { > + ir_constant *sample_num = ir->operands[1]->as_constant(); > + assert(sample_num || !"nonconstant sample number should have been > lowered."); > + > + msg_type = GEN7_PIXEL_INTERPOLATOR_LOC_SAMPLE; > + imm_data = sample_num->value.i[0] << 4; > + } break; > + > + case ir_binop_interpolate_at_offset: > + { Style. Other places where we need to declare variables in a case, we just put { after the : and the closing brace on its own line, with the break inside. > + ir_constant *const_offset = ir->operands[1]->as_constant(); > + if (const_offset) { > + msg_type = GEN7_PIXEL_INTERPOLATOR_LOC_SHARED_OFFSET; > + imm_data = pack_pixel_offset(const_offset->value.f[0]) | > + (pack_pixel_offset(const_offset->value.f[1]) << 4); > + } else { > + /* pack the operands: hw wants offsets as 4 bit signed ints */ > + ir->operands[1]->accept(this); > + src = fs_reg(this, glsl_type::ivec2_type); > + fs_reg src2 = src; > + for (int i = 0; i < 2; i++) { > + fs_reg temp = fs_reg(this, glsl_type::float_type); > + emit(MUL(temp, this->result, fs_reg(16.0f))); > + emit(MOV(src2, temp)); /* float to int */ > + fs_inst *inst = emit(BRW_OPCODE_SEL, src2, src2, fs_reg(7)); > + inst->conditional_mod = BRW_CONDITIONAL_L; /* min(src2, 7) */ > + > + src2.reg_offset++; > + this->result.reg_offset++; > + } > + > + mlen = 2 * dispatch_width / 8; > + msg_type = GEN7_PIXEL_INTERPOLATOR_LOC_PER_SLOT_OFFSET; > + } > + } break; > + > + default: > + unreachable("not reached"); > + } > + > + fs_inst *inst = emit(FS_OPCODE_PIXEL_INTERPOLATOR_QUERY, dst_x, src); > + inst->mlen = mlen; > + inst->regs_written = 2 * dispatch_width / 8; /* 2 floats per slot > returned */ > + inst->pi_noperspective = > var->determine_interpolation_mode(key->flat_shade) == > INTERP_QUALIFIER_NOPERSPECTIVE; > + inst->pi_msg_type = msg_type; > + inst->pi_msg_data = imm_data; > + > + /* 2. emit linterp */ > + > + fs_reg res(this, ir->type); > + this->result = res; > + > + for (int i = 0; i < ir->type->vector_elements; i++) { > + int ch = swiz ? ((*(int *)&swiz->mask) >> 2*i) & 3 : i; > + emit(FS_OPCODE_LINTERP, res, > + dst_x, dst_y, > + fs_reg(interp_reg(var->data.location, ch))); > + res.reg_offset++; > + } > +} > + > void > fs_visitor::visit(ir_expression *ir) > { > @@ -355,9 +467,22 @@ fs_visitor::visit(ir_expression *ir) > > if (try_emit_saturate(ir)) > return; > - if (ir->operation == ir_binop_add) { > + > + /* Deal with the real oddball stuff first */ > + switch (ir->operation) { > + case ir_binop_add: > if (try_emit_mad(ir)) > - return; > + return; > + break; > + > + case ir_unop_interpolate_at_centroid: > + case ir_binop_interpolate_at_offset: > + case ir_binop_interpolate_at_sample: > + emit_interpolate_expression(ir); > + return; > + > + default: > + break; > } > > for (operand = 0; operand < ir->get_num_operands(); operand++) { > @@ -815,6 +940,12 @@ fs_visitor::visit(ir_expression *ir) > inst = emit(BRW_OPCODE_SEL, this->result, op[1], op[2]); > inst->predicate = BRW_PREDICATE_NORMAL; > break; > + > + case ir_unop_interpolate_at_centroid: > + case ir_binop_interpolate_at_offset: > + case ir_binop_interpolate_at_sample: > + assert(!"not reached; already handled above"); > + break; Use unreachable() here. _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev