intel/blorp: Add support for RGB destinations in copies
authorJason Ekstrand <jason.ekstrand@intel.com>
Sat, 27 Aug 2016 19:07:31 +0000 (12:07 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 13 Sep 2016 02:42:57 +0000 (19:42 -0700)
Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/intel/blorp/blorp_blit.c
src/intel/blorp/blorp_priv.h

index 49c8648aee7660578e0a10e63746ebd2ca6b9f3a..0898ed45faa4e0d86cb8e9ad51980d073108d803 100644 (file)
@@ -1198,6 +1198,27 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp,
       }
    }
 
+   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 pick off the appropriate component
+       * 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)),
+                       nir_channel(&b, color, 0),
+                       nir_bcsel(&b, nir_ieq(&b, comp, nir_imm_int(&b, 1)),
+                                     nir_channel(&b, color, 1),
+                                     nir_channel(&b, color, 2)));
+
+      nir_ssa_def *u = nir_ssa_undef(&b, 1, 32);
+      color = nir_vec4(&b, color_component, u, u, u);
+   }
+
    nir_store_var(&b, v.color_out, color, 0xf);
 
    return b.shader;
@@ -1772,6 +1793,40 @@ surf_convert_to_uncompressed(const struct isl_device *isl_dev,
    info->surf.format = get_copy_format_for_bpb(fmtl->bpb);
 }
 
+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)
+{
+   surf_convert_to_single_slice(isl_dev, info);
+
+   info->surf.logical_level0_px.width *= 3;
+   info->surf.phys_level0_sa.width *= 3;
+   *x *= 3;
+   *width *= 3;
+
+   enum isl_format red_format;
+   switch (info->view.format) {
+   case ISL_FORMAT_R8G8B8_UNORM:
+      red_format = ISL_FORMAT_R8_UNORM;
+      break;
+   case ISL_FORMAT_R16G16B16_UNORM:
+      red_format = ISL_FORMAT_R16_UNORM;
+      break;
+   case ISL_FORMAT_R32G32B32_UINT:
+      red_format = ISL_FORMAT_R32_UINT;
+      break;
+   default:
+      unreachable("Invalid RGB copy destination format");
+   }
+   assert(isl_format_get_layout(red_format)->channels.r.type ==
+          isl_format_get_layout(info->view.format)->channels.r.type);
+   assert(isl_format_get_layout(red_format)->channels.r.bits ==
+          isl_format_get_layout(info->view.format)->channels.r.bits);
+
+   info->surf.format = info->view.format = red_format;
+}
+
 void
 blorp_copy(struct blorp_batch *batch,
            const struct blorp_surf *src_surf,
@@ -1818,6 +1873,13 @@ blorp_copy(struct blorp_batch *batch,
    uint32_t dst_width = src_width;
    uint32_t dst_height = src_height;
 
+   if (dst_fmtl->bpb % 3 == 0) {
+      surf_fake_rgb_with_red(batch->blorp->isl_dev, &params.dst,
+                             &dst_x, &dst_width);
+      wm_prog_key.dst_rgb = true;
+      wm_prog_key.need_dst_offset = true;
+   }
+
    do_blorp_blit(batch, &params, &wm_prog_key,
                  src_x, src_y, src_x + src_width, src_y + src_height,
                  dst_x, dst_y, dst_x + dst_width, dst_y + dst_height,
index 46ff272630af937e9a899d6a6206d958a545a2e1..a88d0f87ba1688dfb3cd2f4f9c87b3089be1a22a 100644 (file)
@@ -245,6 +245,13 @@ struct brw_blorp_blit_prog_key
     */
    bool dst_tiled_w;
 
+   /* True if the destination is an RGB format.  If true, the surface state
+    * for the render target must be configured as red with three times the
+    * normal width.  We need to do this because you cannot render to
+    * non-power-of-two formats.
+    */
+   bool dst_rgb;
+
    /* True if all source samples should be blended together to produce each
     * destination pixel.  If true, src_tiled_w must be false, tex_samples must
     * equal src_samples, and tex_samples must be nonzero.