isl: add gen12 comment about CCS for linear tiling
[mesa.git] / src / intel / isl / isl.c
index c756fb0c80fb185b6a3a55241198ccba45970db7..f737f8b3b539d9678276bfc1db8e684a0ab08fd9 100644 (file)
@@ -95,6 +95,56 @@ __isl_finishme(const char *file, int line, const char *fmt, ...)
    fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buf);
 }
 
+static void
+isl_device_setup_mocs(struct isl_device *dev)
+{
+   if (dev->info->gen >= 12) {
+      /* TODO: Set PTE to MOCS 61 when the kernel is ready */
+      /* TC=1/LLC Only, LeCC=1/Uncacheable, LRUM=0, L3CC=1/Uncacheable */
+      dev->mocs.external = 3 << 1;
+      /* TC=LLC/eLLC, LeCC=WB, LRUM=3, L3CC=WB */
+      dev->mocs.internal = 2 << 1;
+   } else if (dev->info->gen >= 9) {
+      /* TC=LLC/eLLC, LeCC=PTE, LRUM=3, L3CC=WB */
+      dev->mocs.external = 1 << 1;
+      /* TC=LLC/eLLC, LeCC=WB, LRUM=3, L3CC=WB */
+      dev->mocs.internal = 2 << 1;
+   } else if (dev->info->gen >= 8) {
+      /* MEMORY_OBJECT_CONTROL_STATE:
+       * .MemoryTypeLLCeLLCCacheabilityControl = UCwithFenceifcoherentcycle,
+       * .TargetCache = L3DefertoPATforLLCeLLCselection,
+       * .AgeforQUADLRU = 0
+       */
+      dev->mocs.external = 0x18;
+      /* MEMORY_OBJECT_CONTROL_STATE:
+       * .MemoryTypeLLCeLLCCacheabilityControl = WB,
+       * .TargetCache = L3DefertoPATforLLCeLLCselection,
+       * .AgeforQUADLRU = 0
+       */
+      dev->mocs.internal = 0x78;
+   } else if (dev->info->gen >= 7) {
+      if (dev->info->is_haswell) {
+         /* MEMORY_OBJECT_CONTROL_STATE:
+          * .LLCeLLCCacheabilityControlLLCCC             = 0,
+          * .L3CacheabilityControlL3CC                   = 1,
+          */
+         dev->mocs.internal = 1;
+         dev->mocs.external = 1;
+      } else {
+         /* MEMORY_OBJECT_CONTROL_STATE:
+          * .GraphicsDataTypeGFDT                        = 0,
+          * .LLCCacheabilityControlLLCCC                 = 0,
+          * .L3CacheabilityControlL3CC                   = 1,
+          */
+         dev->mocs.internal = 1;
+         dev->mocs.external = 1;
+      }
+   } else {
+      dev->mocs.internal = 0;
+      dev->mocs.external = 0;
+   }
+}
+
 void
 isl_device_init(struct isl_device *dev,
                 const struct gen_device_info *info,
@@ -172,6 +222,8 @@ isl_device_init(struct isl_device *dev,
       dev->ds.stencil_offset = 0;
       dev->ds.hiz_offset = 0;
    }
+
+   isl_device_setup_mocs(dev);
 }
 
 /**
@@ -1309,11 +1361,22 @@ isl_calc_phys_total_extent_el(const struct isl_device *dev,
 }
 
 static uint32_t
-isl_calc_row_pitch_alignment(const struct isl_surf_init_info *surf_info,
+isl_calc_row_pitch_alignment(const struct isl_device *dev,
+                             const struct isl_surf_init_info *surf_info,
                              const struct isl_tile_info *tile_info)
 {
-   if (tile_info->tiling != ISL_TILING_LINEAR)
+   if (tile_info->tiling != ISL_TILING_LINEAR) {
+      /* According to BSpec: 44930, Gen12's CCS-compressed surface pitches must
+       * be 512B-aligned. CCS is only support on Y tilings.
+       */
+      if (ISL_DEV_GEN(dev) >= 12 &&
+          isl_format_supports_ccs_e(dev->info, surf_info->format) &&
+          tile_info->tiling != ISL_TILING_X) {
+         return isl_align(tile_info->phys_extent_B.width, 512);
+      }
+
       return tile_info->phys_extent_B.width;
