[Mesa-dev] [PATCH 2/7] intel/blorp: Handle more exotic destination formats

Pohjolainen, Topi topi.pohjolainen at gmail.com
Thu Jan 26 07:32:52 UTC 2017


On Tue, Jan 24, 2017 at 03:45:49PM -0800, Jason Ekstrand wrote:
> This commit adds support for using both R24_UNORM_X8_TYPELESS and
> R9G9B9E5_SHAREDEXP as destination formats even though the hardware does
> not support rendering to them.  This is done by using a different format
> and emitting shader code to fake it the rest of the way.

Okay, I compared the R9G9B9E5_SHAREDEXP conversion to the software version in
src/util/format_rgb9e5.h. Looks good to me.

Reviewed-by: Topi Pohjolainen <topi.pohjolainen at intel.com>

> ---
>  src/intel/blorp/blorp_blit.c | 92 ++++++++++++++++++++++++++++++++++++++++++++
>  src/intel/blorp/blorp_priv.h |  6 +++
>  2 files changed, 98 insertions(+)
> 
> diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c
> index fc76fd4..b964224 100644
> --- a/src/intel/blorp/blorp_blit.c
> +++ b/src/intel/blorp/blorp_blit.c
> @@ -26,6 +26,7 @@
>  #include "blorp_priv.h"
>  #include "brw_meta_util.h"
>  
> +#include "util/format_rgb9e5.h"
>  /* header-only include needed for _mesa_unorm_to_float and friends. */
>  #include "mesa/main/format_utils.h"
>  
> @@ -916,6 +917,88 @@ bit_cast_color(struct nir_builder *b, nir_ssa_def *color,
>     }
>  }
>  
> +static nir_ssa_def *
> +convert_color(struct nir_builder *b, nir_ssa_def *color,
> +              const struct brw_blorp_blit_prog_key *key)
> +{
> +   /* All of our color conversions end up generating a single-channel color
> +    * value that we need to write out.
> +    */
> +   nir_ssa_def *value;
> +
> +   if (key->dst_format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) {
> +      /* The destination image is bound as R32_UNORM but the data needs to be
> +       * in R24_UNORM_X8_TYPELESS.  The bottom 24 are the actual data and the
> +       * top 8 need to be zero.  We can accomplish this by simply multiplying
> +       * by a factor to scale things down.
> +       */
> +      float factor = (float)((1 << 24) - 1) / (float)UINT32_MAX;
> +      value = nir_fmul(b, nir_fsat(b, nir_channel(b, color, 0)),
> +                          nir_imm_float(b, factor));
> +   } else if (key->dst_format == ISL_FORMAT_R9G9B9E5_SHAREDEXP) {
> +      /* See also float3_to_rgb9e5 */
> +
> +      /* First, we need to clamp it to range. */
> +      nir_ssa_def *clamped = nir_fmin(b, color, nir_imm_float(b, MAX_RGB9E5));
> +
> +      /* Get rid of negatives and NaN */
> +      clamped = nir_bcsel(b, nir_ult(b, nir_imm_int(b, 0x7f800000), color),
> +                             nir_imm_float(b, 0), clamped);
> +
> +      /* maxrgb.u = MAX3(rc.u, gc.u, bc.u); */
> +      nir_ssa_def *maxu = nir_umax(b, nir_channel(b, clamped, 0),
> +                          nir_umax(b, nir_channel(b, clamped, 1),
> +                                      nir_channel(b, clamped, 2)));
> +
> +      /* maxrgb.u += maxrgb.u & (1 << (23-9)); */
> +      maxu = nir_iadd(b, maxu, nir_iand(b, maxu, nir_imm_int(b, 1 << 14)));
> +
> +      /* exp_shared = MAX2((maxrgb.u >> 23), -RGB9E5_EXP_BIAS - 1 + 127) +
> +       *              1 + RGB9E5_EXP_BIAS - 127;
> +       */
> +      nir_ssa_def *exp_shared =
> +         nir_iadd(b, nir_umax(b, nir_ushr(b, maxu, nir_imm_int(b, 23)),
> +                                 nir_imm_int(b, -RGB9E5_EXP_BIAS - 1 + 127)),
> +                     nir_imm_int(b, 1 + RGB9E5_EXP_BIAS - 127));
> +
> +      /* revdenom_biasedexp = 127 - (exp_shared - RGB9E5_EXP_BIAS -
> +       *                             RGB9E5_MANTISSA_BITS) + 1;
> +       */
> +      nir_ssa_def *revdenom_biasedexp =
> +         nir_isub(b, nir_imm_int(b, 127 + RGB9E5_EXP_BIAS +
> +                                    RGB9E5_MANTISSA_BITS + 1),
> +                     exp_shared);
> +
> +      /* revdenom.u = revdenom_biasedexp << 23; */
> +      nir_ssa_def *revdenom =
> +         nir_ishl(b, revdenom_biasedexp, nir_imm_int(b, 23));
> +
> +      /* rm = (int) (rc.f * revdenom.f);
> +       * gm = (int) (gc.f * revdenom.f);
> +       * bm = (int) (bc.f * revdenom.f);
> +       */
> +      nir_ssa_def *mantissa =
> +         nir_f2i(b, nir_fmul(b, clamped, revdenom));
> +
> +      /* rm = (rm & 1) + (rm >> 1);
> +       * gm = (gm & 1) + (gm >> 1);
> +       * bm = (bm & 1) + (bm >> 1);
> +       */
> +      mantissa = nir_iadd(b, nir_iand(b, mantissa, nir_imm_int(b, 1)),
> +                             nir_ushr(b, mantissa, nir_imm_int(b, 1)));
> +
> +      value = nir_channel(b, mantissa, 0);
> +      value = nir_mask_shift_or(b, value, nir_channel(b, mantissa, 1), ~0, 9);
> +      value = nir_mask_shift_or(b, value, nir_channel(b, mantissa, 2), ~0, 18);
> +      value = nir_mask_shift_or(b, value, exp_shared, ~0, 27);
> +   } else {
> +      unreachable("Unsupported format conversion");
> +   }
> +
> +   nir_ssa_def *u = nir_ssa_undef(b, 1, 32);
> +   return nir_vec4(b, value, u, u, u);
> +}
> +
>  /**
>   * Generator for WM programs used in BLORP blits.
>   *
> @@ -1274,6 +1357,9 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
>     if (key->dst_bpc != key->src_bpc)
>        color = bit_cast_color(&b, color, key);
>  
> +   if (key->dst_format)
> +      color = convert_color(&b, color, key);
> +
>     if (key->dst_rgb) {
>        /* The destination image is bound as a red texture three times as wide
>         * as the actual image.  Our shader is effectively running one color
> @@ -1797,6 +1883,12 @@ try_blorp_blit(struct blorp_batch *batch,
>  
>        wm_prog_key->dst_rgb = true;
>        wm_prog_key->need_dst_offset = true;
> +   } else if (params->dst.view.format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) {
> +      wm_prog_key->dst_format = params->dst.view.format;
> +      params->dst.view.format = ISL_FORMAT_R32_UNORM;
> +   } else if (params->dst.view.format == ISL_FORMAT_R9G9B9E5_SHAREDEXP) {
> +      wm_prog_key->dst_format = params->dst.view.format;
> +      params->dst.view.format = ISL_FORMAT_R32_UINT;
>     }
>  
>     if (params->src.tile_x_sa || params->src.tile_y_sa) {
> diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h
> index d9c03b1..9c6b81e 100644
> --- a/src/intel/blorp/blorp_priv.h
> +++ b/src/intel/blorp/blorp_priv.h
> @@ -245,6 +245,12 @@ struct brw_blorp_blit_prog_key
>     /* Number of bits per channel in the destination image. */
>     uint8_t dst_bpc;
>  
> +   /* The format of the destination if format-specific workarounds are needed
> +    * and 0 (ISL_FORMAT_R32G32B32A32_FLOAT) if the destination is natively
> +    * renderable.
> +    */
> +   enum isl_format dst_format;
> +
>     /* Type of the data to be read from the texture (one of
>      * nir_type_(int|uint|float)).
>      */
> -- 
> 2.5.0.400.gff86faf
> 
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list