From 293b8de16159912133fde59c62c58b42ad80e1af Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Sat, 21 Jan 2017 07:59:56 -0800 Subject: [PATCH] blorp: Handle the RGB workaround more like other workarounds The previous version was sort-of strapped on in that it just adjusted the blit rectangle and trusted in the fact that we would use texelFetch and round to the nearest integer to ensure that the component positions matched. This new version, while slightly more complicated, is more accurate because all three components end up with exactly the same dst_pos and so they will get interpolated and sampled at the same texture coordinate. This makes the workaround suitable for using with scaled blits. Reviewed-by: Topi Pohjolainen --- src/intel/blorp/blorp_blit.c | 60 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/intel/blorp/blorp_blit.c b/src/intel/blorp/blorp_blit.c index 0757db0d04b..7d717da0912 100644 --- a/src/intel/blorp/blorp_blit.c +++ b/src/intel/blorp/blorp_blit.c @@ -1155,6 +1155,20 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, key->dst_layout); } + nir_ssa_def *comp = NULL; + 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 + * component at a time. We need to save off the component and adjust + * the destination position. + */ + assert(dst_pos->num_components == 2); + nir_ssa_def *dst_x = nir_channel(&b, dst_pos, 0); + comp = nir_umod(&b, dst_x, nir_imm_int(&b, 3)); + dst_pos = nir_vec2(&b, nir_idiv(&b, dst_x, nir_imm_int(&b, 3)), + nir_channel(&b, dst_pos, 1)); + } + /* Now (X, Y, S) = decode_msaa(dst_samples, detile(dst_tiling, offset)). * * That is: X, Y and S now contain the true coordinates and sample index of @@ -1285,8 +1299,6 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx, * from the source color and write that to destination red. */ assert(dst_pos->num_components == 2); - nir_ssa_def *comp = - nir_umod(&b, nir_channel(&b, dst_pos, 0), nir_imm_int(&b, 3)); nir_ssa_def *color_component = nir_bcsel(&b, nir_ieq(&b, comp, nir_imm_int(&b, 0)), @@ -1549,16 +1561,13 @@ struct blt_coords { static void surf_fake_rgb_with_red(const struct isl_device *isl_dev, - struct brw_blorp_surface_info *info, - uint32_t *x, uint32_t *width) + struct brw_blorp_surface_info *info) { blorp_surf_convert_to_single_slice(isl_dev, info); info->surf.logical_level0_px.width *= 3; info->surf.phys_level0_sa.width *= 3; info->tile_x_sa *= 3; - *x *= 3; - *width *= 3; enum isl_format red_format; switch (info->view.format) { @@ -1588,28 +1597,6 @@ surf_fake_rgb_with_red(const struct isl_device *isl_dev, info->surf.format = info->view.format = red_format; } -static void -fake_dest_rgb_with_red(const struct isl_device *dev, - struct blorp_params *params, - struct brw_blorp_blit_prog_key *wm_prog_key, - struct blt_coords *coords) -{ - /* Handle RGB destinations for blorp_copy */ - const struct isl_format_layout *dst_fmtl = - isl_format_get_layout(params->dst.surf.format); - - if (dst_fmtl->bpb % 3 == 0) { - uint32_t dst_x = coords->x.dst0; - uint32_t dst_width = coords->x.dst1 - dst_x; - surf_fake_rgb_with_red(dev, ¶ms->dst, - &dst_x, &dst_width); - coords->x.dst0 = dst_x; - coords->x.dst1 = dst_x + dst_width; - wm_prog_key->dst_rgb = true; - wm_prog_key->need_dst_offset = true; - } -} - enum blit_shrink_status { BLIT_NO_SHRINK = 0, BLIT_WIDTH_SHRINK = 1, @@ -1628,8 +1615,6 @@ try_blorp_blit(struct blorp_batch *batch, { const struct gen_device_info *devinfo = batch->blorp->isl_dev->info; - fake_dest_rgb_with_red(batch->blorp->isl_dev, params, wm_prog_key, coords); - if (isl_format_has_sint_channel(params->src.view.format)) { wm_prog_key->texture_data_type = nir_type_int; } else if (isl_format_has_uint_channel(params->src.view.format)) { @@ -1835,6 +1820,21 @@ try_blorp_blit(struct blorp_batch *batch, params->src.view.base_level); } + if (isl_format_get_layout(params->dst.view.format)->bpb % 3 == 0) { + /* We can't render to RGB formats natively because they aren't a + * power-of-two size. Instead, we fake them by using a red format + * with the same channel type and size and emitting shader code to + * only write one channel at a time. + */ + params->x0 *= 3; + params->x1 *= 3; + + surf_fake_rgb_with_red(batch->blorp->isl_dev, ¶ms->dst); + + wm_prog_key->dst_rgb = true; + wm_prog_key->need_dst_offset = true; + } + if (params->src.tile_x_sa || params->src.tile_y_sa) { assert(wm_prog_key->need_src_offset); surf_get_intratile_offset_px(¶ms->src, -- 2.30.2