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_gen7.h" 25#include "isl_priv.h" 26 27bool 28isl_gen7_choose_msaa_layout(const struct isl_device *dev, 29 const struct isl_surf_init_info *info, 30 enum isl_tiling tiling, 31 enum isl_msaa_layout *msaa_layout) 32{ 33 bool require_array = false; 34 bool require_interleaved = false; 35 36 assert(ISL_DEV_GEN(dev) == 7); 37 assert(info->samples >= 1); 38 39 if (info->samples == 1) { 40 *msaa_layout = ISL_MSAA_LAYOUT_NONE; 41 return true; 42 } 43 44 if (!isl_format_supports_multisampling(dev->info, info->format)) 45 return false; 46 47 /* From the Ivybridge PRM, Volume 4 Part 1 p73, SURFACE_STATE, Number of 48 * Multisamples: 49 * 50 * - If this field is any value other than MULTISAMPLECOUNT_1, the 51 * Surface Type must be SURFTYPE_2D. 52 * 53 * - If this field is any value other than MULTISAMPLECOUNT_1, Surface 54 * Min LOD, Mip Count / LOD, and Resource Min LOD must be set to zero 55 */ 56 if (info->dim != ISL_SURF_DIM_2D) 57 return false; 58 if (info->levels > 1) 59 return false; 60 61 /* The Ivyrbridge PRM insists twice that signed integer formats cannot be 62 * multisampled. 63 * 64 * From the Ivybridge PRM, Volume 4 Part 1 p73, SURFACE_STATE, Number of 65 * Multisamples: 66 * 67 * - This field must be set to MULTISAMPLECOUNT_1 for SINT MSRTs when 68 * all RT channels are not written. 69 * 70 * And errata from the Ivybridge PRM, Volume 4 Part 1 p77, 71 * RENDER_SURFACE_STATE, MCS Enable: 72 * 73 * This field must be set to 0 [MULTISAMPLECOUNT_1] for all SINT MSRTs 74 * when all RT channels are not written. 75 * 76 * Note that the above SINT restrictions apply only to *MSRTs* (that is, 77 * *multisampled* render targets). The restrictions seem to permit an MCS 78 * if the render target is singlesampled. 79 */ 80 if (isl_format_has_sint_channel(info->format)) 81 return false; 82 83 /* More obvious restrictions */ 84 if (isl_surf_usage_is_display(info->usage)) 85 return false; 86 if (tiling == ISL_TILING_LINEAR) 87 return false; 88 89 /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled 90 * Suface Storage Format: 91 * 92 * +---------------------+----------------------------------------------------------------+ 93 * | MSFMT_MSS | Multsampled surface was/is rendered as a render target | 94 * | MSFMT_DEPTH_STENCIL | Multisampled surface was rendered as a depth or stencil buffer | 95 * +---------------------+----------------------------------------------------------------+ 96 * 97 * In the table above, MSFMT_MSS refers to ISL_MSAA_LAYOUT_ARRAY, and 98 * MSFMT_DEPTH_STENCIL refers to ISL_MSAA_LAYOUT_INTERLEAVED. 99 */ 100 if (isl_surf_usage_is_depth_or_stencil(info->usage) || 101 (info->usage & ISL_SURF_USAGE_HIZ_BIT)) 102 require_interleaved = true; 103 104 /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled 105 * Suface Storage Format: 106 * 107 * If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, Width 108 * is >= 8192 (meaning the actual surface width is >= 8193 pixels), this 109 * field must be set to MSFMT_MSS. 110 */ 111 if (info->samples == 8 && info->width == 8192) 112 require_array = true; 113 114 /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled 115 * Suface Storage Format: 116 * 117 * If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, 118 * ((Depth+1) * (Height+1)) is > 4,194,304, OR if the surface’s Number 119 * of Multisamples is MULTISAMPLECOUNT_4, ((Depth+1) * (Height+1)) is 120 * > 8,388,608, this field must be set to MSFMT_DEPTH_STENCIL. 121 */ 122 if ((info->samples == 8 && info->height > 4194304u) || 123 (info->samples == 4 && info->height > 8388608u)) 124 require_interleaved = true; 125 126 /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled 127 * Suface Storage Format: 128 * 129 * This field must be set to MSFMT_DEPTH_STENCIL if Surface Format is 130 * one of the following: I24X8_UNORM, L24X8_UNORM, A24X8_UNORM, or 131 * R24_UNORM_X8_TYPELESS. 132 */ 133 if (info->format == ISL_FORMAT_I24X8_UNORM || 134 info->format == ISL_FORMAT_L24X8_UNORM || 135 info->format == ISL_FORMAT_A24X8_UNORM || 136 info->format == ISL_FORMAT_R24_UNORM_X8_TYPELESS) 137 require_interleaved = true; 138 139 if (require_array && require_interleaved) 140 return false; 141 142 if (require_interleaved) { 143 *msaa_layout = ISL_MSAA_LAYOUT_INTERLEAVED; 144 return true; 145 } 146 147 /* Default to the array layout because it permits multisample 148 * compression. 149 */ 150 *msaa_layout = ISL_MSAA_LAYOUT_ARRAY; 151 return true; 152} 153 154static bool 155gen7_format_needs_valign2(const struct isl_device *dev, 156 enum isl_format format) 157{ 158 assert(ISL_DEV_GEN(dev) == 7); 159 160 /* From the Ivybridge PRM (2012-05-31), Volume 4, Part 1, Section 2.12.1, 161 * RENDER_SURFACE_STATE Surface Vertical Alignment: 162 * 163 * - Value of 1 [VALIGN_4] is not supported for format YCRCB_NORMAL 164 * (0x182), YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY 165 * (0x190) 166 * 167 * - VALIGN_4 is not supported for surface format R32G32B32_FLOAT. 168 */ 169 return isl_format_is_yuv(format) || 170 format == ISL_FORMAT_R32G32B32_FLOAT; 171} 172 173/** 174 * @brief Filter out tiling flags that are incompatible with the surface. 175 * 176 * The resultant outgoing @a flags is a subset of the incoming @a flags. The 177 * outgoing flags may be empty (0x0) if the incoming flags were too 178 * restrictive. 179 * 180 * For example, if the surface will be used for a display 181 * (ISL_SURF_USAGE_DISPLAY_BIT), then this function filters out all tiling 182 * flags except ISL_TILING_X_BIT and ISL_TILING_LINEAR_BIT. 183 */ 184void 185isl_gen6_filter_tiling(const struct isl_device *dev, 186 const struct isl_surf_init_info *restrict info, 187 isl_tiling_flags_t *flags) 188{ 189 /* IVB+ requires separate stencil */ 190 assert(ISL_DEV_USE_SEPARATE_STENCIL(dev)); 191 192 /* Clear flags unsupported on this hardware */ 193 if (ISL_DEV_GEN(dev) < 9) { 194 *flags &= ~ISL_TILING_Yf_BIT; 195 *flags &= ~ISL_TILING_Ys_BIT; 196 } 197 198 /* And... clear the Yf and Ys bits anyway because Anvil doesn't support 199 * them yet. 200 */ 201 *flags &= ~ISL_TILING_Yf_BIT; /* FINISHME[SKL]: Support Yf */ 202 *flags &= ~ISL_TILING_Ys_BIT; /* FINISHME[SKL]: Support Ys */ 203 204 if (isl_surf_usage_is_depth(info->usage)) { 205 /* Depth requires Y. */ 206 *flags &= ISL_TILING_ANY_Y_MASK; 207 } 208 209 /* Separate stencil requires W tiling, and W tiling requires separate 210 * stencil. 211 */ 212 if (isl_surf_usage_is_stencil(info->usage)) { 213 *flags &= ISL_TILING_W_BIT; 214 } else { 215 *flags &= ~ISL_TILING_W_BIT; 216 } 217 218 /* From the SKL+ PRMs, RENDER_SURFACE_STATE:TileMode, 219 * If Surface Format is ASTC*, this field must be TILEMODE_YMAJOR. 220 */ 221 if (isl_format_get_layout(info->format)->txc == ISL_TXC_ASTC) 222 *flags &= ISL_TILING_Y0_BIT; 223 224 /* MCS buffers are always Y-tiled */ 225 if (isl_format_get_layout(info->format)->txc == ISL_TXC_MCS) 226 *flags &= ISL_TILING_Y0_BIT; 227 228 if (info->usage & (ISL_SURF_USAGE_DISPLAY_ROTATE_90_BIT | 229 ISL_SURF_USAGE_DISPLAY_ROTATE_180_BIT | 230 ISL_SURF_USAGE_DISPLAY_ROTATE_270_BIT)) { 231 assert(*flags & ISL_SURF_USAGE_DISPLAY_BIT); 232 isl_finishme("%s:%s: handle rotated display surfaces", 233 __FILE__, __func__); 234 } 235 236 if (info->usage & (ISL_SURF_USAGE_DISPLAY_FLIP_X_BIT | 237 ISL_SURF_USAGE_DISPLAY_FLIP_Y_BIT)) { 238 assert(*flags & ISL_SURF_USAGE_DISPLAY_BIT); 239 isl_finishme("%s:%s: handle flipped display surfaces", 240 __FILE__, __func__); 241 } 242 243 if (info->usage & ISL_SURF_USAGE_DISPLAY_BIT) { 244 /* Before Skylake, the display engine does not accept Y */ 245 /* FINISHME[SKL]: Y tiling for display surfaces */ 246 *flags &= (ISL_TILING_LINEAR_BIT | ISL_TILING_X_BIT); 247 } 248 249 if (info->samples > 1) { 250 /* From the Sandybridge PRM, Volume 4 Part 1, SURFACE_STATE Tiled 251 * Surface: 252 * 253 * For multisample render targets, this field must be 1 (true). MSRTs 254 * can only be tiled. 255 * 256 * From the Broadwell PRM >> Volume2d: Command Structures >> 257 * RENDER_SURFACE_STATE Tile Mode: 258 * 259 * If Number of Multisamples is not MULTISAMPLECOUNT_1, this field 260 * must be YMAJOR. 261 * 262 * As usual, though, stencil is special and requires W-tiling. 263 */ 264 *flags &= (ISL_TILING_ANY_Y_MASK | ISL_TILING_W_BIT); 265 } 266 267 /* workaround */ 268 if (ISL_DEV_GEN(dev) == 7 && 269 gen7_format_needs_valign2(dev, info->format) && 270 (info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) && 271 info->samples == 1) { 272 /* Y tiling is illegal. From the Ivybridge PRM, Vol4 Part1 2.12.2.1, 273 * SURFACE_STATE Surface Vertical Alignment: 274 * 275 * This field must be set to VALIGN_4 for all tiled Y Render Target 276 * surfaces. 277 */ 278 *flags &= ~ISL_TILING_Y0_BIT; 279 } 280 281 /* From the Sandybridge PRM, Volume 1, Part 2, page 32: 282 * 283 * "NOTE: 128BPE Format Color Buffer ( render target ) MUST be either 284 * TileX or Linear." 285 * 286 * This is necessary all the way back to 965, but is permitted on Gen7+. 287 */ 288 if (ISL_DEV_GEN(dev) < 7 && isl_format_get_layout(info->format)->bpb >= 128) 289 *flags &= ~ISL_TILING_Y0_BIT; 290} 291 292/** 293 * Choose horizontal subimage alignment, in units of surface elements. 294 */ 295static uint32_t 296gen7_choose_halign_el(const struct isl_device *dev, 297 const struct isl_surf_init_info *restrict info) 298{ 299 if (isl_format_is_compressed(info->format)) 300 return 1; 301 302 /* From the Ivybridge PRM (2012-05-31), Volume 4, Part 1, Section 2.12.1, 303 * RENDER_SURFACE_STATE Surface Hoizontal Alignment: 304 * 305 * - This field is intended to be set to HALIGN_8 only if the surface 306 * was rendered as a depth buffer with Z16 format or a stencil buffer, 307 * since these surfaces support only alignment of 8. Use of HALIGN_8 308 * for other surfaces is supported, but uses more memory. 309 */ 310 if (isl_surf_info_is_z16(info) || 311 isl_surf_usage_is_stencil(info->usage)) 312 return 8; 313 314 return 4; 315} 316 317/** 318 * Choose vertical subimage alignment, in units of surface elements. 319 */ 320static uint32_t 321gen7_choose_valign_el(const struct isl_device *dev, 322 const struct isl_surf_init_info *restrict info, 323 enum isl_tiling tiling) 324{ 325 MAYBE_UNUSED bool require_valign2 = false; 326 bool require_valign4 = false; 327 328 if (isl_format_is_compressed(info->format)) 329 return 1; 330 331 if (gen7_format_needs_valign2(dev, info->format)) 332 require_valign2 = true; 333 334 /* From the Ivybridge PRM, Volume 4, Part 1, Section 2.12.1: 335 * RENDER_SURFACE_STATE Surface Vertical Alignment: 336 * 337 * - This field is intended to be set to VALIGN_4 if the surface was 338 * rendered as a depth buffer, for a multisampled (4x) render target, 339 * or for a multisampled (8x) render target, since these surfaces 340 * support only alignment of 4. Use of VALIGN_4 for other surfaces is 341 * supported, but uses more memory. This field must be set to 342 * VALIGN_4 for all tiled Y Render Target surfaces. 343 * 344 */ 345 if (isl_surf_usage_is_depth(info->usage) || 346 info->samples > 1 || 347 ((info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) && 348 tiling == ISL_TILING_Y0)) { 349 require_valign4 = true; 350 } 351 352 if (isl_surf_usage_is_stencil(info->usage)) { 353 /* The Ivybridge PRM states that the stencil buffer's vertical alignment 354 * is 8 [Ivybridge PRM, Volume 1, Part 1, Section 6.18.4.4 Alignment 355 * Unit Size]. However, valign=8 is outside the set of valid values of 356 * RENDER_SURFACE_STATE.SurfaceVerticalAlignment, which is VALIGN_2 357 * (0x0) and VALIGN_4 (0x1). 358 * 359 * The PRM is generally confused about the width, height, and alignment 360 * of the stencil buffer; and this confusion appears elsewhere. For 361 * example, the following PRM text effectively converts the stencil 362 * buffer's 8-pixel alignment to a 4-pixel alignment [Ivybridge PRM, 363 * Volume 1, Part 1, Section 364 * 6.18.4.2 Base Address and LOD Calculation]: 365 * 366 * For separate stencil buffer, the width must be mutiplied by 2 and 367 * height divided by 2 as follows: 368 * 369 * w_L = 2*i*ceil(W_L/i) 370 * h_L = 1/2*j*ceil(H_L/j) 371 * 372 * The root of the confusion is that, in W tiling, each pair of rows is 373 * interleaved into one. 374 * 375 * FINISHME(chadv): Decide to set valign=4 or valign=8 after isl's API 376 * is more polished. 377 */ 378 require_valign4 = true; 379 } 380 381 assert(!require_valign2 || !require_valign4); 382 383 if (require_valign4) 384 return 4; 385 386 /* Prefer VALIGN_2 because it conserves memory. */ 387 return 2; 388} 389 390void 391isl_gen7_choose_image_alignment_el(const struct isl_device *dev, 392 const struct isl_surf_init_info *restrict info, 393 enum isl_tiling tiling, 394 enum isl_dim_layout dim_layout, 395 enum isl_msaa_layout msaa_layout, 396 struct isl_extent3d *image_align_el) 397{ 398 assert(ISL_DEV_GEN(dev) == 7); 399 400 /* Handled by isl_choose_image_alignment_el */ 401 assert(info->format != ISL_FORMAT_HIZ); 402 403 /* IVB+ does not support combined depthstencil. */ 404 assert(!isl_surf_usage_is_depth_and_stencil(info->usage)); 405 406 *image_align_el = (struct isl_extent3d) { 407 .w = gen7_choose_halign_el(dev, info), 408 .h = gen7_choose_valign_el(dev, info, tiling), 409 .d = 1, 410 }; 411} 412