blorp: Write to depth/stencil images as depth/stencil when possible
authorJason Ekstrand <jason@jlekstrand.net>
Wed, 5 Feb 2020 09:59:01 +0000 (03:59 -0600)
committerMarge Bot <eric+marge@anholt.net>
Thu, 5 Mar 2020 18:56:45 +0000 (18:56 +0000)
On Gen4 and G45 and earlier, we have to handle weird offsetting to write
to depth and stencil due to a lack of proper depth mipmapping support in
hardware.  On Gen6, we have to deal with strange HiZ and stencil
layouts.  Prior to Gen9, we also had to do crazy things for stencil
writes because we didn't support GL_ARB_shader_stencil_export and
friends in hardware.  However, starting with Gen7 for depth and Gen9 for
stencil, we can easily write out with the "right" hardware.  This allows
us to leave HiZ and other compression enabled for blorp_blit() and
blorp_copy() operations.

Reviewed-by: Nanley Chery <nanley.g.chery@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3717>

src/intel/blorp/blorp_blit.c
src/intel/blorp/blorp_genX_exec.h
src/intel/blorp/blorp_priv.h

index 5c38ba6adb6f982c062a83ca649bfbc0873a811b..cff57a356acf94cdc772dece42ca789e31501fd1 100644 (file)
@@ -59,9 +59,6 @@ struct brw_blorp_blit_vars {
    nir_variable *v_src_offset;
    nir_variable *v_dst_offset;
    nir_variable *v_src_inv_size;
-
-   /* gl_FragColor */
-   nir_variable *color_out;
 };
 
 static void
@@ -80,10 +77,6 @@ brw_blorp_blit_vars_init(nir_builder *b, struct brw_blorp_blit_vars *v,
    LOAD_INPUT(src_inv_size, glsl_vector_type(GLSL_TYPE_FLOAT, 2))
 
 #undef LOAD_INPUT
-
-   v->color_out = nir_variable_create(b->shader, nir_var_shader_out,
-                                      glsl_vec4_type(), "gl_FragColor");
-   v->color_out->data.location = FRAG_RESULT_COLOR;
 }
 
 static nir_ssa_def *
@@ -1472,7 +1465,27 @@ brw_blorp_build_nir_shader(struct blorp_context *blorp, void *mem_ctx,
       color = nir_vec4(&b, color_component, u, u, u);
    }
 
-   nir_store_var(&b, v.color_out, color, 0xf);
+   if (key->dst_usage == ISL_SURF_USAGE_RENDER_TARGET_BIT) {
+      nir_variable *color_out =
+         nir_variable_create(b.shader, nir_var_shader_out,
+                             glsl_vec4_type(), "gl_FragColor");
+      color_out->data.location = FRAG_RESULT_COLOR;
+      nir_store_var(&b, color_out, color, 0xf);
+   } else if (key->dst_usage == ISL_SURF_USAGE_DEPTH_BIT) {
+      nir_variable *depth_out =
+         nir_variable_create(b.shader, nir_var_shader_out,
+                             glsl_float_type(), "gl_FragDepth");
+      depth_out->data.location = FRAG_RESULT_DEPTH;
+      nir_store_var(&b, depth_out, nir_channel(&b, color, 0), 0x1);
+   } else if (key->dst_usage == ISL_SURF_USAGE_STENCIL_BIT) {
+      nir_variable *stencil_out =
+         nir_variable_create(b.shader, nir_var_shader_out,
+                             glsl_int_type(), "gl_FragStencilRef");
+      stencil_out->data.location = FRAG_RESULT_STENCIL;
+      nir_store_var(&b, stencil_out, nir_channel(&b, color, 0), 0x1);
+   } else {
+      unreachable("Invalid destination usage");
+   }
 
    return b.shader;
 }
