diff --git a/src/intel/compiler/brw_builder.cpp b/src/intel/compiler/brw_builder.cpp index 062174896e8..9d3c0c6645e 100644 --- a/src/intel/compiler/brw_builder.cpp +++ b/src/intel/compiler/brw_builder.cpp @@ -5,6 +5,125 @@ #include "brw_builder.h" +/* + * This helper takes a source register and un/shuffles it into the destination + * register. + * + * If source type size is smaller than destination type size the operation + * needed is a component shuffle. The opposite case would be an unshuffle. If + * source/destination type size is equal a shuffle is done that would be + * equivalent to a simple MOV. + * + * For example, if source is a 16-bit type and destination is 32-bit. A 3 + * components .xyz 16-bit vector on SIMD8 would be. + * + * |x1|x2|x3|x4|x5|x6|x7|x8|y1|y2|y3|y4|y5|y6|y7|y8| + * |z1|z2|z3|z4|z5|z6|z7|z8| | | | | | | | | + * + * This helper will return the following 2 32-bit components with the 16-bit + * values shuffled: + * + * |x1 y1|x2 y2|x3 y3|x4 y4|x5 y5|x6 y6|x7 y7|x8 y8| + * |z1 |z2 |z3 |z4 |z5 |z6 |z7 |z8 | + * + * For unshuffle, the example would be the opposite, a 64-bit type source + * and a 32-bit destination. A 2 component .xy 64-bit vector on SIMD8 + * would be: + * + * | x1l x1h | x2l x2h | x3l x3h | x4l x4h | + * | x5l x5h | x6l x6h | x7l x7h | x8l x8h | + * | y1l y1h | y2l y2h | y3l y3h | y4l y4h | + * | y5l y5h | y6l y6h | y7l y7h | y8l y8h | + * + * The returned result would be the following 4 32-bit components unshuffled: + * + * | x1l | x2l | x3l | x4l | x5l | x6l | x7l | x8l | + * | x1h | x2h | x3h | x4h | x5h | x6h | x7h | x8h | + * | y1l | y2l | y3l | y4l | y5l | y6l | y7l | y8l | + * | y1h | y2h | y3h | y4h | y5h | y6h | y7h | y8h | + * + * - Source and destination register must not be overlapped. + * - components units are measured in terms of the smaller type between + * source and destination because we are un/shuffling the smaller + * components from/into the bigger ones. + * - first_component parameter allows skipping source components. + */ +static void +shuffle_src_to_dst(const brw_builder &bld, + const brw_reg &dst, + const brw_reg &src, + uint32_t first_component, + uint32_t components) +{ + if (brw_type_size_bytes(src.type) == brw_type_size_bytes(dst.type)) { + assert(!regions_overlap(dst, + brw_type_size_bytes(dst.type) * bld.dispatch_width() * components, + offset(src, bld, first_component), + brw_type_size_bytes(src.type) * bld.dispatch_width() * components)); + for (unsigned i = 0; i < components; i++) { + bld.MOV(retype(offset(dst, bld, i), src.type), + offset(src, bld, i + first_component)); + } + } else if (brw_type_size_bytes(src.type) < brw_type_size_bytes(dst.type)) { + /* Source is shuffled into destination */ + unsigned size_ratio = brw_type_size_bytes(dst.type) / brw_type_size_bytes(src.type); + assert(!regions_overlap(dst, + brw_type_size_bytes(dst.type) * bld.dispatch_width() * + DIV_ROUND_UP(components, size_ratio), + offset(src, bld, first_component), + brw_type_size_bytes(src.type) * bld.dispatch_width() * components)); + + brw_reg_type shuffle_type = + brw_type_with_size(BRW_TYPE_D, brw_type_size_bits(src.type)); + for (unsigned i = 0; i < components; i++) { + brw_reg shuffle_component_i = + subscript(offset(dst, bld, i / size_ratio), + shuffle_type, i % size_ratio); + bld.MOV(shuffle_component_i, + retype(offset(src, bld, i + first_component), shuffle_type)); + } + } else { + /* Source is unshuffled into destination */ + unsigned size_ratio = brw_type_size_bytes(src.type) / brw_type_size_bytes(dst.type); + assert(!regions_overlap(dst, + brw_type_size_bytes(dst.type) * bld.dispatch_width() * components, + offset(src, bld, first_component / size_ratio), + brw_type_size_bytes(src.type) * bld.dispatch_width() * + DIV_ROUND_UP(components + (first_component % size_ratio), + size_ratio))); + + brw_reg_type shuffle_type = + brw_type_with_size(BRW_TYPE_D, brw_type_size_bits(dst.type)); + for (unsigned i = 0; i < components; i++) { + brw_reg shuffle_component_i = + subscript(offset(src, bld, (first_component + i) / size_ratio), + shuffle_type, (first_component + i) % size_ratio); + bld.MOV(retype(offset(dst, bld, i), shuffle_type), + shuffle_component_i); + } + } +} + +void +brw_builder::shuffle_from_32bit_read(const brw_reg &dst, + const brw_reg &src, + uint32_t first_component, + uint32_t components) const +{ + assert(brw_type_size_bytes(src.type) == 4); + + /* This function takes components in units of the destination type while + * shuffle_src_to_dst takes components in units of the smallest type + */ + if (brw_type_size_bytes(dst.type) > 4) { + assert(brw_type_size_bytes(dst.type) == 8); + first_component *= 2; + components *= 2; + } + + shuffle_src_to_dst(*this, dst, src, first_component, components); +} + /** * Get the mask of SIMD channels enabled during dispatch and not yet disabled * by discard. Due to the layout of the sample mask in the fragment shader diff --git a/src/intel/compiler/brw_builder.h b/src/intel/compiler/brw_builder.h index 182a89dc6f8..428bf702489 100644 --- a/src/intel/compiler/brw_builder.h +++ b/src/intel/compiler/brw_builder.h @@ -798,7 +798,7 @@ public: vec4_result, srcs, PULL_VARYING_CONSTANT_SRCS); inst->size_written = 4 * vec4_result.component_size(inst->exec_size); - shuffle_from_32bit_read(*this, dst, vec4_result, 0, components); + shuffle_from_32bit_read(dst, vec4_result, 0, components); } brw_reg @@ -908,6 +908,11 @@ private: return expanded; } + void shuffle_from_32bit_read(const brw_reg &dst, + const brw_reg &src, + uint32_t first_component, + uint32_t components) const; + bblock_t *block; exec_node *cursor; diff --git a/src/intel/compiler/brw_fs.h b/src/intel/compiler/brw_fs.h index 19f6d2f8436..36cba9427bb 100644 --- a/src/intel/compiler/brw_fs.h +++ b/src/intel/compiler/brw_fs.h @@ -486,12 +486,6 @@ namespace brw { lower_src_modifiers(fs_visitor *v, bblock_t *block, fs_inst *inst, unsigned i); } -void shuffle_from_32bit_read(const brw_builder &bld, - const brw_reg &dst, - const brw_reg &src, - uint32_t first_component, - uint32_t components); - enum intel_barycentric_mode brw_barycentric_mode(const struct brw_wm_prog_key *key, nir_intrinsic_instr *intr); diff --git a/src/intel/compiler/brw_fs_nir.cpp b/src/intel/compiler/brw_fs_nir.cpp index c600a8ef2a9..7e39e22eaef 100644 --- a/src/intel/compiler/brw_fs_nir.cpp +++ b/src/intel/compiler/brw_fs_nir.cpp @@ -7625,126 +7625,6 @@ fs_nir_emit_jump(nir_to_brw_state &ntb, nir_jump_instr *instr) } } -/* - * This helper takes a source register and un/shuffles it into the destination - * register. - * - * If source type size is smaller than destination type size the operation - * needed is a component shuffle. The opposite case would be an unshuffle. If - * source/destination type size is equal a shuffle is done that would be - * equivalent to a simple MOV. - * - * For example, if source is a 16-bit type and destination is 32-bit. A 3 - * components .xyz 16-bit vector on SIMD8 would be. - * - * |x1|x2|x3|x4|x5|x6|x7|x8|y1|y2|y3|y4|y5|y6|y7|y8| - * |z1|z2|z3|z4|z5|z6|z7|z8| | | | | | | | | - * - * This helper will return the following 2 32-bit components with the 16-bit - * values shuffled: - * - * |x1 y1|x2 y2|x3 y3|x4 y4|x5 y5|x6 y6|x7 y7|x8 y8| - * |z1 |z2 |z3 |z4 |z5 |z6 |z7 |z8 | - * - * For unshuffle, the example would be the opposite, a 64-bit type source - * and a 32-bit destination. A 2 component .xy 64-bit vector on SIMD8 - * would be: - * - * | x1l x1h | x2l x2h | x3l x3h | x4l x4h | - * | x5l x5h | x6l x6h | x7l x7h | x8l x8h | - * | y1l y1h | y2l y2h | y3l y3h | y4l y4h | - * | y5l y5h | y6l y6h | y7l y7h | y8l y8h | - * - * The returned result would be the following 4 32-bit components unshuffled: - * - * | x1l | x2l | x3l | x4l | x5l | x6l | x7l | x8l | - * | x1h | x2h | x3h | x4h | x5h | x6h | x7h | x8h | - * | y1l | y2l | y3l | y4l | y5l | y6l | y7l | y8l | - * | y1h | y2h | y3h | y4h | y5h | y6h | y7h | y8h | - * - * - Source and destination register must not be overlapped. - * - components units are measured in terms of the smaller type between - * source and destination because we are un/shuffling the smaller - * components from/into the bigger ones. - * - first_component parameter allows skipping source components. - */ -void -shuffle_src_to_dst(const brw_builder &bld, - const brw_reg &dst, - const brw_reg &src, - uint32_t first_component, - uint32_t components) -{ - if (brw_type_size_bytes(src.type) == brw_type_size_bytes(dst.type)) { - assert(!regions_overlap(dst, - brw_type_size_bytes(dst.type) * bld.dispatch_width() * components, - offset(src, bld, first_component), - brw_type_size_bytes(src.type) * bld.dispatch_width() * components)); - for (unsigned i = 0; i < components; i++) { - bld.MOV(retype(offset(dst, bld, i), src.type), - offset(src, bld, i + first_component)); - } - } else if (brw_type_size_bytes(src.type) < brw_type_size_bytes(dst.type)) { - /* Source is shuffled into destination */ - unsigned size_ratio = brw_type_size_bytes(dst.type) / brw_type_size_bytes(src.type); - assert(!regions_overlap(dst, - brw_type_size_bytes(dst.type) * bld.dispatch_width() * - DIV_ROUND_UP(components, size_ratio), - offset(src, bld, first_component), - brw_type_size_bytes(src.type) * bld.dispatch_width() * components)); - - brw_reg_type shuffle_type = - brw_type_with_size(BRW_TYPE_D, brw_type_size_bits(src.type)); - for (unsigned i = 0; i < components; i++) { - brw_reg shuffle_component_i = - subscript(offset(dst, bld, i / size_ratio), - shuffle_type, i % size_ratio); - bld.MOV(shuffle_component_i, - retype(offset(src, bld, i + first_component), shuffle_type)); - } - } else { - /* Source is unshuffled into destination */ - unsigned size_ratio = brw_type_size_bytes(src.type) / brw_type_size_bytes(dst.type); - assert(!regions_overlap(dst, - brw_type_size_bytes(dst.type) * bld.dispatch_width() * components, - offset(src, bld, first_component / size_ratio), - brw_type_size_bytes(src.type) * bld.dispatch_width() * - DIV_ROUND_UP(components + (first_component % size_ratio), - size_ratio))); - - brw_reg_type shuffle_type = - brw_type_with_size(BRW_TYPE_D, brw_type_size_bits(dst.type)); - for (unsigned i = 0; i < components; i++) { - brw_reg shuffle_component_i = - subscript(offset(src, bld, (first_component + i) / size_ratio), - shuffle_type, (first_component + i) % size_ratio); - bld.MOV(retype(offset(dst, bld, i), shuffle_type), - shuffle_component_i); - } - } -} - -void -shuffle_from_32bit_read(const brw_builder &bld, - const brw_reg &dst, - const brw_reg &src, - uint32_t first_component, - uint32_t components) -{ - assert(brw_type_size_bytes(src.type) == 4); - - /* This function takes components in units of the destination type while - * shuffle_src_to_dst takes components in units of the smallest type - */ - if (brw_type_size_bytes(dst.type) > 4) { - assert(brw_type_size_bytes(dst.type) == 8); - first_component *= 2; - components *= 2; - } - - shuffle_src_to_dst(bld, dst, src, first_component, components); -} - static void fs_nir_emit_instr(nir_to_brw_state &ntb, nir_instr *instr) {