1 /* 2 * Copyright 2015 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24 #include "isl_gen8.h" 25 #include "isl_gen9.h" 26 #include "isl_priv.h" 27 28 /** 29 * Calculate the surface's subimage alignment, in units of surface samples, 30 * for the standard tiling formats Yf and Ys. 31 */ 32 static void 33 gen9_calc_std_image_alignment_sa(const struct isl_device *dev, 34 const struct isl_surf_init_info *restrict info, 35 enum isl_tiling tiling, 36 enum isl_msaa_layout msaa_layout, 37 struct isl_extent3d *align_sa) 38 { 39 const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 40 41 assert(isl_tiling_is_std_y(tiling)); 42 43 const uint32_t bpb = fmtl->bpb; 44 const uint32_t is_Ys = tiling == ISL_TILING_Ys; 45 46 switch (info->dim) { 47 case ISL_SURF_DIM_1D: 48 /* See the Skylake BSpec > Memory Views > Common Surface Formats > Surface 49 * Layout and Tiling > 1D Surfaces > 1D Alignment Requirements. 50 */ 51 *align_sa = (struct isl_extent3d) { 52 .w = 1 << (12 - (ffs(bpb) - 4) + (4 * is_Ys)), 53 .h = 1, 54 .d = 1, 55 }; 56 return; 57 case ISL_SURF_DIM_2D: 58 /* See the Skylake BSpec > Memory Views > Common Surface Formats > 59 * Surface Layout and Tiling > 2D Surfaces > 2D/CUBE Alignment 60 * Requirements. 61 */ 62 *align_sa = (struct isl_extent3d) { 63 .w = 1 << (6 - ((ffs(bpb) - 4) / 2) + (4 * is_Ys)), 64 .h = 1 << (6 - ((ffs(bpb) - 3) / 2) + (4 * is_Ys)), 65 .d = 1, 66 }; 67 68 if (is_Ys) { 69 /* FINISHME(chadv): I don't trust this code. Untested. */ 70 isl_finishme("%s:%s: [SKL+] multisample TileYs", __FILE__, __func__); 71 72 switch (msaa_layout) { 73 case ISL_MSAA_LAYOUT_NONE: 74 case ISL_MSAA_LAYOUT_INTERLEAVED: 75 break; 76 case ISL_MSAA_LAYOUT_ARRAY: 77 align_sa->w >>= (ffs(info->samples) - 0) / 2; 78 align_sa->h >>= (ffs(info->samples) - 1) / 2; 79 break; 80 } 81 } 82 return; 83 84 case ISL_SURF_DIM_3D: 85 /* See the Skylake BSpec > Memory Views > Common Surface Formats > Surface 86 * Layout and Tiling > 1D Surfaces > 1D Alignment Requirements. 87 */ 88 *align_sa = (struct isl_extent3d) { 89 .w = 1 << (4 - ((ffs(bpb) - 2) / 3) + (4 * is_Ys)), 90 .h = 1 << (4 - ((ffs(bpb) - 4) / 3) + (2 * is_Ys)), 91 .d = 1 << (4 - ((ffs(bpb) - 3) / 3) + (2 * is_Ys)), 92 }; 93 return; 94 } 95 96 unreachable("bad isl_surface_type"); 97 } 98 99 void 100 isl_gen9_choose_image_alignment_el(const struct isl_device *dev, 101 const struct isl_surf_init_info *restrict info, 102 enum isl_tiling tiling, 103 enum isl_dim_layout dim_layout, 104 enum isl_msaa_layout msaa_layout, 105 struct isl_extent3d *image_align_el) 106 { 107 /* Handled by isl_choose_image_alignment_el */ 108 assert(info->format != ISL_FORMAT_HIZ); 109 110 const struct isl_format_layout *fmtl = isl_format_get_layout(info->format); 111 if (fmtl->txc == ISL_TXC_CCS) { 112 /* Sky Lake PRM Vol. 7, "MCS Buffer for Render Target(s)" (p. 632): 113 * 114 * "Mip-mapped and arrayed surfaces are supported with MCS buffer 115 * layout with these alignments in the RT space: Horizontal 116 * Alignment = 128 and Vertical Alignment = 64." 117 */ 118 *image_align_el = isl_extent3d(128 / fmtl->bw, 64 / fmtl->bh, 1); 119 return; 120 } 121 122 /* This BSpec text provides some insight into the hardware's alignment 123 * requirements [Skylake BSpec > Memory Views > Common Surface Formats > 124 * Surface Layout and Tiling > 2D Surfaces]: 125 * 126 * An LOD must be aligned to a cache-line except for some special cases 127 * related to Planar YUV surfaces. In general, the cache-alignment 128 * restriction implies there is a minimum height for an LOD of 4 texels. 129 * So, LODs which are smaller than 4 high are padded. 130 * 131 * From the Skylake BSpec, RENDER_SURFACE_STATE Surface Vertical Alignment: 132 * 133 * - For Sampling Engine and Render Target Surfaces: This field 134 * specifies the vertical alignment requirement in elements for the 135 * surface. [...] An element is defined as a pixel in uncompresed 136 * surface formats, and as a compression block in compressed surface 137 * formats. For MSFMT_DEPTH_STENCIL type multisampled surfaces, an 138 * element is a sample. 139 * 140 * - This field is used for 2D, CUBE, and 3D surface alignment when Tiled 141 * Resource Mode is TRMODE_NONE (Tiled Resource Mode is disabled). 142 * This field is ignored for 1D surfaces and also when Tiled Resource 143 * Mode is not TRMODE_NONE (e.g. Tiled Resource Mode is enabled). 144 * 145 * See the appropriate Alignment table in the "Surface Layout and 146 * Tiling" section under Common Surface Formats for the table of 147 * alignment values for Tiled Resrouces. 148 * 149 * - For uncompressed surfaces, the units of "j" are rows of pixels on 150 * the physical surface. For compressed texture formats, the units of 151 * "j" are in compression blocks, thus each increment in "j" is equal 152 * to h pixels, where h is the height of the compression block in 153 * pixels. 154 * 155 * - Valid Values: VALIGN_4, VALIGN_8, VALIGN_16 156 * 157 * From the Skylake BSpec, RENDER_SURFACE_STATE Surface Horizontal 158 * Alignment: 159 * 160 * - For uncompressed surfaces, the units of "i" are pixels on the 161 * physical surface. For compressed texture formats, the units of "i" 162 * are in compression blocks, thus each increment in "i" is equal to 163 * w pixels, where w is the width of the compression block in pixels. 164 * 165 * - Valid Values: HALIGN_4, HALIGN_8, HALIGN_16 166 */ 167 168 if (isl_tiling_is_std_y(tiling)) { 169 struct isl_extent3d image_align_sa; 170 gen9_calc_std_image_alignment_sa(dev, info, tiling, msaa_layout, 171 &image_align_sa); 172 173 *image_align_el = isl_extent3d_sa_to_el(info->format, image_align_sa); 174 return; 175 } 176 177 if (dim_layout == ISL_DIM_LAYOUT_GEN9_1D) { 178 /* See the Skylake BSpec > Memory Views > Common Surface Formats > Surface 179 * Layout and Tiling > 1D Surfaces > 1D Alignment Requirements. 180 */ 181 *image_align_el = isl_extent3d(64, 1, 1); 182 return; 183 } 184 185 if (isl_format_is_compressed(info->format)) { 186 /* On Gen9, the meaning of RENDER_SURFACE_STATE's 187 * SurfaceHorizontalAlignment and SurfaceVerticalAlignment changed for 188 * compressed formats. They now indicate a multiple of the compression 189 * block. For example, if the compression mode is ETC2 then HALIGN_4 190 * indicates a horizontal alignment of 16 pixels. 191 * 192 * To avoid wasting memory, choose the smallest alignment possible: 193 * HALIGN_4 and VALIGN_4. 194 */ 195 *image_align_el = isl_extent3d(4, 4, 1); 196 return; 197 } 198 199 isl_gen8_choose_image_alignment_el(dev, info, tiling, dim_layout, 200 msaa_layout, image_align_el); 201 } 202