From 804856fa5735164cc0733ad0ea62adad39b00ae2 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 20 Jan 2017 22:12:06 -0800 Subject: [PATCH] intel/blorp: Handle more exotic destination formats This commit adds support for the following formats as destination formats even though the hardware does not support rendering to them: - ISL_FORMAT_R24_UNORM_X8_TYPELESS - ISL_FORMAT_A4B4G4R4_UNORM - ISL_FORMAT_L8_UNORM_SRGB - ISL_FORMAT_R9G9B9E5_SHAREDEXP This is done by using a different format and emitting shader code to fake it the rest of the way. Reviewed-by: Topi Pohjolainen --- src/intel/blorp/blorp_blit.c | 48 ++++++++++++++++++++++++++++++++++++ src/intel/blorp/blorp_priv.h | 6 +++++ 2 files changed, 54 insertions(+) diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index d54dd1ecc0d..8b64cd7bad2 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -26,6 +26,7 @@ #include "blorp_priv.h" +#include "util/format_rgb9e5.h" /* header-only include needed for _mesa_unorm_to_float and friends. */ #include "mesa/main/format_utils.h" @@ -949,6 +950,36 @@ swizzle_color(struct nir_builder *b, nir_ssa_def *color, select_color_channel(b, color, data_type, swizzle.a)); } +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_L8_UNORM_SRGB) { + value = nir_format_linear_to_srgb(b, color); + } else if (key->dst_format == ISL_FORMAT_R9G9B9E5_SHAREDEXP) { + value = nir_format_pack_r9g9b9e5(b, color); + } 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. * @@ -1321,6 +1352,9 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, 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 @@ -1862,6 +1896,20 @@ 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_A4B4G4R4_UNORM) { + params->dst.view.swizzle = + isl_swizzle_compose(params->dst.view.swizzle, + ISL_SWIZZLE(ALPHA, RED, GREEN, BLUE)); + params->dst.view.format = ISL_FORMAT_B4G4R4A4_UNORM; + } else if (params->dst.view.format == ISL_FORMAT_L8_UNORM_SRGB) { + wm_prog_key->dst_format = params->dst.view.format; + params->dst.view.format = ISL_FORMAT_R8_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 (devinfo->gen <= 7 && !devinfo->is_haswell && diff --git a/src/intel/blorp/blorp_priv.h b/src/intel/blorp/blorp_priv.h index 1c2cb20acf0..97f5d298339 100644 --- a/src/intel/blorp/blorp_priv.h +++ b/src/intel/blorp/blorp_priv.h @@ -272,6 +272,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.30.2