+   }
 
    /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >>
     * RENDER_SURFACE_STATE Surface Pitch (p349):
@@ -1371,8 +1434,12 @@ isl_calc_tiled_min_row_pitch(const struct isl_device *dev,
       isl_align_div(phys_total_el->w * tile_el_scale,
                     tile_info->logical_extent_el.width);
 
-   assert(alignment_B == tile_info->phys_extent_B.width);
-   return total_w_tl * tile_info->phys_extent_B.width;
+   /* In some cases the alignment of the pitch might be > to the tile size
+    * (for example Gen12 CCS requires 512B alignment while the tile's width
+    * can be 128B), so align the row pitch to the alignment.
+    */
+   assert(alignment_B >= tile_info->phys_extent_B.width);
+   return isl_align(total_w_tl * tile_info->phys_extent_B.width, alignment_B);
 }
 
 static uint32_t
@@ -1416,7 +1483,7 @@ isl_calc_row_pitch(const struct isl_device *dev,
                    uint32_t *out_row_pitch_B)
 {
    uint32_t alignment_B =
-      isl_calc_row_pitch_alignment(surf_info, tile_info);
+      isl_calc_row_pitch_alignment(dev, surf_info, tile_info);
 
    const uint32_t min_row_pitch_B =
       isl_calc_min_row_pitch(dev, surf_info, tile_info, phys_total_el,
@@ -1431,16 +1498,7 @@ isl_calc_row_pitch(const struct isl_device *dev,
    }
 
    const uint32_t row_pitch_B =
-      surf_info->row_pitch_B != 0 ?
-         surf_info->row_pitch_B :
-      /* According to BSpec: 44930, Gen12's CCS-compressed surface pitches
-       * must be 512B-aligned.
-       */
-      ISL_DEV_GEN(dev) >= 12 &&
-      isl_format_supports_ccs_e(dev->info, surf_info->format) ?
-         isl_align(min_row_pitch_B, 512) :
-      /* Else */
-         min_row_pitch_B;
+      surf_info->row_pitch_B != 0 ? surf_info->row_pitch_B : min_row_pitch_B;
 
    const uint32_t row_pitch_tl = row_pitch_B / tile_info->phys_extent_B.width;
 
@@ -1773,6 +1831,9 @@ isl_surf_get_mcs_surf(const struct isl_device *dev,
    if (surf->msaa_layout != ISL_MSAA_LAYOUT_ARRAY)
       return false;
 
+   if (mcs_surf->size_B > 0)
+      return false;
+
    /* The following are true of all multisampled surfaces */
    assert(surf->samples > 1);
    assert(surf->dim == ISL_SURF_DIM_2D);
@@ -1845,13 +1906,9 @@ isl_surf_get_ccs_surf(const struct isl_device *dev,
    if (aux_surf->usage & ISL_SURF_USAGE_CCS_BIT)
       return false;
 
-   /* Only multisampled depth buffers with HiZ can have CCS. */
-   if (surf->samples > 1 && !(aux_surf->usage & ISL_SURF_USAGE_HIZ_BIT))
+   if (ISL_DEV_GEN(dev) < 12 && surf->samples > 1)
       return false;
 
-   assert(surf->msaa_layout == ISL_MSAA_LAYOUT_NONE ||
-          surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED);
-
    /* CCS support does not exist prior to Gen7 */
    if (ISL_DEV_GEN(dev) <= 6)
       return false;
@@ -1859,8 +1916,9 @@ isl_surf_get_ccs_surf(const struct isl_device *dev,
    if (surf->usage & ISL_SURF_USAGE_DISABLE_AUX_BIT)
       return false;
 
-   /* Callers don't yet support this configuration. */
-   if (isl_surf_usage_is_stencil(surf->usage))
+   /* Allow CCS for single-sampled stencil buffers Gen12+. */
+   if (isl_surf_usage_is_stencil(surf->usage) &&
+       (ISL_DEV_GEN(dev) < 12 || surf->samples > 1))
       return false;
 
    /* [TGL+] CCS can only be added to a non-D16-formatted depth buffer if it
@@ -1928,6 +1986,19 @@ isl_surf_get_ccs_surf(const struct isl_device *dev,
       return false;
    }
 
+   /* GEN:BUG:1207137018
+    *
+    * TODO: implement following workaround currently covered by the restriction
+    * above. If following conditions are met:
+    *
+    *    - RENDER_SURFACE_STATE.Surface Type == 3D
+    *    - RENDER_SURFACE_STATE.Auxiliary Surface Mode != AUX_NONE
+    *    - RENDER_SURFACE_STATE.Tiled ResourceMode is TYF or TYS
+    *
+    * Set the value of RENDER_SURFACE_STATE.Mip Tail Start LOD to a mip that
+    * larger than those present in the surface (i.e. 15)
+    */
+
    /* TODO: More conditions where it can fail. */
 
    /* From the Ivy Bridge PRM, Vol2 Part1 11.7 "MCS Buffer for Render
@@ -1949,6 +2020,16 @@ isl_surf_get_ccs_surf(const struct isl_device *dev,
       if (surf->tiling != ISL_TILING_Y0)
          return false;
 
+      /* BSpec 44930:
+       *
+       *    Linear CCS is only allowed for Untyped Buffers but only via HDC
+       *    Data-Port messages.
+       *
+       * We probably want to limit linear CCS to storage usage and check that
+       * the shaders actually use only untyped messages.
+       */
+      assert(surf->tiling != ISL_TILING_LINEAR);
+
       switch (isl_format_get_layout(surf->format)->bpb) {
       case 8:     ccs_format = ISL_FORMAT_GEN12_CCS_8BPP_Y0;    break;
       case 16:    ccs_format = ISL_FORMAT_GEN12_CCS_16BPP_Y0;   break;
@@ -2098,7 +2179,7 @@ void
 isl_buffer_fill_state_s(const struct isl_device *dev, void *state,
                         const struct isl_buffer_fill_state_info *restrict info)
 {
-   isl_genX_call(dev, buffer_fill_state_s, state, info);
+   isl_genX_call(dev, buffer_fill_state_s, dev, state, info);
 }
 
 void
@@ -2448,6 +2529,56 @@ isl_surf_get_image_offset_B_tile_sa(const struct isl_surf *surf,
    }
 }
 
+void
+isl_surf_get_image_range_B_tile(const struct isl_surf *surf,
+                                uint32_t level,
+                                uint32_t logical_array_layer,
+                                uint32_t logical_z_offset_px,
+                                uint32_t *start_tile_B,
+                                uint32_t *end_tile_B)
+{
+   uint32_t start_x_offset_el, start_y_offset_el;
+   isl_surf_get_image_offset_el(surf, level, logical_array_layer,
+                                logical_z_offset_px,
+                                &start_x_offset_el,
+                                &start_y_offset_el);
+
+   /* Compute the size of the subimage in surface elements */
+   const uint32_t subimage_w_sa = isl_minify(surf->phys_level0_sa.w, level);
+   const uint32_t subimage_h_sa = isl_minify(surf->phys_level0_sa.h, level);
+   const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
+   const uint32_t subimage_w_el = isl_align_div_npot(subimage_w_sa, fmtl->bw);
+   const uint32_t subimage_h_el = isl_align_div_npot(subimage_h_sa, fmtl->bh);
+
+   /* Find the last pixel */
+   uint32_t end_x_offset_el = start_x_offset_el + subimage_w_el - 1;
+   uint32_t end_y_offset_el = start_y_offset_el + subimage_h_el - 1;
+
+   UNUSED uint32_t x_offset_el, y_offset_el;
+   isl_tiling_get_intratile_offset_el(surf->tiling, fmtl->bpb,
+                                      surf->row_pitch_B,
+                                      start_x_offset_el,
+                                      start_y_offset_el,
+                                      start_tile_B,
+                                      &x_offset_el,
+                                      &y_offset_el);
+
+   isl_tiling_get_intratile_offset_el(surf->tiling, fmtl->bpb,
+                                      surf->row_pitch_B,
+                                      end_x_offset_el,
+                                      end_y_offset_el,
+                                      end_tile_B,
+                                      &x_offset_el,
+                                      &y_offset_el);
+
+   /* We want the range we return to be exclusive but the tile containing the
+    * last pixel (what we just calculated) is inclusive.  Add one.
+    */
+   (*end_tile_B)++;
+
+   assert(*end_tile_B <= surf->size_B);
+}
+
 void
 isl_surf_get_image_surf(const struct isl_device *dev,
                         const struct isl_surf *surf,