nir: Embed the shader_info in the nir_shader again
[mesa.git] / src / intel / blorp / blorp_blit.c
index b976eefef8e4d1feadb763790560a9ad03089a05..04ea98aaf5b8ba751b8102c6badf48b0aafda68f 100644 (file)
 #include "compiler/nir/nir_builder.h"
 
 #include "blorp_priv.h"
-#include "brw_meta_util.h"
+
+/* header-only include needed for _mesa_unorm_to_float and friends. */
+#include "mesa/main/format_utils.h"
 
 #define FILE_DEBUG_FLAG DEBUG_BLORP
 
+static const bool split_blorp_blit_debug = false;
+
 /**
  * Enum to specify the order of arguments in a sampler message
  */
@@ -93,7 +97,7 @@ blorp_blit_get_frag_coords(nir_builder *b,
                            const struct brw_blorp_blit_prog_key *key,
                            struct brw_blorp_blit_vars *v)
 {
-   nir_ssa_def *coord = nir_f2i(b, nir_load_var(b, v->frag_coord));
+   nir_ssa_def *coord = nir_f2i32(b, nir_load_var(b, v->frag_coord));
 
    /* Account for destination surface intratile offset
     *
@@ -760,7 +764,7 @@ blorp_nir_manual_blend_bilinear(nir_builder *b, nir_ssa_def *pos,
       nir_ssa_def *sample_off = nir_imm_vec2(b, sample_off_x, sample_off_y);
 
       nir_ssa_def *sample_coords = nir_fadd(b, pos_xy, sample_off);
-      nir_ssa_def *sample_coords_int = nir_f2i(b, sample_coords);
+      nir_ssa_def *sample_coords_int = nir_f2i32(b, sample_coords);
 
       /* The MCS value we fetch has to match up with the pixel that we're
        * sampling from. Since we sample from different pixels in each
@@ -817,7 +821,7 @@ blorp_nir_manual_blend_bilinear(nir_builder *b, nir_ssa_def *pos,
       nir_ssa_def *sample =
          nir_fdot2(b, frac, nir_imm_vec2(b, key->x_scale,
                                             key->x_scale * key->y_scale));
-      sample = nir_f2i(b, sample);
+      sample = nir_f2i32(b, sample);
 
       if (tex_samples == 8) {
          sample = nir_iand(b, nir_ishr(b, nir_imm_int(b, 0x64210573),
@@ -1146,7 +1150,7 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
       blorp_nir_discard_if_outside_rect(&b, dst_pos, &v);
    }
 
-   src_pos = blorp_blit_apply_transform(&b, nir_i2f(&b, dst_pos), &v);
+   src_pos = blorp_blit_apply_transform(&b, nir_i2f32(&b, dst_pos), &v);
    if (dst_pos->num_components == 3) {
       /* The sample coordinate is an integer that we want left alone but
        * blorp_blit_apply_transform() blindly applies the transform to all
@@ -1171,7 +1175,7 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
       /* Resolves (effecively) use texelFetch, so we need integers and we
        * don't care about the sample index if we got one.
        */
-      src_pos = nir_f2i(&b, nir_channels(&b, src_pos, 0x3));
+      src_pos = nir_f2i32(&b, nir_channels(&b, src_pos, 0x3));
 
       if (devinfo->gen == 6) {
          /* Because gen6 only supports 4x interleved MSAA, we can do all the
@@ -1183,7 +1187,7 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
           */
          src_pos = nir_ishl(&b, src_pos, nir_imm_int(&b, 1));
          src_pos = nir_iadd(&b, src_pos, nir_imm_int(&b, 1));
-         src_pos = nir_i2f(&b, src_pos);
+         src_pos = nir_i2f32(&b, src_pos);
          color = blorp_nir_tex(&b, &v, src_pos, key->texture_data_type);
       } else {
          /* Gen7+ hardware doesn't automaticaly blend. */
@@ -1200,11 +1204,11 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
       } else {
          /* We're going to use texelFetch, so we need integers */
          if (src_pos->num_components == 2) {
-            src_pos = nir_f2i(&b, src_pos);
+            src_pos = nir_f2i32(&b, src_pos);
          } else {
             assert(src_pos->num_components == 3);
-            src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i(&b, src_pos), 0),
-                                   nir_channel(&b, nir_f2i(&b, src_pos), 1),
+            src_pos = nir_vec3(&b, nir_channel(&b, nir_f2i32(&b, src_pos), 0),
+                                   nir_channel(&b, nir_f2i32(&b, src_pos), 1),
                                    nir_channel(&b, src_pos, 2));
          }
 
@@ -1281,14 +1285,14 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
    return b.shader;
 }
 
