• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 bool
isl_gen7_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)28 isl_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 
154 static bool
gen7_format_needs_valign2(const struct isl_device * dev,enum isl_format format)155 gen7_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  */
184 void
isl_gen6_filter_tiling(const struct isl_device * dev,const struct isl_surf_init_info * restrict info,isl_tiling_flags_t * flags)185 isl_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  */
295 static uint32_t
gen7_choose_halign_el(const struct isl_device * dev,const struct isl_surf_init_info * restrict info)296 gen7_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  */
320 static uint32_t
gen7_choose_valign_el(const struct isl_device * dev,const struct isl_surf_init_info * restrict info,enum isl_tiling tiling)321 gen7_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 
390 void
isl_gen7_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)391 isl_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