X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fi965%2Fbrw_vec4_nir.cpp;h=dde07d0d141d539be44cb3d098a1597424e3938e;hb=4f2d1d6ea713df8f8d816b48b9e99c7117cf36d7;hp=ee6929b16a2ed16c4f7f0cfdca9321f4413fbc8a;hpb=14c46954c910efb1db94a068a866c7259deaa9d9;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 ee6929b16a2..dde07d0d141 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); + } } } @@ -132,15 +127,6 @@ void vec4_visitor::nir_setup_uniforms() { uniforms = nir->num_uniforms / 16; - - nir_foreach_variable(var, &nir->uniforms) { - /* UBO's and atomics don't take up space in the uniform file */ - if (var->interface_type != NULL || var->type->contains_atomic()) - continue; - - if (type_size_vec4(var->type) > 0) - uniform_size[var->data.driver_location / 16] = type_size_vec4(var->type); - } } void @@ -222,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); } } @@ -270,7 +256,7 @@ dst_reg_for_nir_reg(vec4_visitor *v, nir_register *nir_reg, dst_reg reg; reg = v->nir_locals[nir_reg->index]; - reg = offset(reg, base_offset); + reg = offset(reg, 8, base_offset); if (indirect) { reg.reladdr = new(v->mem_ctx) src_reg(v->get_nir_src(*indirect, @@ -281,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)); @@ -294,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; @@ -328,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); @@ -411,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); @@ -428,7 +416,9 @@ 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); + unsigned c = nir_intrinsic_component(instr); + output_reg[varying][c] = dst_reg(src); + output_num_components[varying][c] = instr->num_components; break; } @@ -478,7 +468,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) brw_mark_surface_used(&prog_data->base, prog_data->base.binding_table.ssbo_start + - nir->info.num_ssbos - 1); + nir->info->num_ssbos - 1); } /* Offset */ @@ -620,7 +610,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) */ brw_mark_surface_used(&prog_data->base, prog_data->base.binding_table.ssbo_start + - nir->info.num_ssbos - 1); + nir->info->num_ssbos - 1); } src_reg offset_reg; @@ -695,25 +685,47 @@ 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_reg tmp = get_nir_src(instr->src[0], BRW_REGISTER_TYPE_D, 1); - src.reladdr = new(mem_ctx) src_reg(tmp); - } + src.swizzle += BRW_SWIZZLE4(shift, shift, shift, shift); - emit(MOV(dest, src)); + 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])); + } break; } @@ -722,33 +734,32 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) case nir_intrinsic_atomic_counter_dec: { unsigned surf_index = prog_data->base.binding_table.abo_start + (unsigned) instr->const_index[0]; + const vec4_builder bld = + vec4_builder(this).at_end().annotate(current_annotation, base_ir); + + /* Get some metadata from the image intrinsic. */ + const nir_intrinsic_info *info = &nir_intrinsic_infos[instr->intrinsic]; + + /* Get the arguments of the atomic intrinsic. */ src_reg offset = get_nir_src(instr->src[0], nir_type_int, instr->num_components); const src_reg surface = brw_imm_ud(surf_index); - const vec4_builder bld = - vec4_builder(this).at_end().annotate(current_annotation, base_ir); + const src_reg src0 = (info->num_srcs >= 2 + ? get_nir_src(instr->src[1]) : src_reg()); + const src_reg src1 = (info->num_srcs >= 3 + ? get_nir_src(instr->src[2]) : src_reg()); + src_reg tmp; dest = get_nir_dest(instr->dest); - switch (instr->intrinsic) { - case nir_intrinsic_atomic_counter_inc: - tmp = emit_untyped_atomic(bld, surface, offset, - src_reg(), src_reg(), - 1, 1, - BRW_AOP_INC); - break; - case nir_intrinsic_atomic_counter_dec: + if (instr->intrinsic == nir_intrinsic_atomic_counter_read) { + tmp = emit_untyped_read(bld, surface, offset, 1, 1); + } else { tmp = emit_untyped_atomic(bld, surface, offset, - src_reg(), src_reg(), + src0, src1, 1, 1, - BRW_AOP_PREDEC); - break; - case nir_intrinsic_atomic_counter_read: - tmp = emit_untyped_read(bld, surface, offset, 1, 1); - break; - default: - unreachable("Unreachable"); + get_atomic_counter_op(instr->intrinsic)); } bld.MOV(retype(dest, tmp.type), tmp); @@ -786,7 +797,7 @@ vec4_visitor::nir_emit_intrinsic(nir_intrinsic_instr *instr) */ brw_mark_surface_used(&prog_data->base, prog_data->base.binding_table.ubo_start + - nir->info.num_ubos - 1); + nir->info->num_ubos - 1); } src_reg offset; @@ -822,7 +833,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; } @@ -865,7 +876,7 @@ vec4_visitor::nir_emit_ssbo_atomic(int op, nir_intrinsic_instr *instr) */ brw_mark_surface_used(&prog_data->base, prog_data->base.binding_table.ssbo_start + - nir->info.num_ssbos - 1); + nir->info->num_ssbos - 1); } src_reg offset = get_nir_src(instr->src[1], 1); @@ -985,6 +996,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) { @@ -1116,9 +1175,45 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr) break; case nir_op_umod: + case nir_op_irem: + /* According to the sign table for INT DIV in the Ivy Bridge PRM, it + * appears that our hardware just does the right thing for signed + * remainder. + */ emit_math(SHADER_OPCODE_INT_REMAINDER, dst, op[0], op[1]); break; + case nir_op_imod: { + /* Get a regular C-style remainder. If a % b == 0, set the predicate. */ + inst = emit_math(SHADER_OPCODE_INT_REMAINDER, dst, op[0], op[1]); + + /* Math instructions don't support conditional mod */ + inst = emit(MOV(dst_null_d(), src_reg(dst))); + inst->conditional_mod = BRW_CONDITIONAL_NZ; + + /* Now, we need to determine if signs of the sources are different. + * When we XOR the sources, the top bit is 0 if they are the same and 1 + * if they are different. We can then use a conditional modifier to + * turn that into a predicate. This leads us to an XOR.l instruction. + * + * Technically, according to the PRM, you're not allowed to use .l on a + * XOR instruction. However, emperical experiments and Curro's reading + * of the simulator source both indicate that it's safe. + */ + src_reg tmp = src_reg(this, glsl_type::ivec4_type); + inst = emit(XOR(dst_reg(tmp), op[0], op[1])); + inst->predicate = BRW_PREDICATE_NORMAL; + inst->conditional_mod = BRW_CONDITIONAL_L; + + /* If the result of the initial remainder operation is non-zero and the + * two sources have different signs, add in a copy of op[1] to get the + * final integer modulus value. + */ + inst = emit(ADD(dst, src_reg(dst), op[1])); + inst->predicate = BRW_PREDICATE_NORMAL; + break; + } + case nir_op_ldexp: unreachable("not reached: should be handled by ldexp_to_arith()"); @@ -1417,25 +1512,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: @@ -1688,6 +1815,10 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr) nir_tex_instr_dest_size(instr)); dst_reg dest = get_nir_dest(instr->dest, instr->dest_type); + /* The hardware requires a LOD for buffer textures */ + if (instr->sampler_dim == GLSL_SAMPLER_DIM_BUF) + lod = brw_imm_d(0); + /* Load the texture operation sources */ uint32_t constant_offset = 0; for (unsigned i = 0; i < instr->num_srcs; i++) { @@ -1749,9 +1880,10 @@ vec4_visitor::nir_emit_texture(nir_tex_instr *instr) case nir_tex_src_offset: { nir_const_value *const_offset = nir_src_as_const_value(instr->src[i].src); - if (const_offset) { - constant_offset = brw_texture_offset(const_offset->i32, 3); - } else { + if (!const_offset || + !brw_texture_offset(const_offset->i32, + nir_tex_instr_src_size(instr, i), + &constant_offset)) { offset_value = get_nir_src(instr->src[i].src, BRW_REGISTER_TYPE_D, 2); } @@ -1827,17 +1959,11 @@ 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, - texture, texture_reg, sampler, sampler_reg); + constant_offset, offset_value, mcs, + texture, texture_reg, sampler_reg); } void