El 22/10/17 a las 12:31, Eduardo Lima Mitev escribió: > On 10/12/2017 08:38 PM, Jose Maria Casanova Crespo wrote: >> From: Eduardo Lima Mitev <el...@igalia.com> >> >> Currently, we use byte-scattered write messages for storing 16-bit >> into an SSBO. This is because untyped surface messages have a fixed >> 32-bit size. >> >> This patch optimizes these 16-bit writes by combining 2 values (e.g, >> two consecutive components) into a 32-bit register, packing the two >> 16-bit words. >> >> 16-bit single component values will continue to use byte-scattered >> write messages. >> >> This optimization reduces the number of SEND messages used for storing >> 16-bit values potentially by 2 or 4, which cuts down execution time >> significantly because byte-scattered writes are an expensive >> operation. >> >> v2: Removed use of stride = 2 on sources (Jason Ekstrand) >> Rework optimization using shuffle 16 write and enable writes >> of 16bit vec4 with only one message of 32-bits. (Chema Casanova) >> >> Signed-off-by: Jose Maria Casanova Crespo <jmcasan...@igalia.com> >> Signed-off-by: Eduardo Lima <el...@igalia.com> >> --- >> src/intel/compiler/brw_fs_nir.cpp | 64 >> +++++++++++++++++++++++++++++++-------- >> 1 file changed, 52 insertions(+), 12 deletions(-) >> >> diff --git a/src/intel/compiler/brw_fs_nir.cpp >> b/src/intel/compiler/brw_fs_nir.cpp >> index 2d0b3e139e..c07b3e4d8d 100644 >> --- a/src/intel/compiler/brw_fs_nir.cpp >> +++ b/src/intel/compiler/brw_fs_nir.cpp >> @@ -4218,6 +4218,9 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, >> nir_intrinsic_instr *instr >> instr->num_components); >> val_reg = tmp; >> } >> + if (bit_size == 16) { >> + val_reg=retype(val_reg, BRW_REGISTER_TYPE_HF); > Spaces around the '='. Probably also remove the block since there is > only one instruction in it.
Fixed locally. > >> + } >> >> /* 16-bit types would use a minimum of 1 slot */ >> unsigned type_slots = MAX2(type_size / 4, 1); >> @@ -4231,6 +4234,9 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, >> nir_intrinsic_instr *instr >> unsigned first_component = ffs(writemask) - 1; >> unsigned length = ffs(~(writemask >> first_component)) - 1; >> >> + fs_reg current_val_reg = >> + offset(val_reg, bld, first_component * type_slots); >> + >> /* We can't write more than 2 64-bit components at once. Limit the >> * length of the write to what we can do and let the next iteration >> * handle the rest >> @@ -4238,11 +4244,40 @@ fs_visitor::nir_emit_intrinsic(const fs_builder >> &bld, nir_intrinsic_instr *instr >> if (type_size > 4) { >> length = MIN2(2, length); >> } else if (type_size == 2) { >> - /* For 16-bit types we are using byte scattered writes, that can >> - * only write one component per call. So we limit the length, >> and >> - * let the write happening in several iterations. >> + /* For 16-bit types we pack two consecutive values into a >> + * 32-bit word and use an untyped write message. For single >> values >> + * we need to use byte-scattered writes because untyped writes >> work >> + * on multiples of 32 bits. >> + * >> + * For example, if there is a 3-component vector we submit one >> + * untyped-write message of 32-bit (first two components), and >> one >> + * byte-scattered write message (the last component). >> */ >> - length = 1; >> + if (length >= 2) { >> + /* pack two consecutive 16-bit words into a 32-bit register, >> + * using the same original source register. >> + */ >> + length -= length % 2; >> + fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F, length / 2); >> + shuffle_16bit_data_for_32bit_write(bld, >> + tmp, >> + current_val_reg, >> + length); >> + current_val_reg = tmp; >> + >> + } else { >> + /* For single 16-bit values, we just limit the length to 1 >> and >> + * use a byte-scattered write message below. >> + */ >> + length = 1; >> + fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F); >> + shuffle_16bit_data_for_32bit_write(bld, >> + tmp, >> + current_val_reg, >> + length); >> + current_val_reg = tmp; >> + >> + } >> } >> >> fs_reg offset_reg; >> @@ -4257,24 +4292,29 @@ fs_visitor::nir_emit_intrinsic(const fs_builder >> &bld, nir_intrinsic_instr *instr >> brw_imm_ud(type_size * first_component)); >> } >> >> - if (type_size == 2) { >> + if (type_size == 2 && length == 1) { >> /* Untyped Surface messages have a fixed 32-bit size, so we need >> * to rely on byte scattered in order to write 16-bit elements. >> * The byte_scattered_write message needs that every written >> 16-bit >> * type to be aligned 32-bits (stride=2). >> */ >> - fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F); >> - val_reg.type = BRW_REGISTER_TYPE_HF; >> - bld.MOV (subscript(tmp, BRW_REGISTER_TYPE_HF, 0), >> - offset(val_reg, bld, first_component)); >> emit_byte_scattered_write(bld, surf_index, offset_reg, >> - tmp, >> + current_val_reg, >> 1 /* dims */, length * type_slots, >> BRW_PREDICATE_NONE); >> } else { >> + unsigned write_size = length * type_slots; >> + >> + /* We need to half the write size of the untyped write message >> when >> + * submitting two packed 16-bit values, because length is 2 but >> the >> + * type size is 16-bit. So we are effectively writing just 32 >> bits >> + * (size = 1). >> + */ >> + if (type_size == 2) >> + write_size /= 2; >> emit_untyped_write(bld, surf_index, offset_reg, >> - offset(val_reg, bld, first_component * >> type_slots), >> - 1 /* dims */, length * type_slots, >> + current_val_reg, >> + 1 /* dims */, write_size, >> BRW_PREDICATE_NONE); >> } >> >> >> _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev