+ isl_tiling_get_info(surf->tiling, fmtl->bpb, tile_info);
+}
+
+bool
+isl_surf_get_hiz_surf(const struct isl_device *dev,
+ const struct isl_surf *surf,
+ struct isl_surf *hiz_surf)
+{
+ assert(ISL_DEV_GEN(dev) >= 5 && ISL_DEV_USE_SEPARATE_STENCIL(dev));
+
+ /* Multisampled depth is always interleaved */
+ assert(surf->msaa_layout == ISL_MSAA_LAYOUT_NONE ||
+ surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED);
+
+ /* From the Broadwell PRM Vol. 7, "Hierarchical Depth Buffer":
+ *
+ * "The Surface Type, Height, Width, Depth, Minimum Array Element, Render
+ * Target View Extent, and Depth Coordinate Offset X/Y of the
+ * hierarchical depth buffer are inherited from the depth buffer. The
+ * height and width of the hierarchical depth buffer that must be
+ * allocated are computed by the following formulas, where HZ is the
+ * hierarchical depth buffer and Z is the depth buffer. The Z_Height,
+ * Z_Width, and Z_Depth values given in these formulas are those present
+ * in 3DSTATE_DEPTH_BUFFER incremented by one.
+ *
+ * "The value of Z_Height and Z_Width must each be multiplied by 2 before
+ * being applied to the table below if Number of Multisamples is set to
+ * NUMSAMPLES_4. The value of Z_Height must be multiplied by 2 and
+ * Z_Width must be multiplied by 4 before being applied to the table
+ * below if Number of Multisamples is set to NUMSAMPLES_8."
+ *
+ * In the Sky Lake PRM, the second paragraph is replaced with this:
+ *
+ * "The Z_Height and Z_Width values must equal those present in
+ * 3DSTATE_DEPTH_BUFFER incremented by one."
+ *
+ * In other words, on Sandy Bridge through Broadwell, each 128-bit HiZ
+ * block corresponds to a region of 8x4 samples in the primary depth
+ * surface. On Sky Lake, on the other hand, each HiZ block corresponds to
+ * a region of 8x4 pixels in the primary depth surface regardless of the
+ * number of samples. The dimensions of a HiZ block in both pixels and
+ * samples are given in the table below:
+ *
+ * | SNB - BDW | SKL+
+ * ------+-----------+-------------
+ * 1x | 8 x 4 sa | 8 x 4 sa
+ * MSAA | 8 x 4 px | 8 x 4 px
+ * ------+-----------+-------------
+ * 2x | 8 x 4 sa | 16 x 4 sa
+ * MSAA | 4 x 4 px | 8 x 4 px
+ * ------+-----------+-------------
+ * 4x | 8 x 4 sa | 16 x 8 sa
+ * MSAA | 4 x 2 px | 8 x 4 px
+ * ------+-----------+-------------
+ * 8x | 8 x 4 sa | 32 x 8 sa
+ * MSAA | 2 x 2 px | 8 x 4 px
+ * ------+-----------+-------------
+ * 16x | N/A | 32 x 16 sa
+ * MSAA | N/A | 8 x 4 px
+ * ------+-----------+-------------
+ *
+ * There are a number of different ways that this discrepency could be
+ * handled. The way we have chosen is to simply make MSAA HiZ have the
+ * same number of samples as the parent surface pre-Sky Lake and always be
+ * single-sampled on Sky Lake and above. Since the block sizes of
+ * compressed formats are given in samples, this neatly handles everything
+ * without the need for additional HiZ formats with different block sizes
+ * on SKL+.
+ */
+ const unsigned samples = ISL_DEV_GEN(dev) >= 9 ? 1 : surf->samples;
+
+ return isl_surf_init(dev, hiz_surf,
+ .dim = surf->dim,
+ .format = ISL_FORMAT_HIZ,
+ .width = surf->logical_level0_px.width,
+ .height = surf->logical_level0_px.height,
+ .depth = surf->logical_level0_px.depth,
+ .levels = surf->levels,
+ .array_len = surf->logical_level0_px.array_len,
+ .samples = samples,
+ .usage = ISL_SURF_USAGE_HIZ_BIT,
+ .tiling_flags = ISL_TILING_HIZ_BIT);
+}
+
+bool
+isl_surf_get_mcs_surf(const struct isl_device *dev,
+ const struct isl_surf *surf,
+ struct isl_surf *mcs_surf)
+{
+ /* It must be multisampled with an array layout */
+ assert(surf->samples > 1 && surf->msaa_layout == ISL_MSAA_LAYOUT_ARRAY);
+
+ /* The following are true of all multisampled surfaces */
+ assert(surf->dim == ISL_SURF_DIM_2D);
+ assert(surf->levels == 1);
+ assert(surf->logical_level0_px.depth == 1);
+
+ /* The "Auxiliary Surface Pitch" field in RENDER_SURFACE_STATE is only 9
+ * bits which means the maximum pitch of a compression surface is 512
+ * tiles or 64KB (since MCS is always Y-tiled). Since a 16x MCS buffer is
+ * 64bpp, this gives us a maximum width of 8192 pixels. We can create
+ * larger multisampled surfaces, we just can't compress them. For 2x, 4x,
+ * and 8x, we have enough room for the full 16k supported by the hardware.
+ */
+ if (surf->samples == 16 && surf->logical_level0_px.width > 8192)
+ return false;
+
+ enum isl_format mcs_format;
+ switch (surf->samples) {
+ case 2: mcs_format = ISL_FORMAT_MCS_2X; break;
+ case 4: mcs_format = ISL_FORMAT_MCS_4X; break;
+ case 8: mcs_format = ISL_FORMAT_MCS_8X; break;
+ case 16: mcs_format = ISL_FORMAT_MCS_16X; break;
+ default:
+ unreachable("Invalid sample count");
+ }
+
+ return isl_surf_init(dev, mcs_surf,
+ .dim = ISL_SURF_DIM_2D,
+ .format = mcs_format,
+ .width = surf->logical_level0_px.width,
+ .height = surf->logical_level0_px.height,
+ .depth = 1,
+ .levels = 1,
+ .array_len = surf->logical_level0_px.array_len,
+ .samples = 1, /* MCS surfaces are really single-sampled */
+ .usage = ISL_SURF_USAGE_MCS_BIT,
+ .tiling_flags = ISL_TILING_Y0_BIT);
+}
+
+bool
+isl_surf_get_ccs_surf(const struct isl_device *dev,
+ const struct isl_surf *surf,
+ struct isl_surf *ccs_surf)
+{
+ assert(surf->samples == 1 && surf->msaa_layout == ISL_MSAA_LAYOUT_NONE);
+ assert(ISL_DEV_GEN(dev) >= 7);
+
+ if (surf->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT)
+ return false;
+
+ if (ISL_DEV_GEN(dev) <= 8 && surf->dim != ISL_SURF_DIM_2D)
+ return false;
+
+ if (isl_format_is_compressed(surf->format))
+ return false;
+
+ /* TODO: More conditions where it can fail. */
+
+ enum isl_format ccs_format;
+ if (ISL_DEV_GEN(dev) >= 9) {
+ if (!isl_tiling_is_any_y(surf->tiling))
+ return false;
+
+ switch (isl_format_get_layout(surf->format)->bpb) {
+ case 32: ccs_format = ISL_FORMAT_GEN9_CCS_32BPP; break;
+ case 64: ccs_format = ISL_FORMAT_GEN9_CCS_64BPP; break;
+ case 128: ccs_format = ISL_FORMAT_GEN9_CCS_128BPP; break;
+ default:
+ return false;
+ }
+ } else if (surf->tiling == ISL_TILING_Y0) {
+ switch (isl_format_get_layout(surf->format)->bpb) {
+ case 32: ccs_format = ISL_FORMAT_GEN7_CCS_32BPP_Y; break;
+ case 64: ccs_format = ISL_FORMAT_GEN7_CCS_64BPP_Y; break;
+ case 128: ccs_format = ISL_FORMAT_GEN7_CCS_128BPP_Y; break;
+ default:
+ return false;
+ }
+ } else if (surf->tiling == ISL_TILING_X) {
+ switch (isl_format_get_layout(surf->format)->bpb) {
+ case 32: ccs_format = ISL_FORMAT_GEN7_CCS_32BPP_X; break;
+ case 64: ccs_format = ISL_FORMAT_GEN7_CCS_64BPP_X; break;
+ case 128: ccs_format = ISL_FORMAT_GEN7_CCS_128BPP_X; break;
+ default:
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ return isl_surf_init(dev, ccs_surf,
+ .dim = surf->dim,
+ .format = ccs_format,
+ .width = surf->logical_level0_px.width,
+ .height = surf->logical_level0_px.height,
+ .depth = surf->logical_level0_px.depth,
+ .levels = surf->levels,
+ .array_len = surf->logical_level0_px.array_len,
+ .samples = 1,
+ .usage = ISL_SURF_USAGE_CCS_BIT,
+ .tiling_flags = ISL_TILING_CCS_BIT);