X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_fs_visitor.cpp;h=ce7075f7940c879c764ff8143b7c94dd33ca8548;hb=c5030ac0ac15d3c91c4352789f94281da9a9dcad;hp=97776c8618966f375f96c797bec0e94e8e036322;hpb=bc9d3a02540e11b863a1f7e7cf755764a02233fe;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 97776c86189..ce7075f7940 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -56,7 +56,7 @@ fs_visitor::visit(ir_variable *ir) if (variable_storage(ir)) return; - if (ir->mode == ir_var_shader_in) { + if (ir->data.mode == ir_var_shader_in) { if (!strcmp(ir->name, "gl_FragCoord")) { reg = emit_fragcoord_interpolation(ir); } else if (!strcmp(ir->name, "gl_FrontFacing")) { @@ -67,27 +67,28 @@ fs_visitor::visit(ir_variable *ir) assert(reg); hash_table_insert(this->variable_ht, reg, ir); return; - } else if (ir->mode == ir_var_shader_out) { + } else if (ir->data.mode == ir_var_shader_out) { reg = new(this->mem_ctx) fs_reg(this, ir->type); - if (ir->index > 0) { - assert(ir->location == FRAG_RESULT_DATA0); - assert(ir->index == 1); + if (ir->data.index > 0) { + assert(ir->data.location == FRAG_RESULT_DATA0); + assert(ir->data.index == 1); this->dual_src_output = *reg; - } else if (ir->location == FRAG_RESULT_COLOR) { + this->do_dual_src = true; + } else if (ir->data.location == FRAG_RESULT_COLOR) { /* Writing gl_FragColor outputs to all color regions. */ - for (unsigned int i = 0; i < MAX2(c->key.nr_color_regions, 1); i++) { + for (unsigned int i = 0; i < MAX2(key->nr_color_regions, 1); i++) { this->outputs[i] = *reg; this->output_components[i] = 4; } - } else if (ir->location == FRAG_RESULT_DEPTH) { + } else if (ir->data.location == FRAG_RESULT_DEPTH) { this->frag_depth = *reg; - } else if (ir->location == FRAG_RESULT_SAMPLE_MASK) { + } else if (ir->data.location == FRAG_RESULT_SAMPLE_MASK) { this->sample_mask = *reg; } else { /* gl_FragData or a user-defined FS output */ - assert(ir->location >= FRAG_RESULT_DATA0 && - ir->location < FRAG_RESULT_DATA0 + BRW_MAX_DRAW_BUFFERS); + assert(ir->data.location >= FRAG_RESULT_DATA0 && + ir->data.location < FRAG_RESULT_DATA0 + BRW_MAX_DRAW_BUFFERS); int vector_elements = ir->type->is_array() ? ir->type->fields.array->vector_elements @@ -95,14 +96,14 @@ fs_visitor::visit(ir_variable *ir) /* General color output. */ for (unsigned int i = 0; i < MAX2(1, ir->type->length); i++) { - int output = ir->location - FRAG_RESULT_DATA0 + i; + int output = ir->data.location - FRAG_RESULT_DATA0 + i; this->outputs[output] = *reg; this->outputs[output].reg_offset += vector_elements * i; this->output_components[output] = vector_elements; } } - } else if (ir->mode == ir_var_uniform) { - int param_index = c->prog_data.nr_params; + } else if (ir->data.mode == ir_var_uniform) { + int param_index = uniforms; /* Thanks to the lower_ubo_reference pass, we will see only * ir_binop_ubo_load expressions and not ir_dereference_variable for UBO @@ -116,7 +117,7 @@ fs_visitor::visit(ir_variable *ir) if (dispatch_width == 16) { if (!variable_storage(ir)) { - fail("Failed to find uniform '%s' in 16-wide\n", ir->name); + fail("Failed to find uniform '%s' in SIMD16\n", ir->name); } return; } @@ -131,11 +132,16 @@ fs_visitor::visit(ir_variable *ir) reg = new(this->mem_ctx) fs_reg(UNIFORM, param_index); reg->type = brw_type_for_base_type(ir->type); - } else if (ir->mode == ir_var_system_value) { - if (ir->location == SYSTEM_VALUE_SAMPLE_POS) { + } else if (ir->data.mode == ir_var_system_value) { + if (ir->data.location == SYSTEM_VALUE_SAMPLE_POS) { reg = emit_samplepos_setup(ir); - } else if (ir->location == SYSTEM_VALUE_SAMPLE_ID) { + } else if (ir->data.location == SYSTEM_VALUE_SAMPLE_ID) { reg = emit_sampleid_setup(ir); + } else if (ir->data.location == SYSTEM_VALUE_SAMPLE_MASK_IN) { + assert(brw->gen >= 7); + reg = new(mem_ctx) + fs_reg(retype(brw_vec8_grf(payload.sample_mask_in_reg, 0), + BRW_REGISTER_TYPE_D)); } } @@ -149,6 +155,12 @@ void fs_visitor::visit(ir_dereference_variable *ir) { fs_reg *reg = variable_storage(ir->var); + + if (!reg) { + fail("Failed to find variable storage for %s\n", ir->var->name); + this->result = fs_reg(reg_null_d); + return; + } this->result = *reg; } @@ -183,7 +195,7 @@ fs_visitor::visit(ir_dereference_array *ir) src.type = brw_type_for_base_type(ir->type); if (constant_index) { - assert(src.file == UNIFORM || src.file == GRF); + assert(src.file == UNIFORM || src.file == GRF || src.file == HW_REG); src.reg_offset += constant_index->value.i[0] * element_size; } else { /* Variable index array dereference. We attach the variable index @@ -210,7 +222,8 @@ fs_visitor::visit(ir_dereference_array *ir) } void -fs_visitor::emit_lrp(fs_reg dst, fs_reg x, fs_reg y, fs_reg a) +fs_visitor::emit_lrp(const fs_reg &dst, const fs_reg &x, const fs_reg &y, + const fs_reg &a) { if (brw->gen < 6 || !x.is_valid_3src() || @@ -223,8 +236,9 @@ fs_visitor::emit_lrp(fs_reg dst, fs_reg x, fs_reg y, fs_reg a) emit(MUL(y_times_a, y, a)); - a.negate = !a.negate; - emit(ADD(one_minus_a, a, fs_reg(1.0f))); + fs_reg negative_a = a; + negative_a.negate = !a.negate; + emit(ADD(one_minus_a, negative_a, fs_reg(1.0f))); emit(MUL(x_times_one_minus_a, x, one_minus_a)); emit(ADD(dst, x_times_one_minus_a, y_times_a)); @@ -237,8 +251,8 @@ fs_visitor::emit_lrp(fs_reg dst, fs_reg x, fs_reg y, fs_reg a) } void -fs_visitor::emit_minmax(uint32_t conditionalmod, fs_reg dst, - fs_reg src0, fs_reg src1) +fs_visitor::emit_minmax(uint32_t conditionalmod, const fs_reg &dst, + const fs_reg &src0, const fs_reg &src1) { fs_inst *inst; @@ -289,7 +303,7 @@ fs_visitor::try_emit_saturate(ir_expression *ir) } bool -fs_visitor::try_emit_mad(ir_expression *ir, int mul_arg) +fs_visitor::try_emit_mad(ir_expression *ir) { /* 3-src instructions were introduced in gen6. */ if (brw->gen < 6) @@ -299,11 +313,16 @@ fs_visitor::try_emit_mad(ir_expression *ir, int mul_arg) if (ir->type != glsl_type::float_type) return false; - ir_rvalue *nonmul = ir->operands[1 - mul_arg]; - ir_expression *mul = ir->operands[mul_arg]->as_expression(); + ir_rvalue *nonmul = ir->operands[1]; + ir_expression *mul = ir->operands[0]->as_expression(); - if (!mul || mul->operation != ir_binop_mul) - return false; + if (!mul || mul->operation != ir_binop_mul) { + nonmul = ir->operands[0]; + mul = ir->operands[1]->as_expression(); + + if (!mul || mul->operation != ir_binop_mul) + return false; + } if (nonmul->as_constant() || mul->operands[0]->as_constant() || @@ -337,7 +356,7 @@ fs_visitor::visit(ir_expression *ir) if (try_emit_saturate(ir)) return; if (ir->operation == ir_binop_add) { - if (try_emit_mad(ir, 0) || try_emit_mad(ir, 1)) + if (try_emit_mad(ir)) return; } @@ -345,8 +364,8 @@ fs_visitor::visit(ir_expression *ir) ir->operands[operand]->accept(this); if (this->result.file == BAD_FILE) { fail("Failed to get tree for expression operand:\n"); - ir->operands[operand]->print(); - printf("\n"); + ir->operands[operand]->fprint(stderr); + fprintf(stderr, "\n"); } assert(this->result.is_valid_3src()); op[operand] = this->result; @@ -382,18 +401,34 @@ fs_visitor::visit(ir_expression *ir) emit(MOV(this->result, op[0])); break; case ir_unop_sign: - temp = fs_reg(this, ir->type); + if (ir->type->is_float()) { + /* AND(val, 0x80000000) gives the sign bit. + * + * Predicated OR ORs 1.0 (0x3f800000) with the sign bit if val is not + * zero. + */ + emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_NZ)); - emit(MOV(this->result, fs_reg(0.0f))); + op[0].type = BRW_REGISTER_TYPE_UD; + this->result.type = BRW_REGISTER_TYPE_UD; + emit(AND(this->result, op[0], fs_reg(0x80000000u))); - emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_G)); - inst = emit(MOV(this->result, fs_reg(1.0f))); - inst->predicate = BRW_PREDICATE_NORMAL; + inst = emit(OR(this->result, this->result, fs_reg(0x3f800000u))); + inst->predicate = BRW_PREDICATE_NORMAL; - emit(CMP(reg_null_f, op[0], fs_reg(0.0f), BRW_CONDITIONAL_L)); - inst = emit(MOV(this->result, fs_reg(-1.0f))); - inst->predicate = BRW_PREDICATE_NORMAL; + this->result.type = BRW_REGISTER_TYPE_F; + } else { + /* ASR(val, 31) -> negative val generates 0xffffffff (signed -1). + * -> non-negative val generates 0x00000000. + * Predicated OR sets 1 if val is positive. + */ + emit(CMP(reg_null_d, op[0], fs_reg(0), BRW_CONDITIONAL_G)); + emit(ASR(this->result, op[0], fs_reg(31))); + + inst = emit(OR(this->result, this->result, fs_reg(1))); + inst->predicate = BRW_PREDICATE_NORMAL; + } break; case ir_unop_rcp: emit_math(SHADER_OPCODE_RCP, this->result, op[0]); @@ -438,25 +473,34 @@ fs_visitor::visit(ir_expression *ir) * of one of the operands (src0 on gen6, src1 on gen7). The * MACH accumulates in the contribution of the upper 16 bits * of that operand. - * - * FINISHME: Emit just the MUL if we know an operand is small - * enough. - */ - if (brw->gen >= 7 && dispatch_width == 16) - fail("16-wide explicit accumulator operands unsupported\n"); - - struct brw_reg acc = retype(brw_acc_reg(), this->result.type); - - emit(MUL(acc, op[0], op[1])); - emit(MACH(reg_null_d, op[0], op[1])); - emit(MOV(this->result, fs_reg(acc))); + */ + if (ir->operands[0]->is_uint16_constant()) { + if (brw->gen < 7) + emit(MUL(this->result, op[0], op[1])); + else + emit(MUL(this->result, op[1], op[0])); + } else if (ir->operands[1]->is_uint16_constant()) { + if (brw->gen < 7) + emit(MUL(this->result, op[1], op[0])); + else + emit(MUL(this->result, op[0], op[1])); + } else { + if (brw->gen >= 7) + no16("SIMD16 explicit accumulator operands unsupported\n"); + + struct brw_reg acc = retype(brw_acc_reg(), this->result.type); + + emit(MUL(acc, op[0], op[1])); + emit(MACH(reg_null_d, op[0], op[1])); + emit(MOV(this->result, fs_reg(acc))); + } } else { emit(MUL(this->result, op[0], op[1])); } break; case ir_binop_imul_high: { - if (brw->gen >= 7 && dispatch_width == 16) - fail("16-wide explicit accumulator operands unsupported\n"); + if (brw->gen >= 7) + no16("SIMD16 explicit accumulator operands unsupported\n"); struct brw_reg acc = retype(brw_acc_reg(), this->result.type); @@ -470,8 +514,8 @@ fs_visitor::visit(ir_expression *ir) emit_math(SHADER_OPCODE_INT_QUOTIENT, this->result, op[0], op[1]); break; case ir_binop_carry: { - if (brw->gen >= 7 && dispatch_width == 16) - fail("16-wide explicit accumulator operands unsupported\n"); + if (brw->gen >= 7) + no16("SIMD16 explicit accumulator operands unsupported\n"); struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD); @@ -480,8 +524,8 @@ fs_visitor::visit(ir_expression *ir) break; } case ir_binop_borrow: { - if (brw->gen >= 7 && dispatch_width == 16) - fail("16-wide explicit accumulator operands unsupported\n"); + if (brw->gen >= 7) + no16("SIMD16 explicit accumulator operands unsupported\n"); struct brw_reg acc = retype(brw_acc_reg(), BRW_REGISTER_TYPE_UD); @@ -716,18 +760,24 @@ fs_visitor::visit(ir_expression *ir) */ ir_constant *uniform_block = ir->operands[0]->as_constant(); ir_constant *const_offset = ir->operands[1]->as_constant(); - fs_reg surf_index = fs_reg(c->prog_data.base.binding_table.ubo_start + + fs_reg surf_index = fs_reg(prog_data->base.binding_table.ubo_start + uniform_block->value.u[0]); if (const_offset) { fs_reg packed_consts = fs_reg(this, glsl_type::float_type); packed_consts.type = result.type; fs_reg const_offset_reg = fs_reg(const_offset->value.u[0] & ~15); - emit(fs_inst(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, - packed_consts, surf_index, const_offset_reg)); + emit(new(mem_ctx) fs_inst(FS_OPCODE_UNIFORM_PULL_CONSTANT_LOAD, + packed_consts, surf_index, const_offset_reg)); - packed_consts.smear = const_offset->value.u[0] % 16 / 4; for (int i = 0; i < ir->type->vector_elements; i++) { + packed_consts.set_smear(const_offset->value.u[0] % 16 / 4 + i); + + /* The std140 packing rules don't allow vectors to cross 16-byte + * boundaries, and a reg is 32 bytes. + */ + assert(packed_consts.subreg_offset < 32); + /* UBO bools are any nonzero value. We consider bools to be * values with the low bit set to 1. Convert them using CMP. */ @@ -737,13 +787,7 @@ fs_visitor::visit(ir_expression *ir) emit(MOV(result, packed_consts)); } - packed_consts.smear++; result.reg_offset++; - - /* The std140 packing rules don't allow vectors to cross 16-byte - * boundaries, and a reg is 32 bytes. - */ - assert(packed_consts.smear < 8); } } else { /* Turn the byte offset into a dword offset. */ @@ -820,6 +864,7 @@ fs_visitor::emit_assignment_writes(fs_reg &l, fs_reg &r, break; case GLSL_TYPE_SAMPLER: + case GLSL_TYPE_IMAGE: case GLSL_TYPE_ATOMIC_UINT: break; @@ -1050,22 +1095,22 @@ fs_visitor::emit_texture_gen4(ir_texture *ir, fs_reg dst, fs_reg coordinate, fs_inst *inst = NULL; switch (ir->op) { case ir_tex: - inst = emit(SHADER_OPCODE_TEX, dst); + inst = emit(SHADER_OPCODE_TEX, dst, reg_undef); break; case ir_txb: - inst = emit(FS_OPCODE_TXB, dst); + inst = emit(FS_OPCODE_TXB, dst, reg_undef); break; case ir_txl: - inst = emit(SHADER_OPCODE_TXL, dst); + inst = emit(SHADER_OPCODE_TXL, dst, reg_undef); break; case ir_txd: - inst = emit(SHADER_OPCODE_TXD, dst); + inst = emit(SHADER_OPCODE_TXD, dst, reg_undef); break; case ir_txs: - inst = emit(SHADER_OPCODE_TXS, dst); + inst = emit(SHADER_OPCODE_TXS, dst, reg_undef); break; case ir_txf: - inst = emit(SHADER_OPCODE_TXF, dst); + inst = emit(SHADER_OPCODE_TXF, dst, reg_undef); break; default: fail("unrecognized texture opcode"); @@ -1132,21 +1177,21 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, fs_inst *inst = NULL; switch (ir->op) { case ir_tex: - inst = emit(SHADER_OPCODE_TEX, dst); + inst = emit(SHADER_OPCODE_TEX, dst, reg_undef); break; case ir_txb: mlen = MAX2(mlen, header_present + 4 * reg_width); emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); mlen += reg_width; - inst = emit(FS_OPCODE_TXB, dst); + inst = emit(FS_OPCODE_TXB, dst, reg_undef); break; case ir_txl: mlen = MAX2(mlen, header_present + 4 * reg_width); emit(MOV(fs_reg(MRF, base_mrf + mlen), lod)); mlen += reg_width; - inst = emit(SHADER_OPCODE_TXL, dst); + inst = emit(SHADER_OPCODE_TXL, dst, reg_undef); break; case ir_txd: { mlen = MAX2(mlen, header_present + 4 * reg_width); /* skip over 'ai' */ @@ -1176,17 +1221,17 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, case ir_txs: emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), lod)); mlen += reg_width; - inst = emit(SHADER_OPCODE_TXS, dst); + inst = emit(SHADER_OPCODE_TXS, dst, reg_undef); break; case ir_query_levels: emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), fs_reg(0u))); mlen += reg_width; - inst = emit(SHADER_OPCODE_TXS, dst); + inst = emit(SHADER_OPCODE_TXS, dst, reg_undef); break; case ir_txf: mlen = header_present + 4 * reg_width; emit(MOV(fs_reg(MRF, base_mrf + mlen - reg_width, BRW_REGISTER_TYPE_UD), lod)); - inst = emit(SHADER_OPCODE_TXF, dst); + inst = emit(SHADER_OPCODE_TXF, dst, reg_undef); break; case ir_txf_ms: mlen = header_present + 4 * reg_width; @@ -1196,13 +1241,13 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, /* sample index */ emit(MOV(fs_reg(MRF, base_mrf + mlen, BRW_REGISTER_TYPE_UD), sample_index)); mlen += reg_width; - inst = emit(SHADER_OPCODE_TXF_MS, dst); + inst = emit(SHADER_OPCODE_TXF_CMS, dst, reg_undef); break; case ir_lod: - inst = emit(SHADER_OPCODE_LOD, dst); + inst = emit(SHADER_OPCODE_LOD, dst, reg_undef); break; case ir_tg4: - inst = emit(SHADER_OPCODE_TG4, dst); + inst = emit(SHADER_OPCODE_TG4, dst, reg_undef); break; default: fail("unrecognized texture opcode"); @@ -1213,8 +1258,9 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, inst->header_present = header_present; inst->regs_written = 4; - if (mlen > 11) { - fail("Message length >11 disallowed by hardware\n"); + if (mlen > MAX_SAMPLER_MESSAGE_SIZE) { + fail("Message length >" STRINGIFY(MAX_SAMPLER_MESSAGE_SIZE) + " disallowed by hardware\n"); } return inst; @@ -1223,29 +1269,36 @@ fs_visitor::emit_texture_gen5(ir_texture *ir, fs_reg dst, fs_reg coordinate, fs_inst * fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, fs_reg shadow_c, fs_reg lod, fs_reg lod2, - fs_reg sample_index) + fs_reg sample_index, fs_reg mcs, int sampler) { int reg_width = dispatch_width / 8; bool header_present = false; - fs_reg payload = fs_reg(this, glsl_type::float_type); - fs_reg next = payload; + fs_reg *sources = ralloc_array(mem_ctx, fs_reg, MAX_SAMPLER_MESSAGE_SIZE); + for (int i = 0; i < MAX_SAMPLER_MESSAGE_SIZE; i++) { + sources[i] = fs_reg(this, glsl_type::float_type); + } + int length = 0; - if (ir->op == ir_tg4 || (ir->offset && ir->op != ir_txf)) { + if (ir->op == ir_tg4 || (ir->offset && ir->op != ir_txf) || sampler >= 16) { /* For general texture offsets (no txf workaround), we need a header to - * put them in. Note that for 16-wide we're making space for two actual + * put them in. Note that for SIMD16 we're making space for two actual * hardware registers here, so the emit will have to fix up for this. * * * ir4_tg4 needs to place its channel select in the header, * for interaction with ARB_texture_swizzle + * + * The sampler index is only 4-bits, so for larger sampler numbers we + * need to offset the Sampler State Pointer in the header. */ header_present = true; - next.reg_offset++; + sources[length] = reg_undef; + length++; } if (ir->shadow_comparitor) { - emit(MOV(next, shadow_c)); - next.reg_offset++; + emit(MOV(sources[length], shadow_c)); + length++; } bool has_nonconstant_offset = ir->offset && !ir->offset->as_constant(); @@ -1257,36 +1310,35 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, case ir_lod: break; case ir_txb: - emit(MOV(next, lod)); - next.reg_offset++; + emit(MOV(sources[length], lod)); + length++; break; case ir_txl: - emit(MOV(next, lod)); - next.reg_offset++; + emit(MOV(sources[length], lod)); + length++; break; case ir_txd: { - if (dispatch_width == 16) - fail("Gen7 does not support sample_d/sample_d_c in SIMD16 mode."); + no16("Gen7 does not support sample_d/sample_d_c in SIMD16 mode."); /* Load dPdx and the coordinate together: * [hdr], [ref], x, dPdx.x, dPdy.x, y, dPdx.y, dPdy.y, z, dPdx.z, dPdy.z */ for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { - emit(MOV(next, coordinate)); + emit(MOV(sources[length], coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; /* For cube map array, the coordinate is (u,v,r,ai) but there are * only derivatives for (u, v, r). */ if (i < ir->lod_info.grad.dPdx->type->vector_elements) { - emit(MOV(next, lod)); + emit(MOV(sources[length], lod)); lod.reg_offset++; - next.reg_offset++; + length++; - emit(MOV(next, lod2)); + emit(MOV(sources[length], lod2)); lod2.reg_offset++; - next.reg_offset++; + length++; } } @@ -1294,77 +1346,74 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, break; } case ir_txs: - emit(MOV(next.retype(BRW_REGISTER_TYPE_UD), lod)); - next.reg_offset++; + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_UD), lod)); + length++; break; case ir_query_levels: - emit(MOV(next.retype(BRW_REGISTER_TYPE_UD), fs_reg(0u))); - next.reg_offset++; + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_UD), fs_reg(0u))); + length++; break; case ir_txf: /* Unfortunately, the parameters for LD are intermixed: u, lod, v, r. */ - emit(MOV(next.retype(BRW_REGISTER_TYPE_D), coordinate)); + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_D), coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; - emit(MOV(next.retype(BRW_REGISTER_TYPE_D), lod)); - next.reg_offset++; + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_D), lod)); + length++; for (int i = 1; i < ir->coordinate->type->vector_elements; i++) { - emit(MOV(next.retype(BRW_REGISTER_TYPE_D), coordinate)); + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_D), coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; } coordinate_done = true; break; case ir_txf_ms: - emit(MOV(next.retype(BRW_REGISTER_TYPE_UD), sample_index)); - next.reg_offset++; + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_UD), sample_index)); + length++; - /* constant zero MCS; we arrange to never actually have a compressed - * multisample surface here for now. TODO: issue ld_mcs to get this first, - * if we ever support texturing from compressed multisample surfaces - */ - emit(MOV(next.retype(BRW_REGISTER_TYPE_UD), fs_reg(0u))); - next.reg_offset++; + /* data from the multisample control surface */ + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_UD), mcs)); + length++; /* there is no offsetting for this message; just copy in the integer * texture coordinates */ for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { - emit(MOV(next.retype(BRW_REGISTER_TYPE_D), coordinate)); + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_D), coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; } coordinate_done = true; break; case ir_tg4: if (has_nonconstant_offset) { - if (ir->shadow_comparitor && dispatch_width == 16) - fail("Gen7 does not support gather4_po_c in SIMD16 mode."); + if (ir->shadow_comparitor) + no16("Gen7 does not support gather4_po_c in SIMD16 mode."); /* More crazy intermixing */ ir->offset->accept(this); fs_reg offset_value = this->result; for (int i = 0; i < 2; i++) { /* u, v */ - emit(MOV(next, coordinate)); + emit(MOV(sources[length], coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; } for (int i = 0; i < 2; i++) { /* offu, offv */ - emit(MOV(next.retype(BRW_REGISTER_TYPE_D), offset_value)); + emit(MOV(retype(sources[length], BRW_REGISTER_TYPE_D), offset_value)); offset_value.reg_offset++; - next.reg_offset++; + length++; } if (ir->coordinate->type->vector_elements == 3) { /* r if present */ - emit(MOV(next, coordinate)); + emit(MOV(sources[length], coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; } coordinate_done = true; @@ -1375,42 +1424,47 @@ fs_visitor::emit_texture_gen7(ir_texture *ir, fs_reg dst, fs_reg coordinate, /* Set up the coordinate (except for cases where it was done above) */ if (ir->coordinate && !coordinate_done) { for (int i = 0; i < ir->coordinate->type->vector_elements; i++) { - emit(MOV(next, coordinate)); + emit(MOV(sources[length], coordinate)); coordinate.reg_offset++; - next.reg_offset++; + length++; } } + fs_reg src_payload = fs_reg(GRF, virtual_grf_alloc(length), + BRW_REGISTER_TYPE_F); + emit(LOAD_PAYLOAD(src_payload, sources, length)); + /* Generate the SEND */ - fs_inst *inst = NULL; + enum opcode opcode; switch (ir->op) { - case ir_tex: inst = emit(SHADER_OPCODE_TEX, dst, payload); break; - case ir_txb: inst = emit(FS_OPCODE_TXB, dst, payload); break; - case ir_txl: inst = emit(SHADER_OPCODE_TXL, dst, payload); break; - case ir_txd: inst = emit(SHADER_OPCODE_TXD, dst, payload); break; - case ir_txf: inst = emit(SHADER_OPCODE_TXF, dst, payload); break; - case ir_txf_ms: inst = emit(SHADER_OPCODE_TXF_MS, dst, payload); break; - case ir_txs: inst = emit(SHADER_OPCODE_TXS, dst, payload); break; - case ir_query_levels: inst = emit(SHADER_OPCODE_TXS, dst, payload); break; - case ir_lod: inst = emit(SHADER_OPCODE_LOD, dst, payload); break; + case ir_tex: opcode = SHADER_OPCODE_TEX; break; + case ir_txb: opcode = FS_OPCODE_TXB; break; + case ir_txl: opcode = SHADER_OPCODE_TXL; break; + case ir_txd: opcode = SHADER_OPCODE_TXD; break; + case ir_txf: opcode = SHADER_OPCODE_TXF; break; + case ir_txf_ms: opcode = SHADER_OPCODE_TXF_CMS; break; + case ir_txs: opcode = SHADER_OPCODE_TXS; break; + case ir_query_levels: opcode = SHADER_OPCODE_TXS; break; + case ir_lod: opcode = SHADER_OPCODE_LOD; break; case ir_tg4: if (has_nonconstant_offset) - inst = emit(SHADER_OPCODE_TG4_OFFSET, dst, payload); + opcode = SHADER_OPCODE_TG4_OFFSET; else - inst = emit(SHADER_OPCODE_TG4, dst, payload); + opcode = SHADER_OPCODE_TG4; break; } + fs_inst *inst = emit(opcode, dst, src_payload); inst->base_mrf = -1; if (reg_width == 2) - inst->mlen = next.reg_offset * reg_width - header_present; + inst->mlen = length * reg_width - header_present; else - inst->mlen = next.reg_offset * reg_width; + inst->mlen = length * reg_width; inst->header_present = header_present; inst->regs_written = 4; - virtual_grf_sizes[payload.reg] = next.reg_offset; - if (inst->mlen > 11) { - fail("Message length >11 disallowed by hardware\n"); + if (inst->mlen > MAX_SAMPLER_MESSAGE_SIZE) { + fail("Message length >" STRINGIFY(MAX_SAMPLER_MESSAGE_SIZE) + " disallowed by hardware\n"); } return inst; @@ -1430,8 +1484,8 @@ fs_visitor::rescale_texcoord(ir_texture *ir, fs_reg coordinate, */ if (is_rect && (brw->gen < 6 || - (brw->gen >= 6 && (c->key.tex.gl_clamp_mask[0] & (1 << sampler) || - c->key.tex.gl_clamp_mask[1] & (1 << sampler))))) { + (brw->gen >= 6 && (key->tex.gl_clamp_mask[0] & (1 << sampler) || + key->tex.gl_clamp_mask[1] & (1 << sampler))))) { struct gl_program_parameter_list *params = prog->Parameters; int tokens[STATE_LENGTH] = { STATE_INTERNAL, @@ -1441,20 +1495,33 @@ fs_visitor::rescale_texcoord(ir_texture *ir, fs_reg coordinate, 0 }; + no16("rectangle scale uniform setup not supported on SIMD16\n"); if (dispatch_width == 16) { - fail("rectangle scale uniform setup not supported on 16-wide\n"); return coordinate; } - scale_x = fs_reg(UNIFORM, c->prog_data.nr_params); - scale_y = fs_reg(UNIFORM, c->prog_data.nr_params + 1); - GLuint index = _mesa_add_state_reference(params, (gl_state_index *)tokens); - c->prog_data.param[c->prog_data.nr_params++] = - &prog->Parameters->ParameterValues[index][0].f; - c->prog_data.param[c->prog_data.nr_params++] = - &prog->Parameters->ParameterValues[index][1].f; + /* Try to find existing copies of the texrect scale uniforms. */ + for (unsigned i = 0; i < uniforms; i++) { + if (stage_prog_data->param[i] == + &prog->Parameters->ParameterValues[index][0].f) { + scale_x = fs_reg(UNIFORM, i); + scale_y = fs_reg(UNIFORM, i + 1); + break; + } + } + + /* If we didn't already set them up, do so now. */ + if (scale_x.file == BAD_FILE) { + scale_x = fs_reg(UNIFORM, uniforms); + scale_y = fs_reg(UNIFORM, uniforms + 1); + + stage_prog_data->param[uniforms++] = + &prog->Parameters->ParameterValues[index][0].f; + stage_prog_data->param[uniforms++] = + &prog->Parameters->ParameterValues[index][1].f; + } } /* The 965 requires the EU to do the normalization of GL rectangle @@ -1479,11 +1546,11 @@ fs_visitor::rescale_texcoord(ir_texture *ir, fs_reg coordinate, needs_gl_clamp = false; for (int i = 0; i < 2; i++) { - if (c->key.tex.gl_clamp_mask[i] & (1 << sampler)) { + if (key->tex.gl_clamp_mask[i] & (1 << sampler)) { fs_reg chan = coordinate; chan.reg_offset += i; - inst = emit(BRW_OPCODE_SEL, chan, chan, brw_imm_f(0.0)); + inst = emit(BRW_OPCODE_SEL, chan, chan, fs_reg(0.0f)); inst->conditional_mod = BRW_CONDITIONAL_G; /* Our parameter comes in as 1.0/width or 1.0/height, @@ -1505,7 +1572,7 @@ fs_visitor::rescale_texcoord(ir_texture *ir, fs_reg coordinate, if (ir->coordinate && needs_gl_clamp) { for (unsigned int i = 0; i < MIN2(ir->coordinate->type->vector_elements, 3); i++) { - if (c->key.tex.gl_clamp_mask[i] & (1 << sampler)) { + if (key->tex.gl_clamp_mask[i] & (1 << sampler)) { fs_reg chan = coordinate; chan.reg_offset += i; @@ -1517,6 +1584,38 @@ fs_visitor::rescale_texcoord(ir_texture *ir, fs_reg coordinate, return coordinate; } +/* Sample from the MCS surface attached to this multisample texture. */ +fs_reg +fs_visitor::emit_mcs_fetch(ir_texture *ir, fs_reg coordinate, int sampler) +{ + int reg_width = dispatch_width / 8; + int length = ir->coordinate->type->vector_elements; + fs_reg payload = fs_reg(GRF, virtual_grf_alloc(length), + BRW_REGISTER_TYPE_F); + fs_reg dest = fs_reg(this, glsl_type::uvec4_type); + fs_reg *sources = ralloc_array(mem_ctx, fs_reg, length); + + /* parameters are: u, v, r; missing parameters are treated as zero */ + for (int i = 0; i < length; i++) { + sources[i] = fs_reg(this, glsl_type::float_type); + emit(MOV(retype(sources[i], BRW_REGISTER_TYPE_D), coordinate)); + coordinate.reg_offset++; + } + + emit(LOAD_PAYLOAD(payload, sources, length)); + + fs_inst *inst = emit(SHADER_OPCODE_TXF_MCS, dest, payload); + inst->base_mrf = -1; + inst->mlen = length * reg_width; + inst->header_present = false; + inst->regs_written = 4; /* we only care about one reg of response, + * but the sampler always writes 4/8 + */ + inst->sampler = sampler; + + return dest; +} + void fs_visitor::visit(ir_texture *ir) { @@ -1535,7 +1634,7 @@ fs_visitor::visit(ir_texture *ir) * emitting anything other than setting up the constant result. */ ir_constant *chan = ir->lod_info.component->as_constant(); - int swiz = GET_SWZ(c->key.tex.swizzles[sampler], chan->value.i[0]); + int swiz = GET_SWZ(key->tex.swizzles[sampler], chan->value.i[0]); if (swiz == SWIZZLE_ZERO || swiz == SWIZZLE_ONE) { fs_reg res = fs_reg(this, glsl_type::vec4_type); @@ -1575,7 +1674,7 @@ fs_visitor::visit(ir_texture *ir) shadow_comparitor = this->result; } - fs_reg lod, lod2, sample_index; + fs_reg lod, lod2, sample_index, mcs; switch (ir->op) { case ir_tex: case ir_lod: @@ -1602,6 +1701,11 @@ fs_visitor::visit(ir_texture *ir) case ir_txf_ms: ir->lod_info.sample_index->accept(this); sample_index = this->result; + + if (brw->gen >= 7 && key->tex.compressed_multisample_layout_mask & (1<gen >= 7) { inst = emit_texture_gen7(ir, dst, coordinate, shadow_comparitor, - lod, lod2, sample_index); + lod, lod2, sample_index, mcs, sampler); } else if (brw->gen >= 5) { inst = emit_texture_gen5(ir, dst, coordinate, shadow_comparitor, lod, lod2, sample_index); @@ -1641,13 +1745,60 @@ fs_visitor::visit(ir_texture *ir) type->sampler_array) { fs_reg depth = dst; depth.reg_offset = 2; - emit_math(SHADER_OPCODE_INT_QUOTIENT, depth, depth, fs_reg(6)); + fs_reg fixed_depth = fs_reg(this, glsl_type::int_type); + emit_math(SHADER_OPCODE_INT_QUOTIENT, fixed_depth, depth, fs_reg(6)); + + fs_reg *fixed_payload = ralloc_array(mem_ctx, fs_reg, inst->regs_written); + fs_reg d = dst; + for (int i = 0; i < inst->regs_written; i++) { + if (i == 2) { + fixed_payload[i] = fixed_depth; + } else { + d.reg_offset = i; + fixed_payload[i] = d; + } + } + emit(LOAD_PAYLOAD(dst, fixed_payload, inst->regs_written)); } } + if (brw->gen == 6 && ir->op == ir_tg4) { + emit_gen6_gather_wa(key->tex.gen6_gather_wa[sampler], dst); + } + swizzle_result(ir, dst, sampler); } +/** + * Apply workarounds for Gen6 gather with UINT/SINT + */ +void +fs_visitor::emit_gen6_gather_wa(uint8_t wa, fs_reg dst) +{ + if (!wa) + return; + + int width = (wa & WA_8BIT) ? 8 : 16; + + for (int i = 0; i < 4; i++) { + fs_reg dst_f = retype(dst, BRW_REGISTER_TYPE_F); + /* Convert from UNORM to UINT */ + emit(MUL(dst_f, dst_f, fs_reg((float)((1 << width) - 1)))); + emit(MOV(dst, dst_f)); + + if (wa & WA_SIGN) { + /* Reinterpret the UINT value as a signed INT value by + * shifting the sign bit into place, then shifting back + * preserving sign. + */ + emit(SHL(dst, dst, fs_reg(32 - width))); + emit(ASR(dst, dst, fs_reg(32 - width))); + } + + dst.reg_offset++; + } +} + /** * Set up the gather channel based on the swizzle, for gather4. */ @@ -1655,14 +1806,14 @@ uint32_t fs_visitor::gather_channel(ir_texture *ir, int sampler) { ir_constant *chan = ir->lod_info.component->as_constant(); - int swiz = GET_SWZ(c->key.tex.swizzles[sampler], chan->value.i[0]); + int swiz = GET_SWZ(key->tex.swizzles[sampler], chan->value.i[0]); switch (swiz) { case SWIZZLE_X: return 0; case SWIZZLE_Y: /* gather4 sampler is broken for green channel on RG32F -- * we must ask for blue instead. */ - if (c->key.tex.gather_channel_quirk_mask & (1<tex.gather_channel_quirk_mask & (1<type == glsl_type::float_type) { /* Ignore DEPTH_TEXTURE_MODE swizzling. */ assert(ir->sampler->type->sampler_shadow); - } else if (c->key.tex.swizzles[sampler] != SWIZZLE_NOOP) { + } else if (key->tex.swizzles[sampler] != SWIZZLE_NOOP) { fs_reg swizzled_result = fs_reg(this, glsl_type::vec4_type); for (int i = 0; i < 4; i++) { - int swiz = GET_SWZ(c->key.tex.swizzles[sampler], i); + int swiz = GET_SWZ(key->tex.swizzles[sampler], i); fs_reg l = swizzled_result; l.reg_offset += i; @@ -1712,7 +1863,7 @@ fs_visitor::swizzle_result(ir_texture *ir, fs_reg orig_val, int sampler) emit(MOV(l, fs_reg(1.0f))); } else { fs_reg r = orig_val; - r.reg_offset += GET_SWZ(c->key.tex.swizzles[sampler], i); + r.reg_offset += GET_SWZ(key->tex.swizzles[sampler], i); emit(MOV(l, r)); } } @@ -1819,8 +1970,7 @@ fs_visitor::visit(ir_constant *ir) } } } else if (ir->type->is_record()) { - foreach_list(node, &ir->components) { - ir_constant *const field = (ir_constant *) node; + foreach_in_list(ir_constant, field, &ir->components) { const unsigned size = type_size(field->type); field->accept(this); @@ -2092,8 +2242,8 @@ fs_visitor::try_replace_with_sel() void fs_visitor::visit(ir_if *ir) { - if (brw->gen < 6 && dispatch_width == 16) { - fail("Can't support (non-uniform) control flow on 16-wide\n"); + if (brw->gen < 6) { + no16("Can't support (non-uniform) control flow on SIMD16\n"); } /* Don't point the annotation at the if statement, because then it plus @@ -2109,21 +2259,17 @@ fs_visitor::visit(ir_if *ir) emit(IF(BRW_PREDICATE_NORMAL)); } - foreach_list(node, &ir->then_instructions) { - ir_instruction *ir = (ir_instruction *)node; - this->base_ir = ir; - - ir->accept(this); + foreach_in_list(ir_instruction, ir_, &ir->then_instructions) { + this->base_ir = ir_; + ir_->accept(this); } if (!ir->else_instructions.is_empty()) { emit(BRW_OPCODE_ELSE); - foreach_list(node, &ir->else_instructions) { - ir_instruction *ir = (ir_instruction *)node; - this->base_ir = ir; - - ir->accept(this); + foreach_in_list(ir_instruction, ir_, &ir->else_instructions) { + this->base_ir = ir_; + ir_->accept(this); } } @@ -2135,50 +2281,16 @@ fs_visitor::visit(ir_if *ir) void fs_visitor::visit(ir_loop *ir) { - fs_reg counter = reg_undef; - - if (brw->gen < 6 && dispatch_width == 16) { - fail("Can't support (non-uniform) control flow on 16-wide\n"); - } - - if (ir->counter) { - this->base_ir = ir->counter; - ir->counter->accept(this); - counter = *(variable_storage(ir->counter)); - - if (ir->from) { - this->base_ir = ir->from; - ir->from->accept(this); - - emit(MOV(counter, this->result)); - } + if (brw->gen < 6) { + no16("Can't support (non-uniform) control flow on SIMD16\n"); } this->base_ir = NULL; emit(BRW_OPCODE_DO); - if (ir->to) { - this->base_ir = ir->to; - ir->to->accept(this); - - emit(CMP(reg_null_d, counter, this->result, - brw_conditional_for_comparison(ir->cmp))); - - fs_inst *inst = emit(BRW_OPCODE_BREAK); - inst->predicate = BRW_PREDICATE_NORMAL; - } - - foreach_list(node, &ir->body_instructions) { - ir_instruction *ir = (ir_instruction *)node; - - this->base_ir = ir; - ir->accept(this); - } - - if (ir->increment) { - this->base_ir = ir->increment; - ir->increment->accept(this); - emit(ADD(counter, counter, this->result)); + foreach_in_list(ir_instruction, ir_, &ir->body_instructions) { + this->base_ir = ir_; + ir_->accept(this); } this->base_ir = NULL; @@ -2204,8 +2316,8 @@ fs_visitor::visit_atomic_counter_intrinsic(ir_call *ir) ir_dereference *deref = static_cast( ir->actual_parameters.get_head()); ir_variable *location = deref->variable_referenced(); - unsigned surf_index = (c->prog_data.base.binding_table.abo_start + - location->atomic.buffer_index); + unsigned surf_index = (prog_data->base.binding_table.abo_start + + location->data.atomic.buffer_index); /* Calculate the surface offset */ fs_reg offset(this, glsl_type::uint_type); @@ -2216,9 +2328,9 @@ fs_visitor::visit_atomic_counter_intrinsic(ir_call *ir) fs_reg tmp(this, glsl_type::uint_type); emit(MUL(tmp, this->result, ATOMIC_COUNTER_SIZE)); - emit(ADD(offset, tmp, location->atomic.offset)); + emit(ADD(offset, tmp, location->data.atomic.offset)); } else { - offset = location->atomic.offset; + offset = location->data.atomic.offset; } /* Emit the appropriate machine instruction */ @@ -2273,11 +2385,9 @@ fs_visitor::visit(ir_function *ir) assert(sig); - foreach_list(node, &sig->body) { - ir_instruction *ir = (ir_instruction *)node; - this->base_ir = ir; - - ir->accept(this); + foreach_in_list(ir_instruction, ir_, &sig->body) { + this->base_ir = ir_; + ir_->accept(this); } } } @@ -2310,7 +2420,7 @@ fs_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index, unsigned mlen = 0; /* Initialize the sample mask in the message header. */ - emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0))) + emit(MOV(brw_uvec_mrf(8, mlen, 0), fs_reg(0u))) ->force_writemask_all = true; if (fp->UsesKill) { @@ -2340,9 +2450,11 @@ fs_visitor::emit_untyped_atomic(unsigned atomic_op, unsigned surf_index, } /* Emit the instruction. */ - fs_inst inst(SHADER_OPCODE_UNTYPED_ATOMIC, dst, atomic_op, surf_index); - inst.base_mrf = 0; - inst.mlen = mlen; + fs_inst *inst = new(mem_ctx) fs_inst(SHADER_OPCODE_UNTYPED_ATOMIC, dst, + atomic_op, surf_index); + inst->base_mrf = 0; + inst->mlen = mlen; + inst->header_present = true; emit(inst); } @@ -2354,7 +2466,7 @@ fs_visitor::emit_untyped_surface_read(unsigned surf_index, fs_reg dst, unsigned mlen = 0; /* Initialize the sample mask in the message header. */ - emit(MOV(brw_uvec_mrf(8, mlen, 0), brw_imm_ud(0))) + emit(MOV(brw_uvec_mrf(8, mlen, 0), fs_reg(0u))) ->force_writemask_all = true; if (fp->UsesKill) { @@ -2373,21 +2485,14 @@ fs_visitor::emit_untyped_surface_read(unsigned surf_index, fs_reg dst, mlen += operand_len; /* Emit the instruction. */ - fs_inst inst(SHADER_OPCODE_UNTYPED_SURFACE_READ, dst, surf_index); - inst.base_mrf = 0; - inst.mlen = mlen; + fs_inst *inst = new(mem_ctx) + fs_inst(SHADER_OPCODE_UNTYPED_SURFACE_READ, dst, surf_index); + inst->base_mrf = 0; + inst->mlen = mlen; + inst->header_present = true; emit(inst); } -fs_inst * -fs_visitor::emit(fs_inst inst) -{ - fs_inst *list_inst = new(mem_ctx) fs_inst; - *list_inst = inst; - emit(list_inst); - return list_inst; -} - fs_inst * fs_visitor::emit(fs_inst *inst) { @@ -2438,10 +2543,10 @@ fs_visitor::emit_dummy_fs() struct brw_reg fs_visitor::interp_reg(int location, int channel) { - int regnr = c->prog_data.urb_setup[location] * 2 + channel / 2; + int regnr = prog_data->urb_setup[location] * 2 + channel / 2; int stride = (channel & 1) * 4; - assert(c->prog_data.urb_setup[location] != -1); + assert(prog_data->urb_setup[location] != -1); return brw_vec1_grf(regnr, stride); } @@ -2521,12 +2626,12 @@ fs_visitor::emit_interpolation_setup_gen6() emit(MOV(this->pixel_y, int_pixel_y)); this->current_annotation = "compute pos.w"; - this->pixel_w = fs_reg(brw_vec8_grf(c->source_w_reg, 0)); + this->pixel_w = fs_reg(brw_vec8_grf(payload.source_w_reg, 0)); this->wpos_w = fs_reg(this, glsl_type::float_type); emit_math(SHADER_OPCODE_RCP, this->wpos_w, this->pixel_w); for (int i = 0; i < BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT; ++i) { - uint8_t reg = c->barycentric_coord_reg[i]; + uint8_t reg = payload.barycentric_coord_reg[i]; this->delta_x[i] = fs_reg(brw_vec8_grf(reg, 0)); this->delta_y[i] = fs_reg(brw_vec8_grf(reg + 1, 0)); } @@ -2568,7 +2673,7 @@ fs_visitor::emit_color_write(int target, int index, int first_color_mrf) inst = emit(MOV(fs_reg(MRF, first_color_mrf + index * reg_width, color.type), color)); - inst->saturate = c->key.clamp_fragment_color; + inst->saturate = key->clamp_fragment_color; } else { /* pre-gen6 SIMD16 single source DP write looks like: * m + 0: r0 @@ -2589,20 +2694,18 @@ fs_visitor::emit_color_write(int target, int index, int first_color_mrf) inst = emit(MOV(fs_reg(MRF, BRW_MRF_COMPR4 + first_color_mrf + index, color.type), color)); - inst->saturate = c->key.clamp_fragment_color; + inst->saturate = key->clamp_fragment_color; } else { push_force_uncompressed(); inst = emit(MOV(fs_reg(MRF, first_color_mrf + index, color.type), color)); - inst->saturate = c->key.clamp_fragment_color; + inst->saturate = key->clamp_fragment_color; pop_force_uncompressed(); - color.sechalf = true; inst = emit(MOV(fs_reg(MRF, first_color_mrf + index + 4, color.type), - color)); + half(color, 1))); inst->force_sechalf = true; - inst->saturate = c->key.clamp_fragment_color; - color.sechalf = false; + inst->saturate = key->clamp_fragment_color; } } } @@ -2639,10 +2742,10 @@ fs_visitor::emit_alpha_test() this->current_annotation = "Alpha test"; fs_inst *cmp; - if (c->key.alpha_test_func == GL_ALWAYS) + if (key->alpha_test_func == GL_ALWAYS) return; - if (c->key.alpha_test_func == GL_NEVER) { + if (key->alpha_test_func == GL_NEVER) { /* f0.1 = 0 */ fs_reg some_reg = fs_reg(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW)); @@ -2654,8 +2757,8 @@ fs_visitor::emit_alpha_test() color.reg_offset += 3; /* f0.1 &= func(color, ref) */ - cmp = emit(CMP(reg_null_f, color, fs_reg(c->key.alpha_test_ref), - cond_for_alpha_func(c->key.alpha_test_func))); + cmp = emit(CMP(reg_null_f, color, fs_reg(key->alpha_test_ref), + cond_for_alpha_func(key->alpha_test_func))); } cmp->predicate = BRW_PREDICATE_NORMAL; cmp->flag_subreg = 1; @@ -2672,12 +2775,12 @@ fs_visitor::emit_fb_writes() int base_mrf = 1; int nr = base_mrf; int reg_width = dispatch_width / 8; - bool do_dual_src = this->dual_src_output.file != BAD_FILE; bool src0_alpha_to_render_target = false; - if (dispatch_width == 16 && do_dual_src) { - fail("GL_ARB_blend_func_extended not yet supported in 16-wide."); - do_dual_src = false; + if (do_dual_src) { + no16("GL_ARB_blend_func_extended not yet supported in SIMD16."); + if (dispatch_width == 16) + do_dual_src = false; } /* From the Sandy Bridge PRM, volume 4, page 198: @@ -2688,30 +2791,30 @@ fs_visitor::emit_fb_writes() * thread message and on all dual-source messages." */ if (brw->gen >= 6 && - !this->fp->UsesKill && + (brw->is_haswell || brw->gen >= 8 || !this->fp->UsesKill) && !do_dual_src && - c->key.nr_color_regions == 1) { + key->nr_color_regions == 1) { header_present = false; } if (header_present) { src0_alpha_to_render_target = brw->gen >= 6 && !do_dual_src && - c->key.replicate_alpha; + key->replicate_alpha; /* m2, m3 header */ nr += 2; } - if (c->aa_dest_stencil_reg) { + if (payload.aa_dest_stencil_reg) { push_force_uncompressed(); emit(MOV(fs_reg(MRF, nr++), - fs_reg(brw_vec8_grf(c->aa_dest_stencil_reg, 0)))); + fs_reg(brw_vec8_grf(payload.aa_dest_stencil_reg, 0)))); pop_force_uncompressed(); } - c->prog_data.uses_omask = + prog_data->uses_omask = fp->Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK); - if(c->prog_data.uses_omask) { + if (prog_data->uses_omask) { this->current_annotation = "FB write oMask"; assert(this->sample_mask.file != BAD_FILE); /* Hand over gl_SampleMask. Only lower 16 bits are relevant. */ @@ -2727,14 +2830,14 @@ fs_visitor::emit_fb_writes() if (src0_alpha_to_render_target) nr += reg_width; - if (c->source_depth_to_render_target) { - if (brw->gen == 6 && dispatch_width == 16) { + if (source_depth_to_render_target) { + if (brw->gen == 6) { /* For outputting oDepth on gen6, SIMD8 writes have to be - * used. This would require 8-wide moves of each half to + * used. This would require SIMD8 moves of each half to * message regs, kind of like pre-gen5 SIMD16 FB writes. * Just bail on doing so for now. */ - fail("Missing support for simd16 depth writes on gen6\n"); + no16("Missing support for simd16 depth writes on gen6\n"); } if (prog->OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { @@ -2744,14 +2847,14 @@ fs_visitor::emit_fb_writes() } else { /* Pass through the payload depth. */ emit(MOV(fs_reg(MRF, nr), - fs_reg(brw_vec8_grf(c->source_depth_reg, 0)))); + fs_reg(brw_vec8_grf(payload.source_depth_reg, 0)))); } nr += reg_width; } - if (c->dest_depth_reg) { + if (payload.dest_depth_reg) { emit(MOV(fs_reg(MRF, nr), - fs_reg(brw_vec8_grf(c->dest_depth_reg, 0)))); + fs_reg(brw_vec8_grf(payload.dest_depth_reg, 0)))); nr += reg_width; } @@ -2764,7 +2867,7 @@ fs_visitor::emit_fb_writes() for (int i = 0; i < 4; i++) { fs_inst *inst = emit(MOV(fs_reg(MRF, color_mrf + i, src0.type), src0)); src0.reg_offset++; - inst->saturate = c->key.clamp_fragment_color; + inst->saturate = key->clamp_fragment_color; } this->current_annotation = ralloc_asprintf(this->mem_ctx, @@ -2773,7 +2876,7 @@ fs_visitor::emit_fb_writes() fs_inst *inst = emit(MOV(fs_reg(MRF, color_mrf + 4 + i, src1.type), src1)); src1.reg_offset++; - inst->saturate = c->key.clamp_fragment_color; + inst->saturate = key->clamp_fragment_color; } if (INTEL_DEBUG & DEBUG_SHADER_TIME) @@ -2785,13 +2888,17 @@ fs_visitor::emit_fb_writes() inst->mlen = nr - base_mrf; inst->eot = true; inst->header_present = header_present; + if ((brw->gen >= 8 || brw->is_haswell) && fp->UsesKill) { + inst->predicate = BRW_PREDICATE_NORMAL; + inst->flag_subreg = 1; + } - c->prog_data.dual_src_blend = true; + prog_data->dual_src_blend = true; this->current_annotation = NULL; return; } - for (int target = 0; target < c->key.nr_color_regions; target++) { + for (int target = 0; target < key->nr_color_regions; target++) { this->current_annotation = ralloc_asprintf(this->mem_ctx, "FB write target %d", target); @@ -2806,7 +2913,7 @@ fs_visitor::emit_fb_writes() inst = emit(MOV(fs_reg(MRF, write_color_mrf, color.type), color)); - inst->saturate = c->key.clamp_fragment_color; + inst->saturate = key->clamp_fragment_color; write_color_mrf = color_mrf + reg_width; } @@ -2814,7 +2921,7 @@ fs_visitor::emit_fb_writes() emit_color_write(target, i, write_color_mrf); bool eot = false; - if (target == c->key.nr_color_regions - 1) { + if (target == key->nr_color_regions - 1) { eot = true; if (INTEL_DEBUG & DEBUG_SHADER_TIME) @@ -2830,9 +2937,13 @@ fs_visitor::emit_fb_writes() inst->mlen = nr - base_mrf; inst->eot = eot; inst->header_present = header_present; + if ((brw->gen >= 8 || brw->is_haswell) && fp->UsesKill) { + inst->predicate = BRW_PREDICATE_NORMAL; + inst->flag_subreg = 1; + } } - if (c->key.nr_color_regions == 0) { + if (key->nr_color_regions == 0) { /* Even if there's no color buffers enabled, we still need to send * alpha out the pipeline to our null renderbuffer to support * alpha-testing, alpha-to-coverage, and so on. @@ -2847,6 +2958,10 @@ fs_visitor::emit_fb_writes() inst->mlen = nr - base_mrf; inst->eot = true; inst->header_present = header_present; + if ((brw->gen >= 8 || brw->is_haswell) && fp->UsesKill) { + inst->predicate = BRW_PREDICATE_NORMAL; + inst->flag_subreg = 1; + } } this->current_annotation = NULL; @@ -2876,33 +2991,31 @@ fs_visitor::resolve_bool_comparison(ir_rvalue *rvalue, fs_reg *reg) } fs_visitor::fs_visitor(struct brw_context *brw, - struct brw_wm_compile *c, + void *mem_ctx, + const struct brw_wm_prog_key *key, + struct brw_wm_prog_data *prog_data, struct gl_shader_program *shader_prog, struct gl_fragment_program *fp, unsigned dispatch_width) - : dispatch_width(dispatch_width) + : backend_visitor(brw, shader_prog, &fp->Base, &prog_data->base, + MESA_SHADER_FRAGMENT), + key(key), prog_data(prog_data), + dispatch_width(dispatch_width) { - this->c = c; - this->brw = brw; this->fp = fp; - this->prog = &fp->Base; - this->shader_prog = shader_prog; - this->prog = &fp->Base; - this->stage_prog_data = &c->prog_data.base; - this->ctx = &brw->ctx; - this->mem_ctx = ralloc_context(NULL); - if (shader_prog) - shader = (struct brw_shader *) - shader_prog->_LinkedShaders[MESA_SHADER_FRAGMENT]; - else - shader = NULL; + this->mem_ctx = mem_ctx; this->failed = false; + this->simd16_unsupported = false; + this->no16_msg = NULL; this->variable_ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare); + memset(&this->payload, 0, sizeof(this->payload)); memset(this->outputs, 0, sizeof(this->outputs)); memset(this->output_components, 0, sizeof(this->output_components)); + this->source_depth_to_render_target = false; + this->runtime_check_aads_emit = false; this->first_non_payload_grf = 0; this->max_grf = brw->gen >= 7 ? GEN7_MRF_HACK_START : BRW_MAX_GRF; @@ -2915,19 +3028,23 @@ fs_visitor::fs_visitor(struct brw_context *brw, this->virtual_grf_start = NULL; this->virtual_grf_end = NULL; this->live_intervals = NULL; + this->regs_live_at_ip = NULL; - this->params_remap = NULL; - this->nr_params_remap = 0; + this->uniforms = 0; + this->last_scratch = 0; + this->pull_constant_loc = NULL; + this->push_constant_loc = NULL; this->force_uncompressed_stack = 0; this->spilled_any_registers = false; + this->do_dual_src = false; - memset(&this->param_size, 0, sizeof(this->param_size)); + if (dispatch_width == 8) + this->param_size = rzalloc_array(mem_ctx, int, stage_prog_data->nr_params); } fs_visitor::~fs_visitor() { - ralloc_free(this->mem_ctx); hash_table_dtor(this->variable_ht); }