@@ -1808,6 +1821,30 @@ try_blorp_blit(struct blorp_batch *batch,
 {
    const struct gen_device_info *devinfo = batch->blorp->isl_dev->info;
 
+   if (params->dst.surf.usage & ISL_SURF_USAGE_DEPTH_BIT) {
+      if (devinfo->gen >= 7) {
+         /* We can render as depth on Gen5 but there's no real advantage since
+          * it doesn't support MSAA or HiZ.  On Gen4, we can't always render
+          * to depth due to issues with depth buffers and mip-mapping.  On
+          * Gen6, we can do everything but we have weird offsetting for HiZ
+          * and stencil.  It's easier to just render using the color pipe
+          * on those platforms.
+          */
+         wm_prog_key->dst_usage = ISL_SURF_USAGE_DEPTH_BIT;
+      } else {
+         wm_prog_key->dst_usage = ISL_SURF_USAGE_RENDER_TARGET_BIT;
+      }
+   } else if (params->dst.surf.usage & ISL_SURF_USAGE_STENCIL_BIT) {
+      assert(params->dst.surf.format == ISL_FORMAT_R8_UINT);
+      if (devinfo->gen >= 9) {
+         wm_prog_key->dst_usage = ISL_SURF_USAGE_STENCIL_BIT;
+      } else {
+         wm_prog_key->dst_usage = ISL_SURF_USAGE_RENDER_TARGET_BIT;
+      }
+   } else {
+      wm_prog_key->dst_usage = ISL_SURF_USAGE_RENDER_TARGET_BIT;
+   }
+
    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)) {
@@ -1862,6 +1899,7 @@ try_blorp_blit(struct blorp_batch *batch,
    }
 
    if (devinfo->gen > 6 &&
+       !isl_surf_usage_is_depth_or_stencil(wm_prog_key->dst_usage) &&
        params->dst.surf.msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED) {
       assert(params->dst.surf.samples > 1);
 
@@ -1890,7 +1928,8 @@ try_blorp_blit(struct blorp_batch *batch,
       wm_prog_key->need_dst_offset = true;
    }
 
-   if (params->dst.surf.tiling == ISL_TILING_W) {
+   if (params->dst.surf.tiling == ISL_TILING_W &&
+       wm_prog_key->dst_usage != ISL_SURF_USAGE_STENCIL_BIT) {
       /* We must modify the rectangle we send through the rendering pipeline
        * (and the size and x/y offset of the destination surface), to account
        * for the fact that we are mapping it as Y-tiled when it is in fact
@@ -2034,7 +2073,8 @@ try_blorp_blit(struct blorp_batch *batch,
       /* We can handle RGBX formats easily enough by treating them as RGBA */
       params->dst.view.format =
          isl_format_rgbx_to_rgba(params->dst.view.format);
-   } else if (params->dst.view.format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) {
+   } else if (params->dst.view.format == ISL_FORMAT_R24_UNORM_X8_TYPELESS &&
+              wm_prog_key->dst_usage != ISL_SURF_USAGE_DEPTH_BIT) {
       wm_prog_key->dst_format = params->dst.view.format;
       params->dst.view.format = ISL_FORMAT_R32_UINT;
    } else if (params->dst.view.format == ISL_FORMAT_A4B4G4R4_UNORM) {
@@ -2106,6 +2146,15 @@ try_blorp_blit(struct blorp_batch *batch,
       result |= BLIT_DST_HEIGHT_SHRINK;
 
    if (result == 0) {
+      if (wm_prog_key->dst_usage == ISL_SURF_USAGE_DEPTH_BIT) {
+         params->depth = params->dst;
+         memset(&params->dst, 0, sizeof(params->dst));
+      } else if (wm_prog_key->dst_usage == ISL_SURF_USAGE_STENCIL_BIT) {
+         params->stencil = params->dst;
+         params->stencil_mask = 0xff;
+         memset(&params->dst, 0, sizeof(params->dst));
+      }
+
       batch->blorp->exec(batch, params);
    }
 
@@ -2628,18 +2677,20 @@ blorp_copy(struct blorp_batch *batch,
           params.src.aux_usage == ISL_AUX_USAGE_MCS ||
           params.src.aux_usage == ISL_AUX_USAGE_MCS_CCS ||
           params.src.aux_usage == ISL_AUX_USAGE_CCS_E);
-   assert(params.dst.aux_usage == ISL_AUX_USAGE_NONE ||
-          params.dst.aux_usage == ISL_AUX_USAGE_MCS ||
-          params.dst.aux_usage == ISL_AUX_USAGE_MCS_CCS ||
-          params.dst.aux_usage == ISL_AUX_USAGE_CCS_E);
 
    if (params.src.aux_usage == ISL_AUX_USAGE_HIZ) {
-      /* Depth <-> Color copies are not allowed and HiZ isn't allowed in
-       * destinations because we draw as color.
+      /* In order to use HiZ, we have to use the real format for the source.
+       * Depth <-> Color copies are not allowed.
        */
-      assert(params.dst.aux_usage == ISL_AUX_USAGE_NONE);
       params.src.view.format = params.src.surf.format;
       params.dst.view.format = params.src.surf.format;
+   } else if ((params.dst.surf.usage & ISL_SURF_USAGE_DEPTH_BIT) &&
+              isl_dev->info->gen >= 7) {
+      /* On Gen7 and higher, we use actual depth writes for blits into depth
+       * buffers so we need the real format.
+       */
+      params.src.view.format = params.dst.surf.format;
+      params.dst.view.format = params.dst.surf.format;
    } else if (params.dst.aux_usage == ISL_AUX_USAGE_CCS_E) {
       params.dst.view.format = get_ccs_compatible_copy_format(dst_fmtl);
       if (params.src.aux_usage == ISL_AUX_USAGE_CCS_E) {
index 50ac4489a52bdcdb60ee528988e8169f2d6a6405..a77cff3716c86de62065ecfba1355ecc7854e0c7 100644 (file)
@@ -902,6 +902,10 @@ blorp_emit_ps_config(struct blorp_batch *batch,
          psx.PixelShaderValid = true;
          psx.AttributeEnable = prog_data->num_varying_inputs > 0;
          psx.PixelShaderIsPerSample = prog_data->persample_dispatch;
+         psx.PixelShaderComputedDepthMode = prog_data->computed_depth_mode;
+#if GEN_GEN >= 9
+         psx.PixelShaderComputesStencil = prog_data->computed_stencil;
+#endif
       }
 
       if (params->src.enabled)
@@ -927,8 +931,10 @@ blorp_emit_ps_config(struct blorp_batch *batch,
          unreachable("not reached");
       }
 
-      if (prog_data)
+      if (prog_data) {
          wm.ThreadDispatchEnable = true;
+         wm.PixelShaderComputedDepthMode = prog_data->computed_depth_mode;
+      }
 
       if (params->src.enabled)
          wm.PixelShaderKillsPixel = true;
index ddd118f134944d222d027eaae0f0a2e2cce072e0..63b0ce9a88d8560a22fac9aab86cd323bf823c3e 100644 (file)
@@ -319,6 +319,8 @@ struct brw_blorp_blit_prog_key
     */
    bool dst_rgb;
 
+   isl_surf_usage_flags_t dst_usage;
+
    enum blorp_filter filter;
 
    /* True if the rectangle being sent through the rendering pipeline might be