xref: /aosp_15_r20/external/mesa3d/src/intel/isl/isl_gfx7.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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_gfx7.h"
25 #include "isl_priv.h"
26 
27 static bool
gfx7_format_needs_valign2(const struct isl_device * dev,enum isl_format format)28 gfx7_format_needs_valign2(const struct isl_device *dev,
29                           enum isl_format format)
30 {
31    assert(ISL_GFX_VER(dev) == 7);
32 
33    /* From the Ivybridge PRM (2012-05-31), Volume 4, Part 1, Section 2.12.1,
34     * RENDER_SURFACE_STATE Surface Vertical Alignment:
35     *
36     *    - Value of 1 [VALIGN_4] is not supported for format YCRCB_NORMAL
37     *      (0x182), YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY
38     *      (0x190)
39     *
40     *    - VALIGN_4 is not supported for surface format R32G32B32_FLOAT.
41     *
42     * The R32G32B32_FLOAT restriction is dropped on Haswell.
43     */
44    return isl_format_is_yuv(format) ||
45           (format == ISL_FORMAT_R32G32B32_FLOAT && !ISL_DEV_IS_HASWELL(dev));
46 }
47 
48 bool
isl_gfx7_choose_msaa_layout(const struct isl_device * dev,const struct isl_surf_init_info * info,enum isl_tiling tiling,enum isl_msaa_layout * msaa_layout)49 isl_gfx7_choose_msaa_layout(const struct isl_device *dev,
50                             const struct isl_surf_init_info *info,
51                             enum isl_tiling tiling,
52                             enum isl_msaa_layout *msaa_layout)
53 {
54    bool require_array = false;
55    bool require_interleaved = false;
56 
57    assert(ISL_GFX_VER(dev) == 7);
58    assert(info->samples >= 1);
59 
60    if (info->samples == 1) {
61       *msaa_layout = ISL_MSAA_LAYOUT_NONE;
62       return true;
63    }
64 
65    /* Should have been filtered by isl_gfx6_filter_tiling() */
66    assert(!isl_surf_usage_is_display(info->usage));
67    assert(tiling != ISL_TILING_LINEAR);
68 
69    if (!isl_format_supports_multisampling(dev->info, info->format))
70       return notify_failure(info, "format does not support msaa");
71 
72    /* From the Ivybridge PRM, Volume 4 Part 1 p73, SURFACE_STATE, Number of
73     * Multisamples:
74     *
75     *    - If this field is any value other than MULTISAMPLECOUNT_1, the
76     *      Surface Type must be SURFTYPE_2D.
77     *
78     *    - If this field is any value other than MULTISAMPLECOUNT_1, Surface
79     *      Min LOD, Mip Count / LOD, and Resource Min LOD must be set to zero
80     */
81    if (info->dim != ISL_SURF_DIM_2D)
82       return notify_failure(info, "msaa only supported on 2D surfaces");
83    if (info->levels > 1)
84       return notify_failure(info, "msaa not supported with LOD > 1");
85 
86    /* The Ivyrbridge PRM insists twice that signed integer formats cannot be
87     * multisampled.
88     *
89     * From the Ivybridge PRM, Volume 4 Part 1 p73, SURFACE_STATE, Number of
90     * Multisamples:
91     *
92     *    - This field must be set to MULTISAMPLECOUNT_1 for SINT MSRTs when
93     *      all RT channels are not written.
94     *
95     * And errata from the Ivybridge PRM, Volume 4 Part 1 p77,
96     * RENDER_SURFACE_STATE, MCS Enable:
97     *
98     *   This field must be set to 0 [MULTISAMPLECOUNT_1] for all SINT MSRTs
99     *   when all RT channels are not written.
100     *
101     * Note that the above SINT restrictions apply only to *MSRTs* (that is,
102     * *multisampled* render targets). The restrictions seem to permit an MCS
103     * if the render target is singlesampled.
104     *
105     * Moreover, empirically it looks that hardware can render multisampled
106     * surfaces with RGBA8I, RGBA16I and RGBA32I.
107     */
108 
109    /* Multisampling requires vertical alignment of four. */
110    if (info->samples > 1 && gfx7_format_needs_valign2(dev, info->format)) {
111       return notify_failure(info, "msaa requires vertical alignment of four, "
112                                   "but format requires vertical alignment of two");
113    }
114 
115    /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled
116     * Surface Storage Format:
117     *
118     *    +---------------------+----------------------------------------------------------------+
119     *    | MSFMT_MSS           | Multsampled surface was/is rendered as a render target         |
120     *    | MSFMT_DEPTH_STENCIL | Multisampled surface was rendered as a depth or stencil buffer |
121     *    +---------------------+----------------------------------------------------------------+
122     *
123     * In the table above, MSFMT_MSS refers to ISL_MSAA_LAYOUT_ARRAY, and
124     * MSFMT_DEPTH_STENCIL refers to ISL_MSAA_LAYOUT_INTERLEAVED.
125     */
126    if (isl_surf_usage_is_depth_or_stencil(info->usage) ||
127        (info->usage & ISL_SURF_USAGE_HIZ_BIT))
128       require_interleaved = true;
129 
130    /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled
131     * Surface Storage Format:
132     *
133     *    If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8, Width
134     *    is >= 8192 (meaning the actual surface width is >= 8193 pixels), this
135     *    field must be set to MSFMT_MSS.
136     */
137    if (info->samples == 8 && info->width > 8192)
138       require_array = true;
139 
140    /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled
141     * Surface Storage Format:
142     *
143     *    If the surface’s Number of Multisamples is MULTISAMPLECOUNT_8,
144     *    ((Depth+1) * (Height+1)) is > 4,194,304, OR if the surface’s Number
145     *    of Multisamples is MULTISAMPLECOUNT_4, ((Depth+1) * (Height+1)) is
146     *    > 8,388,608, this field must be set to MSFMT_DEPTH_STENCIL.
147     */
148    if ((info->samples == 8 && info->height > 4194304u) ||
149        (info->samples == 4 && info->height > 8388608u))
150       require_interleaved = true;
151 
152    /* From the Ivybridge PRM, Volume 4 Part 1 p72, SURFACE_STATE, Multisampled
153     * Surface Storage Format:
154     *
155     *    This field must be set to MSFMT_DEPTH_STENCIL if Surface Format is
156     *    one of the following: I24X8_UNORM, L24X8_UNORM, A24X8_UNORM, or
157     *    R24_UNORM_X8_TYPELESS.
158     */
159    if (info->format == ISL_FORMAT_I24X8_UNORM ||
160        info->format == ISL_FORMAT_L24X8_UNORM ||
161        info->format == ISL_FORMAT_A24X8_UNORM ||
162        info->format == ISL_FORMAT_R24_UNORM_X8_TYPELESS)
163       require_interleaved = true;
164 
165    if (require_array && require_interleaved)
166       return notify_failure(info, "cannot require array & interleaved msaa layouts");
167 
168    if (require_interleaved) {
169       *msaa_layout = ISL_MSAA_LAYOUT_INTERLEAVED;
170       return true;
171    }
172 
173    /* Default to the array layout because it permits multisample
174     * compression.
175     */
176    *msaa_layout = ISL_MSAA_LAYOUT_ARRAY;
177    return true;
178 }
179 
180 /**
181  * @brief Filter out tiling flags that are incompatible with the surface.
182  *
183  * The resultant outgoing @a flags is a subset of the incoming @a flags. The
184  * outgoing flags may be empty (0x0) if the incoming flags were too
185  * restrictive.
186  *
187  * For example, if the surface will be used for a display
188  * (ISL_SURF_USAGE_DISPLAY_BIT), then this function filters out all tiling
189  * flags except ISL_TILING_X_BIT and ISL_TILING_LINEAR_BIT.
190  */
191 void
isl_gfx6_filter_tiling(const struct isl_device * dev,const struct isl_surf_init_info * restrict info,isl_tiling_flags_t * flags)192 isl_gfx6_filter_tiling(const struct isl_device *dev,
193                        const struct isl_surf_init_info *restrict info,
194                        isl_tiling_flags_t *flags)
195 {
196    /* IVB+ requires separate stencil */
197    assert(ISL_DEV_USE_SEPARATE_STENCIL(dev));
198 
199    /* Clear flags unsupported on this hardware */
200    assert(ISL_GFX_VERX10(dev) < 125);
201    if (ISL_GFX_VER(dev) >= 12) {
202       *flags &= ISL_TILING_LINEAR_BIT |
203                 ISL_TILING_X_BIT |
204                 ISL_TILING_Y0_BIT |
205                 ISL_TILING_ICL_Yf_BIT |
206                 ISL_TILING_ICL_Ys_BIT;
207    } else if (ISL_GFX_VER(dev) >= 11) {
208       *flags &= ISL_TILING_LINEAR_BIT |
209                 ISL_TILING_X_BIT |
210                 ISL_TILING_W_BIT |
211                 ISL_TILING_Y0_BIT |
212                 ISL_TILING_ICL_Yf_BIT |
213                 ISL_TILING_ICL_Ys_BIT;
214    } else if (ISL_GFX_VER(dev) >= 9) {
215       *flags &= ISL_TILING_LINEAR_BIT |
216                 ISL_TILING_X_BIT |
217                 ISL_TILING_W_BIT |
218                 ISL_TILING_Y0_BIT |
219                 ISL_TILING_SKL_Yf_BIT |
220                 ISL_TILING_SKL_Ys_BIT;
221    } else {
222       *flags &= ISL_TILING_LINEAR_BIT |
223                 ISL_TILING_X_BIT |
224                 ISL_TILING_W_BIT |
225                 ISL_TILING_Y0_BIT;
226    }
227 
228    /* TODO: Investigate Yf failures (~5000 VK CTS failures at the time of this
229     *       writing).
230     */
231    if (isl_format_is_compressed(info->format) ||
232        info->samples > 1 ||
233        info->dim == ISL_SURF_DIM_3D) {
234       *flags &= ~ISL_TILING_SKL_Yf_BIT; /* FINISHME[SKL]: Support Yf */
235       *flags &= ~ISL_TILING_ICL_Yf_BIT; /* FINISHME[ICL]: Support Yf */
236    }
237 
238    if (isl_surf_usage_is_depth(info->usage)) {
239       /* Depth requires Y. */
240       *flags &= ISL_TILING_ANY_Y_MASK;
241    }
242 
243    if (isl_surf_usage_is_depth_or_stencil(info->usage)) {
244       /* We choose to avoid Yf/Ys for 3D depth/stencil buffers. The swizzles
245        * for the Yf and Ys tilings are dependent on the image dimension. So,
246        * reads and writes should specify the same dimension to consistently
247        * interpret the data. This is not possible for 3D depth/stencil buffers
248        * however. Such buffers can be sampled from with a 3D view, but
249        * rendering is only possible with a 2D view due to the limitations of
250        * 3DSTATE_(DEPTH|STENCIL)_BUFFER.
251        */
252       if (info->dim == ISL_SURF_DIM_3D)
253          *flags &= ~ISL_TILING_STD_Y_MASK;
254    }
255 
256    /* Again, Yf and Ys tilings for 3D have a different swizzling than a 2D
257     * surface. So filter them out if the usage wants 2D/3D compatibility.
258     */
259    if (info->usage & ISL_SURF_USAGE_2D_3D_COMPATIBLE_BIT)
260       *flags &= ~ISL_TILING_STD_Y_MASK;
261 
262    /* For 3D storage images, we appear to have an undocumented dataport issue,
263     * where the RENDER_SURFACE_STATE::MinimumArrayElement is ignored with
264     * TileYs/TileYf.
265     *
266     * This is breaking VK_EXT_image_sliced_view_of_3d which is trying to
267     * access 3D images with an offset.
268     *
269     * It's unclear what the issue is but the behavior does not match
270     * simulation and there is no workaround related to 3D images & TileYs/Yf.
271     *
272     * We could workaround this issue by reading the offset from memory and add
273     * it to the imageLoad/Store() coordinates.
274     */
275    if (ISL_GFX_VER(dev) <= 11 &&
276        info->dim == ISL_SURF_DIM_3D &&
277        (info->usage & ISL_SURF_USAGE_STORAGE_BIT))
278       *flags &= ~ISL_TILING_STD_Y_MASK;
279 
280    if (isl_surf_usage_is_stencil(info->usage)) {
281       if (ISL_GFX_VER(dev) >= 12) {
282          /* Stencil requires Y. */
283          *flags &= ISL_TILING_ANY_Y_MASK;
284       } else {
285          /* Stencil requires W. */
286          *flags &= ISL_TILING_W_BIT;
287       }
288    } else {
289       *flags &= ~ISL_TILING_W_BIT;
290    }
291 
292    /* ICL PRMs, Volume 5: Memory Data Formats, 1D Alignment Requirements:
293     *
294     *    Tiled Resource Mode | Bits per Element | Horizontal Alignment
295     *    TRMODE_NONE         |      Any         |         64
296     *
297     * The table does not list any other tiled resource modes. On the other hand,
298     * the SKL PRM has entries for TRMODE_64KB and TRMODE_4KB. This suggests that
299     * standard tilings are no longer officially supported for 1D surfaces. We don't
300     * really have a use-case for it anyway, so we choose to match the later docs.
301     */
302    if (info->dim == ISL_SURF_DIM_1D)
303       *flags &= ~ISL_TILING_STD_Y_MASK;
304 
305    /* MCS buffers are always Y-tiled */
306    if (isl_format_get_layout(info->format)->txc == ISL_TXC_MCS)
307       *flags &= ISL_TILING_Y0_BIT;
308 
309    if (info->usage & ISL_SURF_USAGE_DISPLAY_BIT) {
310       if (ISL_GFX_VER(dev) >= 12) {
311          *flags &= (ISL_TILING_LINEAR_BIT | ISL_TILING_X_BIT |
312                     ISL_TILING_Y0_BIT);
313       } else if (ISL_GFX_VER(dev) >= 9) {
314          *flags &= (ISL_TILING_LINEAR_BIT | ISL_TILING_X_BIT |
315                     ISL_TILING_Y0_BIT |
316                     ISL_TILING_SKL_Yf_BIT | ISL_TILING_ICL_Yf_BIT);
317       } else {
318          /* Before Skylake, the display engine does not accept Y */
319          *flags &= (ISL_TILING_LINEAR_BIT | ISL_TILING_X_BIT);
320       }
321    }
322 
323    if (info->samples > 1) {
324       /* From the Sandybridge PRM, Volume 4 Part 1, SURFACE_STATE Tiled
325        * Surface:
326        *
327        *   For multisample render targets, this field must be 1 (true). MSRTs
328        *   can only be tiled.
329        *
330        * From the Broadwell PRM >> Volume2d: Command Structures >>
331        * RENDER_SURFACE_STATE Tile Mode:
332        *
333        *   If Number of Multisamples is not MULTISAMPLECOUNT_1, this field
334        *   must be YMAJOR.
335        *
336        * As usual, though, stencil is special and requires W-tiling.
337        */
338       *flags &= (ISL_TILING_ANY_Y_MASK | ISL_TILING_W_BIT);
339    }
340 
341    /* workaround */
342    if (ISL_GFX_VER(dev) == 7 &&
343        gfx7_format_needs_valign2(dev, info->format) &&
344        (info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) &&
345        info->samples == 1) {
346       /* Y tiling is illegal. From the Ivybridge PRM, Vol4 Part1 2.12.2.1,
347        * SURFACE_STATE Surface Vertical Alignment:
348        *
349        *     This field must be set to VALIGN_4 for all tiled Y Render Target
350        *     surfaces.
351        */
352       *flags &= ~ISL_TILING_Y0_BIT;
353    }
354 
355    /* From the Sandybridge PRM, Volume 1, Part 2, page 32:
356     *
357     *    "NOTE: 128BPE Format Color Buffer ( render target ) MUST be either
358     *     TileX or Linear."
359     *
360     * This is necessary all the way back to 965, but is permitted on Gfx7+.
361     */
362    if (ISL_GFX_VER(dev) < 7 && isl_format_get_layout(info->format)->bpb >= 128)
363       *flags &= ~ISL_TILING_Y0_BIT;
364 
365    /* From the BDW and SKL PRMs, Volume 2d,
366     * RENDER_SURFACE_STATE::Width - Programming Notes:
367     *
368     *   A known issue exists if a primitive is rendered to the first 2 rows and
369     *   last 2 columns of a 16K width surface. If any geometry is drawn inside
370     *   this square it will be copied to column X=2 and X=3 (arrangement on Y
371     *   position will stay the same). If any geometry exceeds the boundaries of
372     *   this 2x2 region it will be drawn normally. The issue also only occurs
373     *   if the surface has TileMode != Linear.
374     *
375     * [Internal documentation notes that this issue isn't present on SKL GT4.]
376     * To prevent this rendering corruption, only allow linear tiling for
377     * surfaces with widths greater than 16K-2 pixels.
378     *
379     * TODO: Is this an issue for multisampled surfaces as well?
380     */
381    if (info->width > 16382 && info->samples == 1 &&
382        info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT &&
383        (ISL_GFX_VER(dev) == 8 ||
384         (dev->info->platform == INTEL_PLATFORM_SKL && dev->info->gt != 4))) {
385           *flags &= ISL_TILING_LINEAR_BIT;
386    }
387 }
388 
389 void
isl_gfx7_choose_image_alignment_el(const struct isl_device * dev,const struct isl_surf_init_info * restrict info,enum isl_tiling tiling,enum isl_dim_layout dim_layout,enum isl_msaa_layout msaa_layout,struct isl_extent3d * image_align_el)390 isl_gfx7_choose_image_alignment_el(const struct isl_device *dev,
391                                    const struct isl_surf_init_info *restrict info,
392                                    enum isl_tiling tiling,
393                                    enum isl_dim_layout dim_layout,
394                                    enum isl_msaa_layout msaa_layout,
395                                    struct isl_extent3d *image_align_el)
396 {
397    assert(ISL_GFX_VER(dev) == 7);
398 
399    /* Handled by isl_choose_image_alignment_el */
400    assert(info->format != ISL_FORMAT_HIZ);
401 
402    /* IVB+ does not support combined depthstencil. */
403    assert(!isl_surf_usage_is_depth_and_stencil(info->usage));
404 
405    /* From the Ivy Bridge PRM, Vol. 2, Part 2, Section 6.18.4.4,
406     * "Alignment unit size", the alignment parameters are summarized in the
407     * following table:
408     *
409     *     Surface Defined By | Surface Format  | Align Width | Align Height
410     *    --------------------+-----------------+-------------+--------------
411     *       DEPTH_BUFFER     |   D16_UNORM     |      8      |      4
412     *                        |     other       |      4      |      4
413     *    --------------------+-----------------+-------------+--------------
414     *       STENCIL_BUFFER   |      N/A        |      8      |      8
415     *    --------------------+-----------------+-------------+--------------
416     *       SURFACE_STATE    | BC*, ETC*, EAC* |      4      |      4
417     *                        |      FXT1       |      8      |      4
418     *                        |   all others    |   HALIGN    |   VALIGN
419     *    -------------------------------------------------------------------
420     */
421    if (isl_surf_usage_is_depth(info->usage)) {
422       *image_align_el = info->format == ISL_FORMAT_R16_UNORM ?
423                         isl_extent3d(8, 4, 1) : isl_extent3d(4, 4, 1);
424       return;
425    } else if (isl_surf_usage_is_stencil(info->usage)) {
426       *image_align_el = isl_extent3d(8, 8, 1);
427       return;
428    } else if (isl_format_is_compressed(info->format)) {
429       /* Compressed formats all have alignment equal to block size. */
430       *image_align_el = isl_extent3d(1, 1, 1);
431       return;
432    }
433 
434    /* Everything after this point is in the "set by Surface Horizontal or
435     * Vertical Alignment" case.  Now it's just a matter of applying
436     * restrictions.
437     */
438 
439    /* There are no restrictions on halign beyond what's given in the table
440     * above.  We set it to the minimum value of 4 because that uses the least
441     * memory.
442     */
443    const uint32_t halign = 4;
444 
445    bool require_valign4 = false;
446 
447    /* From the Ivybridge PRM, Volume 4, Part 1, Section 2.12.1:
448     * RENDER_SURFACE_STATE Surface Vertical Alignment:
449     *
450     *    * This field is intended to be set to VALIGN_4 if the surface was
451     *      rendered as a depth buffer,
452     *
453     *    * for a multisampled (4x) render target, or for a multisampled (8x)
454     *      render target, since these surfaces support only alignment of 4.
455     *
456     *    * This field must be set to VALIGN_4 for all tiled Y Render Target
457     *      surfaces
458     *
459     *    * Value of 1 is not supported for format YCRCB_NORMAL (0x182),
460     *      YCRCB_SWAPUVY (0x183), YCRCB_SWAPUV (0x18f), YCRCB_SWAPY (0x190)
461     *
462     *    * If Number of Multisamples is not MULTISAMPLECOUNT_1, this field
463     *      must be set to VALIGN_4."
464     *
465     * The first restriction is already handled by the table above and the
466     * second restriction is redundant with the fifth.
467     */
468    if (info->samples > 1)
469       require_valign4 = true;
470 
471    if (tiling == ISL_TILING_Y0 &&
472        (info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT))
473       require_valign4 = true;
474 
475    assert(!(require_valign4 && gfx7_format_needs_valign2(dev, info->format)));
476 
477    /* We default to VALIGN_2 because it uses the least memory. */
478    const uint32_t valign = require_valign4 ? 4 : 2;
479 
480    *image_align_el = isl_extent3d(halign, valign, 1);
481 }
482