-static void
+static bool
 brw_blorp_get_blit_kernel(struct blorp_context *blorp,
                           struct blorp_params *params,
                           const struct brw_blorp_blit_prog_key *prog_key)
 {
    if (blorp->lookup_shader(blorp, prog_key, sizeof(*prog_key),
                             &params->wm_prog_kernel, &params->wm_prog_data))
-      return;
+      return true;
 
    void *mem_ctx = ralloc_context(NULL);
 
@@ -1297,6 +1301,8 @@ brw_blorp_get_blit_kernel(struct blorp_context *blorp,
    struct brw_wm_prog_data prog_data;
 
    nir_shader *nir = brw_blorp_build_nir_shader(blorp, mem_ctx, prog_key);
+   nir->info.name = ralloc_strdup(nir, "BLORP-blit");
+
    struct brw_wm_prog_key wm_key;
    brw_blorp_init_wm_prog_key(&wm_key);
    wm_key.tex.compressed_multisample_layout_mask =
@@ -1307,12 +1313,14 @@ brw_blorp_get_blit_kernel(struct blorp_context *blorp,
    program = blorp_compile_fs(blorp, mem_ctx, nir, &wm_key, false,
                               &prog_data, &program_size);
 
-   blorp->upload_shader(blorp, prog_key, sizeof(*prog_key),
-                        program, program_size,
-                        &prog_data.base, sizeof(prog_data),
-                        &params->wm_prog_kernel, &params->wm_prog_data);
+   bool result =
+      blorp->upload_shader(blorp, prog_key, sizeof(*prog_key),
+                           program, program_size,
+                           &prog_data.base, sizeof(prog_data),
+                           &params->wm_prog_kernel, &params->wm_prog_data);
 
    ralloc_free(mem_ctx);
+   return result;
 }
 
 static void
@@ -1367,6 +1375,8 @@ static void
 surf_convert_to_single_slice(const struct isl_device *isl_dev,
                              struct brw_blorp_surface_info *info)
 {
+   bool ok UNUSED;
+
    /* Just bail if we have nothing to do. */
    if (info->surf.dim == ISL_SURF_DIM_2D &&
        info->view.base_level == 0 && info->view.base_array_layer == 0 &&
@@ -1413,13 +1423,13 @@ surf_convert_to_single_slice(const struct isl_device *isl_dev,
       .levels = 1,
       .array_len = 1,
       .samples = info->surf.samples,
-      .min_pitch = info->surf.row_pitch,
+      .row_pitch = info->surf.row_pitch,
       .usage = info->surf.usage,
       .tiling_flags = 1 << info->surf.tiling,
    };
 
-   isl_surf_init_s(isl_dev, &info->surf, &init_info);
-   assert(info->surf.row_pitch == init_info.min_pitch);
+   ok = isl_surf_init_s(isl_dev, &info->surf, &init_info);
+   assert(ok);
 
    /* The view is also different now. */
    info->view.base_level = 0;
@@ -1484,10 +1494,47 @@ surf_retile_w_to_y(const struct isl_device *isl_dev,
    info->tile_y_sa /= 2;
 }
 
+static bool
+can_shrink_surface(const struct brw_blorp_surface_info *surf)
+{
+   /* The current code doesn't support offsets into the aux buffers. This
+    * should be possible, but we need to make sure the offset is page
+    * aligned for both the surface and the aux buffer surface. Generally
+    * this mean using the page aligned offset for the aux buffer.
+    *
+    * Currently the cases where we must split the blit are limited to cases
+    * where we don't have a aux buffer.
+    */
+   if (surf->aux_addr.buffer != NULL)
+      return false;
+
+   /* We can't support splitting the blit for gen <= 7, because the qpitch
+    * size is calculated by the hardware based on the surface height for
+    * gen <= 7. In gen >= 8, the qpitch is controlled by the driver.
+    */
+   if (surf->surf.msaa_layout == ISL_MSAA_LAYOUT_ARRAY)
+      return false;
+
+   return true;
+}
+
 static bool
 can_shrink_surfaces(const struct blorp_params *params)
 {
-   return false;
+   return
+      can_shrink_surface(&params->src) &&
+      can_shrink_surface(&params->dst);
+}
+
+static unsigned
+get_max_surface_size(const struct gen_device_info *devinfo,
+                     const struct blorp_params *params)
+{
+   const unsigned max = devinfo->gen >= 7 ? 16384 : 8192;
+   if (split_blorp_blit_debug && can_shrink_surfaces(params))
+      return max >> 4; /* A smaller restriction when debug is enabled */
+   else
+      return max;
 }
 
 struct blt_axis {
@@ -1499,6 +1546,68 @@ struct blt_coords {
    struct blt_axis x, y;
 };
 
+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_R8G8B8_UINT:
+      red_format = ISL_FORMAT_R8_UINT;
+      break;
+   case ISL_FORMAT_R16G16B16_UNORM:
+      red_format = ISL_FORMAT_R16_UNORM;
+      break;
+   case ISL_FORMAT_R16G16B16_UINT:
+      red_format = ISL_FORMAT_R16_UINT;
+      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;
+}
+
+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, &params->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,
@@ -1513,10 +1622,12 @@ static enum blit_shrink_status
 try_blorp_blit(struct blorp_batch *batch,
                struct blorp_params *params,
                struct brw_blorp_blit_prog_key *wm_prog_key,
-               const struct blt_coords *coords)
+               struct blt_coords *coords)
 {
    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)) {
@@ -1714,9 +1825,17 @@ try_blorp_blit(struct blorp_batch *batch,
    /* For some texture types, we need to pass the layer through the sampler. */
    params->wm_inputs.src_z = params->src.z_offset;
 
-   brw_blorp_get_blit_kernel(batch->blorp, params, wm_prog_key);
+   if (!brw_blorp_get_blit_kernel(batch->blorp, params, wm_prog_key))
+      return 0;
 
    unsigned result = 0;
+   unsigned max_surface_size = get_max_surface_size(devinfo, params);
+   if (params->src.surf.logical_level0_px.width > max_surface_size ||
+       params->dst.surf.logical_level0_px.width > max_surface_size)
+      result |= BLIT_WIDTH_SHRINK;
+   if (params->src.surf.logical_level0_px.height > max_surface_size ||
+       params->dst.surf.logical_level0_px.height > max_surface_size)
+      result |= BLIT_HEIGHT_SHRINK;
 
    if (result == 0) {
       batch->blorp->exec(batch, params);
@@ -1744,7 +1863,7 @@ adjust_split_source_coords(const struct blt_axis *orig,
    split_coords->src1 = orig->src1 + (scale >= 0.0 ? delta1 : delta0);
 }
 
-static const struct isl_extent2d
+static struct isl_extent2d
 get_px_size_sa(const struct isl_surf *surf)
 {
    static const struct isl_extent2d one_to_one = { .w = 1, .h = 1 };
@@ -1837,7 +1956,7 @@ do_blorp_blit(struct blorp_batch *batch,
       y_scale = -y_scale;
 
    bool x_done, y_done;
-   bool shrink = false;
+   bool shrink = split_blorp_blit_debug && can_shrink_surfaces(orig_params);
    do {
       params = *orig_params;
       blit_coords = split_coords;
@@ -2094,6 +2213,75 @@ get_ccs_compatible_uint_format(const struct isl_format_layout *fmtl)
    }
 }
 
+/* Takes an isl_color_value and returns a color value that is the original
+ * color value only bit-casted to a UINT format.  This value, together with
+ * the format from get_ccs_compatible_uint_format, will yield the same bit
+ * value as the original color and format.
+ */
+static union isl_color_value
+bitcast_color_value_to_uint(union isl_color_value color,
+                            const struct isl_format_layout *fmtl)
+{
+   /* All CCS formats have the same number of bits in each channel */
+   const struct isl_channel_layout *chan = &fmtl->channels.r;
+
+   union isl_color_value bits;
+   switch (chan->type) {
+   case ISL_UINT:
+   case ISL_SINT:
+      /* Hardware will ignore the high bits so there's no need to cast */
+      bits = color;
+      break;
+
+   case ISL_UNORM:
+      for (unsigned i = 0; i < 4; i++)
+         bits.u32[i] = _mesa_float_to_unorm(color.f32[i], chan->bits);
+      break;
+
+   case ISL_SNORM:
+      for (unsigned i = 0; i < 4; i++)
+         bits.i32[i] = _mesa_float_to_snorm(color.f32[i], chan->bits);
+      break;
+
+   case ISL_SFLOAT:
+      switch (chan->bits) {
+      case 16:
+         for (unsigned i = 0; i < 4; i++)
+            bits.u32[i] = _mesa_float_to_half(color.f32[i]);
+         break;
+
+      case 32:
+         bits = color;
+         break;
+
+      default:
+         unreachable("Invalid float format size");
+      }
+      break;
+
+   default:
+      unreachable("Invalid channel type");
+   }
+
+   switch (fmtl->format) {
+   case ISL_FORMAT_B8G8R8A8_UNORM:
+   case ISL_FORMAT_B8G8R8A8_UNORM_SRGB:
+   case ISL_FORMAT_B8G8R8X8_UNORM:
+   case ISL_FORMAT_B8G8R8X8_UNORM_SRGB: {
+      /* If it's a BGRA format, we need to swap blue and red */
+      uint32_t tmp = bits.u32[0];
+      bits.u32[0] = bits.u32[2];
+      bits.u32[2] = tmp;
+      break;
+   }
+
+   default:
+      break; /* Nothing to do */
+   }
+
+   return bits;
+}
+
 static void
 surf_convert_to_uncompressed(const struct isl_device *isl_dev,
                              struct brw_blorp_surface_info *info,
@@ -2149,46 +2337,6 @@ surf_convert_to_uncompressed(const struct isl_device *isl_dev,
    info->surf.format = get_copy_format_for_bpb(isl_dev, 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_R8G8B8_UINT:
-      red_format = ISL_FORMAT_R8_UINT;
-      break;
-   case ISL_FORMAT_R16G16B16_UNORM:
-      red_format = ISL_FORMAT_R16_UNORM;
-      break;
-   case ISL_FORMAT_R16G16B16_UINT:
-      red_format = ISL_FORMAT_R16_UINT;
-      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,
@@ -2250,6 +2398,22 @@ blorp_copy(struct blorp_batch *batch,
       params.src.view.format = get_copy_format_for_bpb(isl_dev, src_fmtl->bpb);
    }
 
+   if (params.src.aux_usage == ISL_AUX_USAGE_CCS_E) {
+      assert(isl_formats_are_ccs_e_compatible(batch->blorp->isl_dev->info,
+                                              src_surf->surf->format,
+                                              params.src.view.format));
+      params.src.clear_color =
+         bitcast_color_value_to_uint(params.src.clear_color, src_fmtl);
+   }
+
+   if (params.dst.aux_usage == ISL_AUX_USAGE_CCS_E) {
+      assert(isl_formats_are_ccs_e_compatible(batch->blorp->isl_dev->info,
+                                              dst_surf->surf->format,
+                                              params.dst.view.format));
+      params.dst.clear_color =
+         bitcast_color_value_to_uint(params.dst.clear_color, dst_fmtl);
+   }
+
    wm_prog_key.src_bpc =
       isl_format_get_layout(params.src.view.format)->channels.r.bits;
    wm_prog_key.dst_bpc =
@@ -2273,13 +2437,6 @@ 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;
-   }
-
    struct blt_coords coords = {
       .x = {
          .src0 = src_x,