[Mesa-dev] [PATCH 2/7] intel/blorp: Handle more exotic destination formats
Jason Ekstrand
jason at jlekstrand.net
Tue Jan 24 23:45:49 UTC 2017
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.
---
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
More information about the mesa-dev
mailing list