<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, May 26, 2018 at 11:27 AM, Francisco Jerez <span dir="ltr"><<a href="mailto:currojerez@riseup.net" target="_blank">currojerez@riseup.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> writes:<br>
<br>
> Doing instruction header setup in the generator is aweful for a number<br>
> of reasons. For one, we can't schedule the header setup at all. For<br>
> another, it means lots of implied writes which the instruction scheduler<br>
> and other passes can't properly read about. The second isn't a huge<br>
> problem for FB writes since they always happen at the end. We made a<br>
> similar change to sampler handling in ff4726077d86.<br>
> ---<br>
> src/intel/compiler/brw_fs.cpp | 103 ++++++++++++++++++++++++++----<wbr>--<br>
> src/intel/compiler/brw_fs_<wbr>generator.cpp | 66 --------------------<br>
> 2 files changed, 86 insertions(+), 83 deletions(-)<br>
><br>
> diff --git a/src/intel/compiler/brw_fs.<wbr>cpp b/src/intel/compiler/brw_fs.<wbr>cpp<br>
> index 3e9ccc4..5276a66 100644<br>
> --- a/src/intel/compiler/brw_fs.<wbr>cpp<br>
> +++ b/src/intel/compiler/brw_fs.<wbr>cpp<br>
> @@ -3247,7 +3247,18 @@ fs_visitor::emit_repclear_<wbr>shader()<br>
> write->mlen = 1;<br>
> } else {<br>
> assume(key->nr_color_regions > 0);<br>
> +<br>
> + struct brw_reg header =<br>
> + retype(brw_message_reg(base_<wbr>mrf), BRW_REGISTER_TYPE_UD);<br>
> + bld.exec_all().group(16, 0)<br>
> + .MOV(header, retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD));<br>
> +<br>
> for (int i = 0; i < key->nr_color_regions; ++i) {<br>
> + if (i > 0) {<br>
> + bld.exec_all().group(1, 0)<br>
> + .MOV(component(header, 2), brw_imm_ud(i));<br>
> + }<br>
> +<br>
> write = bld.emit(FS_OPCODE_REP_FB_<wbr>WRITE);<br>
> write->saturate = key->clamp_fragment_color;<br>
> write->base_mrf = base_mrf;<br>
> @@ -3972,25 +3983,83 @@ lower_fb_write_logical_send(<wbr>const fs_builder &bld, fs_inst *inst,<br>
> int header_size = 2, payload_header_size;<br>
> unsigned length = 0;<br>
> <br>
> - /* From the Sandy Bridge PRM, volume 4, page 198:<br>
> - *<br>
> - * "Dispatched Pixel Enables. One bit per pixel indicating<br>
> - * which pixels were originally enabled when the thread was<br>
> - * dispatched. This field is only required for the end-of-<br>
> - * thread message and on all dual-source messages."<br>
> - */<br>
> - if (devinfo->gen >= 6 &&<br>
> - (devinfo->is_haswell || devinfo->gen >= 8 || !prog_data->uses_kill) &&<br>
> - color1.file == BAD_FILE &&<br>
> - key->nr_color_regions == 1) {<br>
> - header_size = 0;<br>
> - }<br>
> + if (devinfo->gen < 6) {<br>
> + /* For gen4-5, we always have a header consisting of g0 and g1. We have<br>
> + * an implied MOV from g0,g1 to the start of the message. The MOV from<br>
> + * g0 is handled by the hardware and the MOV from g1 is provided by the<br>
> + * generator. This is required because, on gen4-5, the generator may<br>
> + * generate two write messages with different message lengths in order<br>
> + * to handle AA data properly.<br>
> + *<br>
> + * Also, since the pixel mask goes in the g0 portion of the message and<br>
> + * since render target writes are the last thing in the shader, we write<br>
> + * the pixel mask directly into g0 and it will get copied as part of the<br>
> + * implied write.<br>
> + */<br>
> + if (prog_data->uses_kill) {<br>
> + bld.exec_all().group(1, 0)<br>
> + .MOV(retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW),<br>
> + brw_flag_reg(0, 1));<br>
> + }<br>
> +<br>
> + assert(length == 0);<br>
> + length = 2;<br>
> + } else if ((devinfo->gen <= 7 && !devinfo->is_haswell &&<br>
> + prog_data->uses_kill) ||<br>
> + color1.file != BAD_FILE ||<br>
> + key->nr_color_regions > 1) {<br>
> + /* From the Sandy Bridge PRM, volume 4, page 198:<br>
> + *<br>
> + * "Dispatched Pixel Enables. One bit per pixel indicating<br>
> + * which pixels were originally enabled when the thread was<br>
> + * dispatched. This field is only required for the end-of-<br>
> + * thread message and on all dual-source messages."<br>
> + */<br>
> + const fs_builder ubld = bld.exec_all().group(8, 0);<br>
> +<br>
> + /* The header starts off as g0 and g1 */<br>
> + fs_reg header = ubld.vgrf(BRW_REGISTER_TYPE_<wbr>UD, 2);<br>
> + ubld.group(16, 0).MOV(header, retype(brw_vec8_grf(0, 0),<br>
> + BRW_REGISTER_TYPE_UD));<br>
> +<br>
> + uint32_t g00_bits = 0;<br>
> +<br>
> + /* Set "Source0 Alpha Present to RenderTarget" bit in message<br>
> + * header.<br>
> + */<br>
> + if (inst->target > 0 && key->replicate_alpha)<br>
> + g00_bits |= 1 << 11;<br>
> +<br>
> + /* Set computes stencil to render target */<br>
> + if (prog_data->computed_stencil)<br>
> + g00_bits |= 1 << 14;<br>
> +<br>
> + if (g00_bits) {<br>
> + /* OR extra bits into g0.0 */<br>
> + ubld.group(1, 0).OR(component(header, 0),<br>
> + retype(brw_vec1_grf(0, 0),<br>
> + BRW_REGISTER_TYPE_UD),<br>
> + brw_imm_ud(g00_bits));<br>
> + }<br>
> +<br>
> + /* Set the render target index for choosing BLEND_STATE. */<br>
> + if (inst->target > 0) {<br>
> + ubld.group(1, 0).MOV(component(header, 2), brw_imm_ud(inst->target));<br>
> + }<br>
> +<br>
> + if (prog_data->uses_kill) {<br>
> + ubld.group(1, 0).MOV(retype(component(<wbr>header, 15),<br>
> + BRW_REGISTER_TYPE_UW),<br>
> + brw_flag_reg(0, 1));<br>
> + }<br>
<br>
</div></div>The original patch from my branch implemented the header setup in a<br>
helper function called setup_fb_write_header() which allowed it to share<br>
the code among emit_repclear_shader() and lower_fb_write_logical_send().<br>
I don't think there is any benefit from open-coding the header setup in<br>
the already complex enough callers, seems like an obfuscation to me<br>
(particularly of the emit_repclear_shader() codepath with PATCH 52 in<br>
mind).<br><div><div class="h5"></div></div></blockquote><div><br></div><div>Yeah, I think this one could go either way, TBH. Having it in a helper avoids some setup in emit_repclear_shader (though not that much) and is nice because it's sort-of functional in nature. The thing I like about this approach is that it combines the decision to use the header with the code to create said header. We could do that in a helper I suppose and have it return BAD_FILE if no header is needed.</div><div><br></div><div>Also, the "allocate and return a register" model ended up resulting in worse code on gen4-5 because it didn't play nicely with the implied MRF write. On those platforms, it's easier to set the header up by doing the needed MOVs to g0 and letting the implied MRF write copy it into the message.<br></div><div><br></div><div>As far as complexity goes, I'm not sure. Setting up FB writes is an inherently complex operation. Probably the biggest thing I didn't like about having it be in a helper was that the header code was around 7-800 lines away from the code to set up the rest of the FB write. That could have been solved by a pre-declaration, however.</div><div><br></div><div>You are free to continue to disagree with my approach. Hopefully, I've at least convinced you that I didn't do it just because I like straight inline code (which I do like).</div><div><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="h5">
> <br>
> - if (header_size != 0) {<br>
> - assert(header_size == 2);<br>
> - /* Allocate 2 registers for a header */<br>
> - length += 2;<br>
> + assert(length == 0);<br>
> + sources[0] = header;<br>
> + sources[1] = horiz_offset(header, 8);<br>
> + length = 2;<br>
> }<br>
> + assert(length == 0 || length == 2);<br>
> + header_size = length;<br>
> <br>
> if (payload.aa_dest_stencil_reg) {<br>
> sources[length] = fs_reg(VGRF, bld.shader->alloc.allocate(1))<wbr>;<br>
> diff --git a/src/intel/compiler/brw_fs_<wbr>generator.cpp b/src/intel/compiler/brw_fs_<wbr>generator.cpp<br>
> index 8cc9d31..1a2b961 100644<br>
> --- a/src/intel/compiler/brw_fs_<wbr>generator.cpp<br>
> +++ b/src/intel/compiler/brw_fs_<wbr>generator.cpp<br>
> @@ -307,9 +307,6 @@ fs_generator::fire_fb_write(<wbr>fs_inst *inst,<br>
> void<br>
> fs_generator::generate_fb_<wbr>write(fs_inst *inst, struct brw_reg payload)<br>
> {<br>
> - struct brw_wm_prog_data *prog_data = brw_wm_prog_data(this->prog_<wbr>data);<br>
> - const brw_wm_prog_key * const key = (brw_wm_prog_key * const) this->key;<br>
> -<br>
> if (devinfo->gen < 8 && !devinfo->is_haswell) {<br>
> brw_set_default_predicate_<wbr>control(p, BRW_PREDICATE_NONE);<br>
> }<br>
> @@ -320,69 +317,6 @@ fs_generator::generate_fb_<wbr>write(fs_inst *inst, struct brw_reg payload)<br>
> if (inst->base_mrf >= 0)<br>
> payload = brw_message_reg(inst->base_<wbr>mrf);<br>
> <br>
> - /* Header is 2 regs, g0 and g1 are the contents. g0 will be implied<br>
> - * move, here's g1.<br>
> - */<br>
> - if (inst->header_size != 0) {<br>
> - brw_push_insn_state(p);<br>
> - brw_set_default_mask_control(<wbr>p, BRW_MASK_DISABLE);<br>
> - brw_set_default_exec_size(p, BRW_EXECUTE_1);<br>
> - brw_set_default_predicate_<wbr>control(p, BRW_PREDICATE_NONE);<br>
> - brw_set_default_compression_<wbr>control(p, BRW_COMPRESSION_NONE);<br>
> - brw_set_default_flag_reg(p, 0, 0);<br>
> -<br>
> - /* On HSW, the GPU will use the predicate on SENDC, unless the header is<br>
> - * present.<br>
> - */<br>
> - if (prog_data->uses_kill) {<br>
> - struct brw_reg pixel_mask;<br>
> -<br>
> - if (devinfo->gen >= 6)<br>
> - pixel_mask = retype(brw_vec1_grf(1, 7), BRW_REGISTER_TYPE_UW);<br>
> - else<br>
> - pixel_mask = retype(brw_vec1_grf(0, 0), BRW_REGISTER_TYPE_UW);<br>
> -<br>
> - brw_MOV(p, pixel_mask, brw_flag_reg(0, 1));<br>
> - }<br>
> -<br>
> - if (devinfo->gen >= 6) {<br>
> - brw_push_insn_state(p);<br>
> - brw_set_default_exec_size(p, BRW_EXECUTE_16);<br>
> - brw_set_default_compression_<wbr>control(p, BRW_COMPRESSION_COMPRESSED);<br>
> - brw_MOV(p,<br>
> - retype(payload, BRW_REGISTER_TYPE_UD),<br>
> - retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD));<br>
> - brw_pop_insn_state(p);<br>
> -<br>
> - if (inst->target > 0 && key->replicate_alpha) {<br>
> - /* Set "Source0 Alpha Present to RenderTarget" bit in message<br>
> - * header.<br>
> - */<br>
> - brw_OR(p,<br>
> - vec1(retype(payload, BRW_REGISTER_TYPE_UD)),<br>
> - vec1(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)),<br>
> - brw_imm_ud(0x1 << 11));<br>
> - }<br>
> -<br>
> - if (inst->target > 0) {<br>
> - /* Set the render target index for choosing BLEND_STATE. */<br>
> - brw_MOV(p, retype(vec1(suboffset(payload, 2)),<br>
> - BRW_REGISTER_TYPE_UD),<br>
> - brw_imm_ud(inst->target));<br>
> - }<br>
> -<br>
> - /* Set computes stencil to render target */<br>
> - if (prog_data->computed_stencil) {<br>
> - brw_OR(p,<br>
> - vec1(retype(payload, BRW_REGISTER_TYPE_UD)),<br>
> - vec1(retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UD)),<br>
> - brw_imm_ud(0x1 << 14));<br>
> - }<br>
> - }<br>
> -<br>
> - brw_pop_insn_state(p);<br>
> - }<br>
> -<br>
> if (!runtime_check_aads_emit) {<br>
> fire_fb_write(inst, payload, implied_header, inst->mlen);<br>
> } else {<br>
> -- <br>
> 2.5.0.400.gff86faf<br>
><br>
</div></div>> ______________________________<wbr>_________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</blockquote></div><br></div></div>