intel/isl: Add support for emitting depth/stencil/hiz
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 30 Mar 2017 04:10:50 +0000 (21:10 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Mon, 10 Apr 2017 14:57:21 +0000 (07:57 -0700)
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/intel/Makefile.sources
src/intel/isl/isl.c
src/intel/isl/isl.h
src/intel/isl/isl_emit_depth_stencil.c [new file with mode: 0644]
src/intel/isl/isl_priv.h

index aa04c0789856abe080337f0f09f45d45c755e9b9..d7bc09ef7a8beda638bc6df4b42c7f17a7dedc88 100644 (file)
@@ -144,32 +144,39 @@ ISL_FILES = \
 ISL_GEN4_FILES = \
        isl/isl_gen4.c \
        isl/isl_gen4.h \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GEN5_FILES = \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GEN6_FILES = \
        isl/isl_gen6.c \
        isl/isl_gen6.h \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GEN7_FILES = \
        isl/isl_gen7.c \
        isl/isl_gen7.h \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GEN75_FILES = \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GEN8_FILES = \
        isl/isl_gen8.c \
        isl/isl_gen8.h \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GEN9_FILES = \
        isl/isl_gen9.c \
        isl/isl_gen9.h \
+       isl/isl_emit_depth_stencil.c \
        isl/isl_surface_state.c
 
 ISL_GENERATED_FILES = \
index 4e899912260982b0180599751843e96b3443534c..f89f351c15771c3fc087a2a22b03e5af24450b2b 100644 (file)
@@ -83,6 +83,32 @@ isl_device_init(struct isl_device *dev,
     */
    dev->ss.aux_addr_offset =
       (RENDER_SURFACE_STATE_AuxiliarySurfaceBaseAddress_start(info) & ~31) / 8;
+
+   dev->ds.size =
+      _3DSTATE_DEPTH_BUFFER_length(info) * 4 +
+      _3DSTATE_STENCIL_BUFFER_length(info) * 4 +
+      _3DSTATE_HIER_DEPTH_BUFFER_length(info) * 4 +
+      _3DSTATE_CLEAR_PARAMS_length(info) * 4;
+
+   assert(_3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0);
+   dev->ds.depth_offset =
+      _3DSTATE_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8;
+
+   if (info->has_hiz_and_separate_stencil) {
+      assert(_3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0);
+      dev->ds.stencil_offset =
+         _3DSTATE_DEPTH_BUFFER_length(info) * 4 +
+         _3DSTATE_STENCIL_BUFFER_SurfaceBaseAddress_start(info) / 8;
+
+      assert(_3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) % 8 == 0);
+      dev->ds.hiz_offset =
+         _3DSTATE_DEPTH_BUFFER_length(info) * 4 +
+         _3DSTATE_STENCIL_BUFFER_length(info) * 4 +
+         _3DSTATE_HIER_DEPTH_BUFFER_SurfaceBaseAddress_start(info) / 8;
+   } else {
+      dev->ds.stencil_offset = 0;
+      dev->ds.hiz_offset = 0;
+   }
 }
 
 /**
@@ -1684,6 +1710,73 @@ isl_buffer_fill_state_s(const struct isl_device *dev, void *state,
    }
 }
 
+void
+isl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                             const struct isl_depth_stencil_hiz_emit_info *restrict info)
+{
+   if (info->depth_surf && info->stencil_surf) {
+      if (!dev->info->has_hiz_and_separate_stencil) {
+         assert(info->depth_surf == info->stencil_surf);
+         assert(info->depth_address == info->stencil_address);
+      }
+      assert(info->depth_surf->dim == info->stencil_surf->dim);
+   }
+
+   if (info->depth_surf) {
+      assert((info->depth_surf->usage & ISL_SURF_USAGE_DEPTH_BIT));
+      if (info->depth_surf->dim == ISL_SURF_DIM_3D) {
+         assert(info->view->base_array_layer + info->view->array_len <=
+                info->depth_surf->logical_level0_px.depth);
+      } else {
+         assert(info->view->base_array_layer + info->view->array_len <=
+                info->depth_surf->logical_level0_px.array_len);
+      }
+   }
+
+   if (info->stencil_surf) {
+      assert((info->stencil_surf->usage & ISL_SURF_USAGE_STENCIL_BIT));
+      if (info->stencil_surf->dim == ISL_SURF_DIM_3D) {
+         assert(info->view->base_array_layer + info->view->array_len <=
+                info->stencil_surf->logical_level0_px.depth);
+      } else {
+         assert(info->view->base_array_layer + info->view->array_len <=
+                info->stencil_surf->logical_level0_px.array_len);
+      }
+   }
+
+   switch (ISL_DEV_GEN(dev)) {
+   case 4:
+      if (ISL_DEV_IS_G4X(dev)) {
+         /* G45 surface state is the same as gen5 */
+         isl_gen5_emit_depth_stencil_hiz_s(dev, batch, info);
+      } else {
+         isl_gen4_emit_depth_stencil_hiz_s(dev, batch, info);
+      }
+      break;
+   case 5:
+      isl_gen5_emit_depth_stencil_hiz_s(dev, batch, info);
+      break;
+   case 6:
+      isl_gen6_emit_depth_stencil_hiz_s(dev, batch, info);
+      break;
+   case 7:
+      if (ISL_DEV_IS_HASWELL(dev)) {
+         isl_gen75_emit_depth_stencil_hiz_s(dev, batch, info);
+      } else {
+         isl_gen7_emit_depth_stencil_hiz_s(dev, batch, info);
+      }
+      break;
+   case 8:
+      isl_gen8_emit_depth_stencil_hiz_s(dev, batch, info);
+      break;
+   case 9:
+      isl_gen9_emit_depth_stencil_hiz_s(dev, batch, info);
+      break;
+   default:
+      assert(!"Cannot fill surface state for this gen");
+   }
+}
+
 /**
  * A variant of isl_surf_get_image_offset_sa() specific to
  * ISL_DIM_LAYOUT_GEN4_2D.
index 17b52cf2f4f6446220f64c8470a657b6f006f16b..1172c4e82b0c65d0d180ce9253c2d941dc989634 100644 (file)
@@ -682,6 +682,17 @@ struct isl_device {
       uint8_t addr_offset;
       uint8_t aux_addr_offset;
    } ss;
+
+   /**
+    * Describes the layout of the depth/stencil/hiz commands as emitted by
+    * isl_emit_depth_stencil_hiz.
+    */
+   struct {
+      uint8_t size;
+      uint8_t depth_offset;
+      uint8_t stencil_offset;
+      uint8_t hiz_offset;
+   } ds;
 };
 
 struct isl_extent2d {
@@ -1017,6 +1028,61 @@ struct isl_buffer_fill_state_info {
    uint32_t stride;
 };
 
+struct isl_depth_stencil_hiz_emit_info {
+   /**
+    * The depth surface
+    */
+   const struct isl_surf *depth_surf;
+
+   /**
+    * The stencil surface
+    *
+    * If separate stencil is not available, this must point to the same
+    * isl_surf as depth_surf.
+    */
+   const struct isl_surf *stencil_surf;
+
+   /**
+    * The view into the depth and stencil surfaces.
+    *
+    * This view applies to both surfaces simultaneously.
+    */
+   const struct isl_view *view;
+
+   /**
+    * The address of the depth surface in GPU memory
+    */
+   uint64_t depth_address;
+
+   /**
+    * The address of the stencil surface in GPU memory
+    *
+    * If separate stencil is not available, this must have the same value as
+    * depth_address.
+    */
+   uint64_t stencil_address;
+
+   /**
+    * The Memory Object Control state for depth and stencil buffers
+    *
+    * Both depth and stencil will get the same MOCS value.  The exact format
+    * of this value depends on hardware generation.
+    */
+   uint32_t mocs;
+
+   /**
+    * The HiZ surfae or NULL if HiZ is disabled.
+    */
+   const struct isl_surf *hiz_surf;
+   enum isl_aux_usage hiz_usage;
+   uint64_t hiz_address;
+
+   /**
+    * The depth clear value
+    */
+   float depth_clear_value;
+};
+
 extern const struct isl_format_layout isl_format_layouts[];
 
 void
@@ -1315,6 +1381,14 @@ void
 isl_buffer_fill_state_s(const struct isl_device *dev, void *state,
                         const struct isl_buffer_fill_state_info *restrict info);
 
+#define isl_emit_depth_stencil_hiz(dev, batch, ...) \
+   isl_emit_depth_stencil_hiz_s((dev), (batch), \
+                                &(struct isl_depth_stencil_hiz_emit_info) {  __VA_ARGS__ })
+
+void
+isl_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                             const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
 void
 isl_surf_fill_image_param(const struct isl_device *dev,
                           struct brw_image_param *param,
diff --git a/src/intel/isl/isl_emit_depth_stencil.c b/src/intel/isl/isl_emit_depth_stencil.c
new file mode 100644 (file)
index 0000000..4869659
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2016 Intel Corporation
+ *
+ *  Permission is hereby granted, free of charge, to any person obtaining a
+ *  copy of this software and associated documentation files (the "Software"),
+ *  to deal in the Software without restriction, including without limitation
+ *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ *  and/or sell copies of the Software, and to permit persons to whom the
+ *  Software is furnished to do so, subject to the following conditions:
+ *
+ *  The above copyright notice and this permission notice (including the next
+ *  paragraph) shall be included in all copies or substantial portions of the
+ *  Software.
+ *
+ *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ *  IN THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#define __gen_address_type uint64_t
+#define __gen_user_data void
+
+static inline uint64_t
+__gen_combine_address(void *data, void *loc, uint64_t addr, uint32_t delta)
+{
+   return addr + delta;
+}
+
+#include "genxml/gen_macros.h"
+#include "genxml/genX_pack.h"
+
+#include "isl_priv.h"
+
+#define __PASTE2(x, y) x ## y
+#define __PASTE(x, y) __PASTE2(x, y)
+#define isl_genX(x) __PASTE(isl_, genX(x))
+
+static const uint32_t isl_to_gen_ds_surftype [] = {
+#if GEN_GEN >= 9
+   /* From the SKL PRM, "3DSTATE_DEPTH_STENCIL::SurfaceType":
+    *
+    *    "If depth/stencil is enabled with 1D render target, depth/stencil
+    *    surface type needs to be set to 2D surface type and height set to 1.
+    *    Depth will use (legacy) TileY and stencil will use TileW. For this
+    *    case only, the Surface Type of the depth buffer can be 2D while the
+    *    Surface Type of the render target(s) are 1D, representing an
+    *    exception to a programming note above.
+    */
+   [ISL_SURF_DIM_1D] = SURFTYPE_2D,
+#else
+   [ISL_SURF_DIM_1D] = SURFTYPE_1D,
+#endif
+   [ISL_SURF_DIM_2D] = SURFTYPE_2D,
+   [ISL_SURF_DIM_3D] = SURFTYPE_3D,
+};
+
+void
+isl_genX(emit_depth_stencil_hiz_s)(const struct isl_device *dev, void *batch,
+                                   const struct isl_depth_stencil_hiz_emit_info *restrict info)
+{
+   struct GENX(3DSTATE_DEPTH_BUFFER) db = {
+      GENX(3DSTATE_DEPTH_BUFFER_header),
+   };
+
+   if (info->depth_surf) {
+      db.SurfaceType = isl_to_gen_ds_surftype[info->depth_surf->dim];
+      db.SurfaceFormat = isl_surf_get_depth_format(dev, info->depth_surf);
+      db.Width = info->depth_surf->logical_level0_px.width - 1;
+      db.Height = info->depth_surf->logical_level0_px.height - 1;
+   } else if (info->stencil_surf) {
+      db.SurfaceType = isl_to_gen_ds_surftype[info->stencil_surf->dim];
+      db.SurfaceFormat = D32_FLOAT;
+      db.Width = info->stencil_surf->logical_level0_px.width - 1;
+      db.Height = info->stencil_surf->logical_level0_px.height - 1;
+   } else {
+      db.SurfaceType = SURFTYPE_NULL;
+      db.SurfaceFormat = D32_FLOAT;
+   }
+
+   if (info->depth_surf || info->stencil_surf) {
+      /* These are based entirely on the view */
+      db.Depth = db.RenderTargetViewExtent = info->view->array_len - 1;
+      db.LOD                  = info->view->base_level;
+      db.MinimumArrayElement  = info->view->base_array_layer;
+   }
+
+   if (info->depth_surf) {
+#if GEN_GEN >= 7
+      db.DepthWriteEnable = true;
+#endif
+      db.SurfaceBaseAddress = info->depth_address;
+#if GEN_GEN >= 6
+      db.DepthBufferMOCS = info->mocs;
+#endif
+
+#if GEN_GEN <= 6
+      db.TiledSurface = info->depth_surf->tiling != ISL_TILING_LINEAR;
+      db.TileWalk = info->depth_surf->tiling == ISL_TILING_Y0 ? TILEWALK_YMAJOR :
+                                                                TILEWALK_XMAJOR;
+      db.MIPMapLayoutMode = MIPLAYOUT_BELOW;
+#endif
+
+      db.SurfacePitch = info->depth_surf->row_pitch - 1;
+#if GEN_GEN >= 8
+      db.SurfaceQPitch =
+         isl_surf_get_array_pitch_el_rows(info->depth_surf) >> 2;
+#endif
+   }
+
+#if GEN_GEN >= 6
+   struct GENX(3DSTATE_STENCIL_BUFFER) sb = {
+      GENX(3DSTATE_STENCIL_BUFFER_header),
+   };
+#else
+#  define sb db
+#endif
+
+   if (info->stencil_surf) {
+#if GEN_GEN >= 7
+      db.StencilWriteEnable = true;
+#endif
+#if GEN_GEN >= 8 || GEN_IS_HASWELL
+      sb.StencilBufferEnable = true;
+#endif
+      sb.SurfaceBaseAddress = info->stencil_address;
+#if GEN_GEN >= 6
+      sb.StencilBufferMOCS = info->mocs;
+#endif
+      sb.SurfacePitch = info->stencil_surf->row_pitch - 1;
+#if GEN_GEN >= 8
+      sb.SurfaceQPitch =
+         isl_surf_get_array_pitch_el_rows(info->stencil_surf) >> 2;
+#endif
+   }
+
+#if GEN_GEN >= 6
+   struct GENX(3DSTATE_HIER_DEPTH_BUFFER) hiz = {
+      GENX(3DSTATE_HIER_DEPTH_BUFFER_header),
+   };
+   struct GENX(3DSTATE_CLEAR_PARAMS) clear = {
+      GENX(3DSTATE_CLEAR_PARAMS_header),
+   };
+
+   assert(info->hiz_usage == ISL_AUX_USAGE_NONE ||
+          info->hiz_usage == ISL_AUX_USAGE_HIZ);
+   if (info->hiz_usage == ISL_AUX_USAGE_HIZ) {
+      db.HierarchicalDepthBufferEnable = true;
+#if GEN_GEN == 5 || GEN_GEN == 6
+      db.SeparateStencilBufferEnable = true;
+#endif
+
+      hiz.SurfaceBaseAddress = info->hiz_address;
+      hiz.HierarchicalDepthBufferMOCS = info->mocs;
+      hiz.SurfacePitch = info->hiz_surf->row_pitch - 1;
+#if GEN_GEN >= 8
+      /* From the SKL PRM Vol2a:
+       *
+       *    The interpretation of this field is dependent on Surface Type
+       *    as follows:
+       *    - SURFTYPE_1D: distance in pixels between array slices
+       *    - SURFTYPE_2D/CUBE: distance in rows between array slices
+       *    - SURFTYPE_3D: distance in rows between R - slices
+       *
+       * Unfortunately, the docs aren't 100% accurate here.  They fail to
+       * mention that the 1-D rule only applies to linear 1-D images.
+       * Since depth and HiZ buffers are always tiled, they are treated as
+       * 2-D images.  Prior to Sky Lake, this field is always in rows.
+       */
+      hiz.SurfaceQPitch =
+         isl_surf_get_array_pitch_sa_rows(info->hiz_surf) >> 2;
+#endif
+
+      clear.DepthClearValueValid = true;
+      clear.DepthClearValue = info->depth_clear_value;
+   }
+#endif /* GEN_GEN >= 6 */
+
+   /* Pack everything into the batch */
+   uint32_t *dw = batch;
+   GENX(3DSTATE_DEPTH_BUFFER_pack)(NULL, dw, &db);
+   dw += GENX(3DSTATE_DEPTH_BUFFER_length);
+
+#if GEN_GEN >= 6
+   GENX(3DSTATE_STENCIL_BUFFER_pack)(NULL, dw, &sb);
+   dw += GENX(3DSTATE_STENCIL_BUFFER_length);
+
+   GENX(3DSTATE_HIER_DEPTH_BUFFER_pack)(NULL, dw, &hiz);
+   dw += GENX(3DSTATE_HIER_DEPTH_BUFFER_length);
+
+   GENX(3DSTATE_CLEAR_PARAMS_pack)(NULL, dw, &clear);
+   dw += GENX(3DSTATE_CLEAR_PARAMS_length);
+#endif
+}
index 1867d258822430d277531b14537a6aed4ae690d9..3c4cc1ed95be7056835fa79ce7b51025fe27b23e 100644 (file)
@@ -205,4 +205,32 @@ void
 isl_gen9_buffer_fill_state_s(void *state,
                              const struct isl_buffer_fill_state_info *restrict info);
 
+void
+isl_gen4_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                  const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
+void
+isl_gen5_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                  const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
+void
+isl_gen6_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                  const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
+void
+isl_gen7_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                  const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
+void
+isl_gen75_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                   const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
+void
+isl_gen8_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                  const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
+void
+isl_gen9_emit_depth_stencil_hiz_s(const struct isl_device *dev, void *batch,
+                                  const struct isl_depth_stencil_hiz_emit_info *restrict info);
+
 #endif /* ISL_PRIV_H */