X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_vec4_nir.cpp;h=ba3bbdfaf16523f7fdfd45e8089d6ed270d39254;hb=31a40202b8bdf8bb65d33862144a03610fd57e3f;hp=b67d104c34029c8415c6afe8fc4769e1d708fd8c;hpb=8e76f664beb845f8dca30ca5635f9369618563b0;p=mesa.git diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index b67d104c340..ba3bbdfaf16 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -41,7 +41,7 @@ vec4_visitor::emit_nir_code() nir_setup_system_values(); /* get the main function and emit it */ - nir_foreach_function(nir, function) { + nir_foreach_function(function, nir) { assert(strcmp(function->name, "main") == 0); assert(function->impl); nir_emit_impl(function->impl); @@ -60,36 +60,31 @@ vec4_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr) case nir_intrinsic_load_vertex_id_zero_base: reg = &nir_system_values[SYSTEM_VALUE_VERTEX_ID_ZERO_BASE]; if (reg->file == BAD_FILE) - *reg = *make_reg_for_system_value(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, - glsl_type::int_type); + *reg = *make_reg_for_system_value(SYSTEM_VALUE_VERTEX_ID_ZERO_BASE); break; case nir_intrinsic_load_base_vertex: reg = &nir_system_values[SYSTEM_VALUE_BASE_VERTEX]; if (reg->file == BAD_FILE) - *reg = *make_reg_for_system_value(SYSTEM_VALUE_BASE_VERTEX, - glsl_type::int_type); + *reg = *make_reg_for_system_value(SYSTEM_VALUE_BASE_VERTEX); break; case nir_intrinsic_load_instance_id: reg = &nir_system_values[SYSTEM_VALUE_INSTANCE_ID]; if (reg->file == BAD_FILE) - *reg = *make_reg_for_system_value(SYSTEM_VALUE_INSTANCE_ID, - glsl_type::int_type); + *reg = *make_reg_for_system_value(SYSTEM_VALUE_INSTANCE_ID); break; case nir_intrinsic_load_base_instance: reg = &nir_system_values[SYSTEM_VALUE_BASE_INSTANCE]; if (reg->file == BAD_FILE) - *reg = *make_reg_for_system_value(SYSTEM_VALUE_BASE_INSTANCE, - glsl_type::int_type); + *reg = *make_reg_for_system_value(SYSTEM_VALUE_BASE_INSTANCE); break; case nir_intrinsic_load_draw_id: reg = &nir_system_values[SYSTEM_VALUE_DRAW_ID]; if (reg->file == BAD_FILE) - *reg = *make_reg_for_system_value(SYSTEM_VALUE_DRAW_ID, - glsl_type::int_type); + *reg = *make_reg_for_system_value(SYSTEM_VALUE_DRAW_ID); break; default: @@ -98,11 +93,9 @@ vec4_visitor::nir_setup_system_value_intrinsic(nir_intrinsic_instr *instr) } static bool -setup_system_values_block(nir_block *block, void *void_visitor) +setup_system_values_block(nir_block *block, vec4_visitor *v) { - vec4_visitor *v = (vec4_visitor *)void_visitor; - - nir_foreach_instr(block, instr) { + nir_foreach_instr(instr, block) { if (instr->type != nir_instr_type_intrinsic) continue; @@ -121,10 +114,12 @@ vec4_visitor::nir_setup_system_values() nir_system_values[i] = dst_reg(); } - nir_foreach_function(nir, function) { + nir_foreach_function(function, nir) { assert(strcmp(function->name, "main") == 0); assert(function->impl); - nir_foreach_block(function->impl, setup_system_values_block, this); + nir_foreach_block(block, function->impl) { + setup_system_values_block(block, this); + } } } @@ -213,7 +208,7 @@ vec4_visitor::nir_emit_loop(nir_loop *loop) void vec4_visitor::nir_emit_block(nir_block *block) { - nir_foreach_instr(block, instr) { + nir_foreach_instr(instr, block) { nir_emit_instr(instr); } } @@ -272,7 +267,7 @@ dst_reg_for_nir_reg(vec4_visitor *v, nir_register *nir_reg, } dst_reg -vec4_visitor::get_nir_dest(nir_dest dest) +vec4_visitor::get_nir_dest(const nir_dest &dest) { if (dest.is_ssa) { dst_reg dst = dst_reg(VGRF, alloc.allocate(1)); @@ -285,19 +280,19 @@ vec4_visitor::get_nir_dest(nir_dest dest) } dst_reg -vec4_visitor::get_nir_dest(nir_dest dest, enum brw_reg_type type) +vec4_visitor::get_nir_dest(const nir_dest &dest, enum brw_reg_type type) { return retype(get_nir_dest(dest), type); } dst_reg -vec4_visitor::get_nir_dest(nir_dest dest, nir_alu_type type) +vec4_visitor::get_nir_dest(const nir_dest &dest, nir_alu_type type) { return get_nir_dest(dest, brw_type_for_nir_type(type)); } src_reg -vec4_visitor::get_nir_src(nir_src src, enum brw_reg_type type, +vec4_visitor::get_nir_src(const nir_src &src, enum brw_reg_type type, unsigned num_components) { dst_reg reg; @@ -319,14 +314,14 @@ vec4_visitor::get_nir_src(nir_src src, enum brw_reg_type type, } src_reg -vec4_visitor::get_nir_src(nir_src src, nir_alu_type type, +vec4_visitor::get_nir_src(const nir_src &src, nir_alu_type type, unsigned num_components) { return get_nir_src(src, brw_type_for_nir_type(type), num_components); } src_reg -vec4_visitor::get_nir_src(nir_src src, unsigned num_components) +vec4_visitor::get_nir_src(const nir_src &src, unsigned num_components) { /* if type is not specified, default to signed int */ return get_nir_src(src, nir_type_int, num_components); @@ -402,6 +397,8 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) src = src_reg(ATTR, instr->const_index[0] + const_offset->u32[0], glsl_type::uvec4_type); + /* Swizzle source based on component layout qualifier */ + src.swizzle = BRW_SWZ_COMP_INPUT(nir_intrinsic_component(instr)); dest = get_nir_dest(instr->dest, src.type); dest.writemask = brw_writemask_for_size(instr->num_components); @@ -419,7 +416,14 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) src = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_F, instr->num_components); - output_reg[varying] = dst_reg(src); + if (varying >= VARYING_SLOT_VAR0) { + unsigned c = nir_intrinsic_component(instr); + unsigned v = varying - VARYING_SLOT_VAR0; + output_generic_reg[v][c] = dst_reg(src); + output_generic_num_components[v][c] = instr->num_components; + } else { + output_reg[varying] = dst_reg(src); + } break; } @@ -686,24 +690,44 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) } case nir_intrinsic_load_uniform: { - /* Offsets are in bytes but they should always be multiples of 16 */ - assert(instr->const_index[0] % 16 == 0); + /* Offsets are in bytes but they should always be multiples of 4 */ + assert(nir_intrinsic_base(instr) % 4 == 0); dest = get_nir_dest(instr->dest); - src = src_reg(dst_reg(UNIFORM, instr->const_index[0] / 16)); + src = src_reg(dst_reg(UNIFORM, nir_intrinsic_base(instr) / 16)); src.type = dest.type; + /* Uniforms don't actually have to be vec4 aligned. In the case that + * it isn't, we have to use a swizzle to shift things around. They + * do still have the std140 alignment requirement that vec2's have to + * be vec2-aligned and vec3's and vec4's have to be vec4-aligned. + * + * The swizzle also works in the indirect case as the generator adds + * the swizzle to the offset for us. + */ + unsigned shift = (nir_intrinsic_base(instr) % 16) / 4; + assert(shift + instr->num_components <= 4); + nir_const_value *const_offset = nir_src_as_const_value(instr->src[0]); if (const_offset) { - /* Offsets are in bytes but they should always be multiples of 16 */ - assert(const_offset->u32[0] % 16 == 0); - src.reg_offset = const_offset->u32[0] / 16; + /* Offsets are in bytes but they should always be multiples of 4 */ + assert(const_offset->u32[0] % 4 == 0); + + unsigned offset = const_offset->u32[0] + shift * 4; + src.offset = ROUND_DOWN_TO(offset, 16); + shift = (offset % 16) / 4; + src.swizzle += BRW_SWIZZLE4(shift, shift, shift, shift); emit(MOV(dest, src)); } else { + src.swizzle += BRW_SWIZZLE4(shift, shift, shift, shift); + src_reg indirect = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_UD, 1); + /* MOV_INDIRECT is going to stomp the whole thing anyway */ + dest.writemask = WRITEMASK_XYZW; + emit(SHADER_OPCODE_MOV_INDIRECT, dest, src, indirect, brw_imm_ud(instr->const_index[1])); } @@ -815,7 +839,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) vec4_builder(this).at_end().annotate(current_annotation, base_ir); const dst_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_UD, 2); bld.emit(SHADER_OPCODE_MEMORY_FENCE, tmp) - ->regs_written = 2; + ->size_written = 2 * REG_SIZE; break; } @@ -978,6 +1002,54 @@ vec4_visitor::optimize_predicate(nir_alu_instr *instr, return true; } +static void +emit_find_msb_using_lzd(const vec4_builder &bld, + const dst_reg &dst, + const src_reg &src, + bool is_signed) +{ + vec4_instruction *inst; + src_reg temp = src; + + if (is_signed) { + /* LZD of an absolute value source almost always does the right + * thing. There are two problem values: + * + * * 0x80000000. Since abs(0x80000000) == 0x80000000, LZD returns + * 0. However, findMSB(int(0x80000000)) == 30. + * + * * 0xffffffff. Since abs(0xffffffff) == 1, LZD returns + * 31. Section 8.8 (Integer Functions) of the GLSL 4.50 spec says: + * + * For a value of zero or negative one, -1 will be returned. + * + * * Negative powers of two. LZD(abs(-(1<src[0].negate = true; +} + void vec4_visitor::nir_emit_alu(nir_alu_instr *instr) { @@ -1446,25 +1518,57 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr) break; case nir_op_ufind_msb: - case nir_op_ifind_msb: { - emit(FBH(retype(dst, BRW_REGISTER_TYPE_UD), op[0])); + emit_find_msb_using_lzd(vec4_builder(this).at_end(), dst, op[0], false); + break; - /* FBH counts from the MSB side, while GLSL's findMSB() wants the count - * from the LSB side. If FBH didn't return an error (0xFFFFFFFF), then - * subtract the result from 31 to convert the MSB count into an LSB count. - */ + case nir_op_ifind_msb: { + vec4_builder bld = vec4_builder(this).at_end(); src_reg src(dst); - emit(CMP(dst_null_d(), src, brw_imm_d(-1), BRW_CONDITIONAL_NZ)); - inst = emit(ADD(dst, src, brw_imm_d(31))); - inst->predicate = BRW_PREDICATE_NORMAL; - inst->src[0].negate = true; + if (devinfo->gen < 7) { + emit_find_msb_using_lzd(bld, dst, op[0], true); + } else { + emit(FBH(retype(dst, BRW_REGISTER_TYPE_UD), op[0])); + + /* FBH counts from the MSB side, while GLSL's findMSB() wants the + * count from the LSB side. If FBH didn't return an error + * (0xFFFFFFFF), then subtract the result from 31 to convert the MSB + * count into an LSB count. + */ + bld.CMP(dst_null_d(), src, brw_imm_d(-1), BRW_CONDITIONAL_NZ); + + inst = bld.ADD(dst, src, brw_imm_d(31)); + inst->predicate = BRW_PREDICATE_NORMAL; + inst->src[0].negate = true; + } break; } - case nir_op_find_lsb: - emit(FBL(dst, op[0])); + case nir_op_find_lsb: { + vec4_builder bld = vec4_builder(this).at_end(); + + if (devinfo->gen < 7) { + dst_reg temp = bld.vgrf(BRW_REGISTER_TYPE_D); + + /* (x & -x) generates a value that consists of only the LSB of x. + * For all powers of 2, findMSB(y) == findLSB(y). + */ + src_reg src = src_reg(retype(op[0], BRW_REGISTER_TYPE_D)); + src_reg negated_src = src; + + /* One must be negated, and the other must be non-negated. It + * doesn't matter which is which. + */ + negated_src.negate = true; + src.negate = false; + + bld.AND(temp, src, negated_src); + emit_find_msb_using_lzd(bld, dst, src_reg(temp), false); + } else { + bld.FBL(dst, op[0]); + } break; + } case nir_op_ubitfield_extract: case nir_op_ibitfield_extract: @@ -1860,16 +1964,10 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr) ir_texture_opcode op = ir_texture_opcode_for_nir_texop(instr->op); - bool is_cube_array = - instr->op == nir_texop_txs && - instr->sampler_dim == GLSL_SAMPLER_DIM_CUBE && - instr->is_array; - emit_texture(op, dest, dest_type, coordinate, instr->coord_components, shadow_comparitor, lod, lod2, sample_index, - constant_offset, offset_value, - mcs, is_cube_array, + constant_offset, offset_value, mcs, texture, texture_reg, sampler, sampler_reg); }