<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Wed, Mar 7, 2018 at 5:08 AM, Pohjolainen, Topi <span dir="ltr"><<a href="mailto:topi.pohjolainen@gmail.com" target="_blank">topi.pohjolainen@gmail.com</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">On Fri, Jan 26, 2018 at 05:59:55PM -0800, Jason Ekstrand wrote:<br>
> By making use of the NIR helper for uint vector casts, we should now be<br>
> able to bitcast between any two uint formats so long as their channels<br>
> are in RGBA order (possibly with channels missing).  In order to do this<br>
> we need to rework the key a bit to pass the actual formats instead of<br>
> just the number of bits in each.<br>
> ---<br>
>  src/intel/blorp/blorp_blit.c | 105 ++++++++++++++++++++++++++++++<wbr>+++++--------<br>
>  src/intel/blorp/blorp_priv.h |  13 +++---<br>
>  2 files changed, 95 insertions(+), 23 deletions(-)<br>
> <br>
> diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c<br>
> index ea0687f..321b3e3 100644<br>
> --- a/src/intel/blorp/blorp_blit.c<br>
> +++ b/src/intel/blorp/blorp_blit.c<br>
> @@ -871,17 +871,71 @@ bit_cast_color(struct nir_builder *b, nir_ssa_def *color,<br>
>  {<br>
>     assert(key->texture_data_type == nir_type_uint);<br>
>  <br>
> -   /* We don't actually know how many source channels we have and NIR will<br>
> -    * assert if the number of destination channels ends up being more than 4.<br>
> -    * Choose the largest number of source channels that won't over-fill a<br>
> -    * destination vec4.<br>
> -    */<br>
> -   const unsigned src_channels =<br>
> -      MIN2(4, (4 * key->dst_bpc) / key->src_bpc);<br>
> -   color = nir_channels(b, color, (1 << src_channels) - 1);<br>
> +   if (key->src_format == key->dst_format)<br>
> +      return color;<br>
>  <br>
> -   color = nir_format_bitcast_uint_vec_<wbr>unmasked(b, color, key->src_bpc,<br>
> -                                                key->dst_bpc);<br>
> +   const struct isl_format_layout *src_fmtl =<br>
> +      isl_format_get_layout(key-><wbr>src_format);<br>
> +   const struct isl_format_layout *dst_fmtl =<br>
> +      isl_format_get_layout(key-><wbr>dst_format);<br>
> +<br>
> +   /* They must be uint formats with the same bit size */<br>
> +   assert(src_fmtl->bpb == dst_fmtl->bpb);<br>
> +   assert(src_fmtl->channels.r.<wbr>type == ISL_UINT);<br>
> +   assert(dst_fmtl->channels.r.<wbr>type == ISL_UINT);<br>
> +<br>
> +   /* They must be in regular color formats (no luminance or alpha) */<br>
> +   assert(src_fmtl->channels.r.<wbr>bits > 0);<br>
> +   assert(dst_fmtl->channels.r.<wbr>bits > 0);<br>
> +<br>
> +   /* They must be in RGBA order (possibly with channels missing) */<br>
> +   assert(src_fmtl->channels.r.<wbr>start_bit == 0);<br>
> +   assert(dst_fmtl->channels.r.<wbr>start_bit == 0);<br>
> +<br>
> +   if (src_fmtl->bpb <= 32) {<br>
> +      const unsigned src_channels =<br>
> +         isl_format_get_num_channels(<wbr>key->src_format);<br>
> +      const unsigned src_bits[4] = {<br>
> +         src_fmtl->channels.r.bits,<br>
> +         src_fmtl->channels.g.bits,<br>
> +         src_fmtl->channels.b.bits,<br>
> +         src_fmtl->channels.a.bits,<br>
> +      };<br>
> +      const unsigned dst_channels =<br>
> +         isl_format_get_num_channels(<wbr>key->dst_format);<br>
> +      const unsigned dst_bits[4] = {<br>
> +         dst_fmtl->channels.r.bits,<br>
> +         dst_fmtl->channels.g.bits,<br>
> +         dst_fmtl->channels.b.bits,<br>
> +         dst_fmtl->channels.a.bits,<br>
> +      };<br>
> +      nir_ssa_def *packed =<br>
> +         nir_format_pack_uint_unmasked(<wbr>b, color, src_bits, src_channels);<br>
> +      color = nir_format_unpack_uint(b, packed, dst_bits, dst_channels);<br>
<br>
</div></div>I tried to think why nir_format_bitcast_uint_vec_<wbr>unmasked() can't handle<br>
these cases (src_fmtl->bpb <= 32). At this point it still does, right? Using<br>
nir_format_pack_uint_unmasked(<wbr>)/nir_format_unpack_uint() already here is<br>
preparing for cases where src or dst is ISL_FORMAT_R11G11B10_FLOAT and which<br>
nir_format_bitcast_uint_vec_<wbr>unmasked() can't handle anymore?<br><div><div class="h5"></div></div></blockquote><div><br></div><div>Correct.  nir_format_bitcast_uint_vec_unmasked can handle any cast from one format with a uniform channel size to another so long as the channel sizes are at least 8 bits.  However, for 1010102 and similar, it falls over.  Maybe I should say that in the commit message.<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">
> +   } else {<br>
> +      const unsigned src_bpc = src_fmtl->channels.r.bits;<br>
> +      const unsigned dst_bpc = dst_fmtl->channels.r.bits;<br>
> +<br>
> +      assert(src_fmtl->channels.g.<wbr>bits == 0 ||<br>
> +             src_fmtl->channels.g.bits == src_fmtl->channels.r.bits);<br>
> +      assert(src_fmtl->channels.b.<wbr>bits == 0 ||<br>
> +             src_fmtl->channels.b.bits == src_fmtl->channels.r.bits);<br>
> +      assert(src_fmtl->channels.a.<wbr>bits == 0 ||<br>
> +             src_fmtl->channels.a.bits == src_fmtl->channels.r.bits);<br>
> +      assert(dst_fmtl->channels.g.<wbr>bits == 0 ||<br>
> +             dst_fmtl->channels.g.bits == dst_fmtl->channels.r.bits);<br>
> +      assert(dst_fmtl->channels.b.<wbr>bits == 0 ||<br>
> +             dst_fmtl->channels.b.bits == dst_fmtl->channels.r.bits);<br>
> +      assert(dst_fmtl->channels.a.<wbr>bits == 0 ||<br>
> +             dst_fmtl->channels.a.bits == dst_fmtl->channels.r.bits);<br>
> +<br>
> +      /* Restrict to only the channels we actually have */<br>
> +      const unsigned src_channels =<br>
> +         isl_format_get_num_channels(<wbr>key->src_format);<br>
> +      color = nir_channels(b, color, (1 << src_channels) - 1);<br>
> +<br>
> +      color = nir_format_bitcast_uint_vec_<wbr>unmasked(b, color, src_bpc, dst_bpc);<br>
> +   }<br>
>  <br>
>     /* Blorp likes to assume that colors are vec4s */<br>
>     nir_ssa_def *u = nir_ssa_undef(b, 1, 32);<br>
> @@ -1321,14 +1375,13 @@ brw_blorp_build_nir_shader(<wbr>struct blorp_context *blorp, void *mem_ctx,<br>
>                              nir_type_int);<br>
>     }<br>
>  <br>
> -   if (key->dst_bpc != key->src_bpc) {<br>
> +   if (key->format_bit_cast) {<br>
>        assert(isl_swizzle_is_<wbr>identity(key->src_swizzle));<br>
>        assert(isl_swizzle_is_<wbr>identity(key->dst_swizzle));<br>
>        color = bit_cast_color(&b, color, key);<br>
> -   }<br>
> -<br>
> -   if (key->dst_format)<br>
> +   } else if (key->dst_format) {<br>
>        color = convert_color(&b, color, key);<br>
> +   }<br>
>  <br>
>     if (key->dst_rgb) {<br>
>        /* The destination image is bound as a red texture three times as wide<br>
> @@ -2522,10 +2575,26 @@ blorp_copy(struct blorp_batch *batch,<br>
>                               params.dst.view.format, packed);<br>
>     }<br>
>  <br>
> -   wm_prog_key.src_bpc =<br>
> -      isl_format_get_layout(params.<wbr>src.view.format)->channels.r.<wbr>bits;<br>
> -   wm_prog_key.dst_bpc =<br>
> -      isl_format_get_layout(params.<wbr>dst.view.format)->channels.r.<wbr>bits;<br>
> +   if (params.src.view.format != params.dst.view.format) {<br>
> +      enum isl_format src_cast_format = params.src.view.format;<br>
> +      enum isl_format dst_cast_format = params.dst.view.format;<br>
> +<br>
> +      /* The BLORP bitcast code gets confused by RGB formats.  Just treat them<br>
> +       * as RGBA and then everything will be happy.  This is perfectly safe<br>
> +       * because BLORP likes to treat things as if they have vec4 colors all<br>
> +       * the time anyway.<br>
> +       */<br>
> +      if (isl_format_is_rgb(src_cast_<wbr>format))<br>
> +         src_cast_format = isl_format_rgb_to_rgba(src_<wbr>cast_format);<br>
> +      if (isl_format_is_rgb(dst_cast_<wbr>format))<br>
> +         dst_cast_format = isl_format_rgb_to_rgba(dst_<wbr>cast_format);<br>
> +<br>
> +      if (src_cast_format != dst_cast_format) {<br>
> +         wm_prog_key.format_bit_cast = true;<br>
> +         wm_prog_key.src_format = src_cast_format;<br>
> +         wm_prog_key.dst_format = dst_cast_format;<br>
> +      }<br>
> +   }<br>
>  <br>
>     if (src_fmtl->bw > 1 || src_fmtl->bh > 1) {<br>
>        blorp_surf_convert_to_<wbr>uncompressed(batch->blorp-><wbr>isl_dev, &params.src,<br>
> diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h<br>
> index 291c0a9..2013c53 100644<br>
> --- a/src/intel/blorp/blorp_priv.h<br>
> +++ b/src/intel/blorp/blorp_priv.h<br>
> @@ -245,8 +245,11 @@ struct brw_blorp_blit_prog_key<br>
>     /* The swizzle to apply to the source in the shader */<br>
>     struct isl_swizzle src_swizzle;<br>
>  <br>
> -   /* Number of bits per channel in the source image. */<br>
> -   uint8_t src_bpc;<br>
> +   /* The format of the source if format-specific workarounds are needed<br>
> +    * and 0 (ISL_FORMAT_R32G32B32A32_<wbr>FLOAT) if the destination is natively<br>
> +    * renderable.<br>
> +    */<br>
> +   enum isl_format src_format;<br>
>  <br>
>     /* True if the source requires normalized coordinates */<br>
>     bool src_coords_normalized;<br>
> @@ -268,15 +271,15 @@ struct brw_blorp_blit_prog_key<br>
>     /* The swizzle to apply to the destination in the shader */<br>
>     struct isl_swizzle dst_swizzle;<br>
>  <br>
> -   /* Number of bits per channel in the destination image. */<br>
> -   uint8_t dst_bpc;<br>
> -<br>
>     /* The format of the destination if format-specific workarounds are needed<br>
>      * and 0 (ISL_FORMAT_R32G32B32A32_<wbr>FLOAT) if the destination is natively<br>
>      * renderable.<br>
>      */<br>
>     enum isl_format dst_format;<br>
>  <br>
> +   /* Whether or not the format workarounds are a bitcast operation */<br>
> +   bool format_bit_cast;<br>
> +<br>
>     /* Type of the data to be read from the texture (one of<br>
>      * nir_type_(int|uint|float)).<br>
>      */<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>