OSDN Git Service

7fd9eeac5151ff4041d8a4af498f7844a2d52015
[android-x86/external-mesa.git] / src / intel / isl / isl.c
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 <assert.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "isl.h"
29 #include "isl_gen4.h"
30 #include "isl_gen6.h"
31 #include "isl_gen7.h"
32 #include "isl_gen8.h"
33 #include "isl_gen9.h"
34 #include "isl_priv.h"
35
36 void PRINTFLIKE(3, 4) UNUSED
37 __isl_finishme(const char *file, int line, const char *fmt, ...)
38 {
39    va_list ap;
40    char buf[512];
41
42    va_start(ap, fmt);
43    vsnprintf(buf, sizeof(buf), fmt, ap);
44    va_end(ap);
45
46    fprintf(stderr, "%s:%d: FINISHME: %s\n", file, line, buf);
47 }
48
49 void
50 isl_device_init(struct isl_device *dev,
51                 const struct brw_device_info *info,
52                 bool has_bit6_swizzling)
53 {
54    dev->info = info;
55    dev->use_separate_stencil = ISL_DEV_GEN(dev) >= 6;
56    dev->has_bit6_swizzling = has_bit6_swizzling;
57
58    /* The ISL_DEV macros may be defined in the CFLAGS, thus hardcoding some
59     * device properties at buildtime. Verify that the macros with the device
60     * properties chosen during runtime.
61     */
62    assert(ISL_DEV_GEN(dev) == dev->info->gen);
63    assert(ISL_DEV_USE_SEPARATE_STENCIL(dev) == dev->use_separate_stencil);
64
65    /* Did we break hiz or stencil? */
66    if (ISL_DEV_USE_SEPARATE_STENCIL(dev))
67       assert(info->has_hiz_and_separate_stencil);
68    if (info->must_use_separate_stencil)
69       assert(ISL_DEV_USE_SEPARATE_STENCIL(dev));
70 }
71
72 /**
73  * @brief Query the set of multisamples supported by the device.
74  *
75  * This function always returns non-zero, as ISL_SAMPLE_COUNT_1_BIT is always
76  * supported.
77  */
78 isl_sample_count_mask_t ATTRIBUTE_CONST
79 isl_device_get_sample_counts(struct isl_device *dev)
80 {
81    if (ISL_DEV_GEN(dev) >= 9) {
82       return ISL_SAMPLE_COUNT_1_BIT |
83              ISL_SAMPLE_COUNT_2_BIT |
84              ISL_SAMPLE_COUNT_4_BIT |
85              ISL_SAMPLE_COUNT_8_BIT |
86              ISL_SAMPLE_COUNT_16_BIT;
87    } else if (ISL_DEV_GEN(dev) >= 8) {
88       return ISL_SAMPLE_COUNT_1_BIT |
89              ISL_SAMPLE_COUNT_2_BIT |
90              ISL_SAMPLE_COUNT_4_BIT |
91              ISL_SAMPLE_COUNT_8_BIT;
92    } else if (ISL_DEV_GEN(dev) >= 7) {
93       return ISL_SAMPLE_COUNT_1_BIT |
94              ISL_SAMPLE_COUNT_4_BIT |
95              ISL_SAMPLE_COUNT_8_BIT;
96    } else if (ISL_DEV_GEN(dev) >= 6) {
97       return ISL_SAMPLE_COUNT_1_BIT |
98              ISL_SAMPLE_COUNT_4_BIT;
99    } else {
100       return ISL_SAMPLE_COUNT_1_BIT;
101    }
102 }
103
104 /**
105  * @param[out] info is written only on success
106  */
107 bool
108 isl_tiling_get_info(const struct isl_device *dev,
109                     enum isl_tiling tiling,
110                     uint32_t format_block_size,
111                     struct isl_tile_info *tile_info)
112 {
113    const uint32_t bs = format_block_size;
114    uint32_t width, height;
115
116    assert(bs > 0);
117
118    switch (tiling) {
119    case ISL_TILING_LINEAR:
120       width = 1;
121       height = 1;
122       break;
123
124    case ISL_TILING_X:
125       width = 1 << 9;
126       height = 1 << 3;
127       break;
128
129    case ISL_TILING_Y0:
130       width = 1 << 7;
131       height = 1 << 5;
132       break;
133
134    case ISL_TILING_W:
135       /* XXX: Should W tile be same as Y? */
136       width = 1 << 6;
137       height = 1 << 6;
138       break;
139
140    case ISL_TILING_Yf:
141    case ISL_TILING_Ys: {
142       if (ISL_DEV_GEN(dev) < 9)
143          return false;
144
145       if (!isl_is_pow2(bs))
146          return false;
147
148       bool is_Ys = tiling == ISL_TILING_Ys;
149
150       width = 1 << (6 + (ffs(bs) / 2) + (2 * is_Ys));
151       height = 1 << (6 - (ffs(bs) / 2) + (2 * is_Ys));
152       break;
153    }
154    } /* end switch */
155
156    *tile_info = (struct isl_tile_info) {
157       .tiling = tiling,
158       .width = width,
159       .height = height,
160       .size = width * height,
161    };
162
163    return true;
164 }
165
166 void
167 isl_tiling_get_extent(const struct isl_device *dev,
168                       enum isl_tiling tiling,
169                       uint32_t format_block_size,
170                       struct isl_extent2d *e)
171 {
172    struct isl_tile_info tile_info;
173    isl_tiling_get_info(dev, tiling, format_block_size, &tile_info);
174    *e = isl_extent2d(tile_info.width, tile_info.height);
175 }
176
177 /**
178  * @param[out] tiling is set only on success
179  */
180 bool
181 isl_surf_choose_tiling(const struct isl_device *dev,
182                        const struct isl_surf_init_info *restrict info,
183                        enum isl_tiling *tiling)
184 {
185    isl_tiling_flags_t tiling_flags = info->tiling_flags;
186
187    if (ISL_DEV_GEN(dev) >= 7) {
188       gen7_filter_tiling(dev, info, &tiling_flags);
189    } else {
190       isl_finishme("%s: gen%u", __func__, ISL_DEV_GEN(dev));
191       gen7_filter_tiling(dev, info, &tiling_flags);
192    }
193
194    #define CHOOSE(__tiling) \
195       do { \
196          if (tiling_flags & (1u << (__tiling))) { \
197             *tiling = (__tiling); \
198             return true; \
199           } \
200       } while (0)
201
202    /* Of the tiling modes remaining, choose the one that offers the best
203     * performance.
204     */
205
206    if (info->dim == ISL_SURF_DIM_1D) {
207       /* Prefer linear for 1D surfaces because they do not benefit from
208        * tiling. To the contrary, tiling leads to wasted memory and poor
209        * memory locality due to the swizzling and alignment restrictions
210        * required in tiled surfaces.
211        */
212       CHOOSE(ISL_TILING_LINEAR);
213    }
214
215    CHOOSE(ISL_TILING_Ys);
216    CHOOSE(ISL_TILING_Yf);
217    CHOOSE(ISL_TILING_Y0);
218    CHOOSE(ISL_TILING_X);
219    CHOOSE(ISL_TILING_W);
220    CHOOSE(ISL_TILING_LINEAR);
221
222    #undef CHOOSE
223
224    /* No tiling mode accomodates the inputs. */
225    return false;
226 }
227
228 static bool
229 isl_choose_msaa_layout(const struct isl_device *dev,
230                  const struct isl_surf_init_info *info,
231                  enum isl_tiling tiling,
232                  enum isl_msaa_layout *msaa_layout)
233 {
234    if (ISL_DEV_GEN(dev) >= 8) {
235       return gen8_choose_msaa_layout(dev, info, tiling, msaa_layout);
236    } else if (ISL_DEV_GEN(dev) >= 7) {
237       return gen7_choose_msaa_layout(dev, info, tiling, msaa_layout);
238    } else if (ISL_DEV_GEN(dev) >= 6) {
239       return gen6_choose_msaa_layout(dev, info, tiling, msaa_layout);
240    } else {
241       return gen4_choose_msaa_layout(dev, info, tiling, msaa_layout);
242    }
243 }
244
245 static void
246 isl_msaa_interleaved_scale_px_to_sa(uint32_t samples,
247                                     uint32_t *width, uint32_t *height)
248 {
249    assert(isl_is_pow2(samples));
250
251    /* From the Broadwell PRM >> Volume 5: Memory Views >> Computing Mip Level
252     * Sizes (p133):
253     *
254     *    If the surface is multisampled and it is a depth or stencil surface
255     *    or Multisampled Surface StorageFormat in SURFACE_STATE is
256     *    MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows before
257     *    proceeding: [...]
258     */
259    if (width)
260       *width = isl_align(*width, 2) << ((ffs(samples) - 0) / 2);
261    if (height)
262       *height = isl_align(*height, 2) << ((ffs(samples) - 1) / 2);
263 }
264
265 static enum isl_array_pitch_span
266 isl_choose_array_pitch_span(const struct isl_device *dev,
267                             const struct isl_surf_init_info *restrict info,
268                             enum isl_dim_layout dim_layout,
269                             const struct isl_extent4d *phys_level0_sa)
270 {
271    switch (dim_layout) {
272    case ISL_DIM_LAYOUT_GEN9_1D:
273    case ISL_DIM_LAYOUT_GEN4_2D:
274       if (ISL_DEV_GEN(dev) >= 8) {
275          /* QPitch becomes programmable in Broadwell. So choose the
276           * most compact QPitch possible in order to conserve memory.
277           *
278           * From the Broadwell PRM >> Volume 2d: Command Reference: Structures
279           * >> RENDER_SURFACE_STATE Surface QPitch (p325):
280           *
281           *    - Software must ensure that this field is set to a value
282           *      sufficiently large such that the array slices in the surface
283           *      do not overlap. Refer to the Memory Data Formats section for
284           *      information on how surfaces are stored in memory.
285           *
286           *    - This field specifies the distance in rows between array
287           *      slices.  It is used only in the following cases:
288           *
289           *          - Surface Array is enabled OR
290           *          - Number of Mulitsamples is not NUMSAMPLES_1 and
291           *            Multisampled Surface Storage Format set to MSFMT_MSS OR
292           *          - Surface Type is SURFTYPE_CUBE
293           */
294          return ISL_ARRAY_PITCH_SPAN_COMPACT;
295       } else if (ISL_DEV_GEN(dev) >= 7) {
296          /* Note that Ivybridge introduces
297           * RENDER_SURFACE_STATE.SurfaceArraySpacing, which provides the
298           * driver more control over the QPitch.
299           */
300
301          if (phys_level0_sa->array_len == 1) {
302             /* The hardware will never use the QPitch. So choose the most
303              * compact QPitch possible in order to conserve memory.
304              */
305             return ISL_ARRAY_PITCH_SPAN_COMPACT;
306          }
307
308          if (isl_surf_usage_is_depth_or_stencil(info->usage)) {
309             /* From the Ivybridge PRM >> Volume 1 Part 1: Graphics Core >>
310              * Section 6.18.4.7: Surface Arrays (p112):
311              *
312              *    If Surface Array Spacing is set to ARYSPC_FULL (note that
313              *    the depth buffer and stencil buffer have an implied value of
314              *    ARYSPC_FULL):
315              */
316             return ISL_ARRAY_PITCH_SPAN_COMPACT;
317          }
318
319          if (info->levels == 1) {
320             /* We are able to set RENDER_SURFACE_STATE.SurfaceArraySpacing
321              * to ARYSPC_LOD0.
322              */
323             return ISL_ARRAY_PITCH_SPAN_COMPACT;
324          }
325
326          return ISL_ARRAY_PITCH_SPAN_FULL;
327       } else if ((ISL_DEV_GEN(dev) == 5 || ISL_DEV_GEN(dev) == 6) &&
328                  ISL_DEV_USE_SEPARATE_STENCIL(dev) &&
329                  isl_surf_usage_is_stencil(info->usage)) {
330          /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1:
331           * Graphics Core >> Section 7.18.3.7: Surface Arrays:
332           *
333           *    The separate stencil buffer does not support mip mapping, thus
334           *    the storage for LODs other than LOD 0 is not needed.
335           */
336          assert(info->levels == 1);
337          assert(phys_level0_sa->array_len == 1);
338          return ISL_ARRAY_PITCH_SPAN_COMPACT;
339       } else {
340          if ((ISL_DEV_GEN(dev) == 5 || ISL_DEV_GEN(dev) == 6) &&
341              ISL_DEV_USE_SEPARATE_STENCIL(dev) &&
342              isl_surf_usage_is_stencil(info->usage)) {
343             /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1:
344              * Graphics Core >> Section 7.18.3.7: Surface Arrays:
345              *
346              *    The separate stencil buffer does not support mip mapping,
347              *    thus the storage for LODs other than LOD 0 is not needed.
348              */
349             assert(info->levels == 1);
350             assert(phys_level0_sa->array_len == 1);
351             return ISL_ARRAY_PITCH_SPAN_COMPACT;
352          }
353
354          if (phys_level0_sa->array_len == 1) {
355             /* The hardware will never use the QPitch. So choose the most
356              * compact QPitch possible in order to conserve memory.
357              */
358             return ISL_ARRAY_PITCH_SPAN_COMPACT;
359          }
360
361          return ISL_ARRAY_PITCH_SPAN_FULL;
362       }
363
364    case ISL_DIM_LAYOUT_GEN4_3D:
365       /* The hardware will never use the QPitch. So choose the most
366        * compact QPitch possible in order to conserve memory.
367        */
368       return ISL_ARRAY_PITCH_SPAN_COMPACT;
369    }
370
371    unreachable("bad isl_dim_layout");
372    return ISL_ARRAY_PITCH_SPAN_FULL;
373 }
374
375 static void
376 isl_choose_image_alignment_el(const struct isl_device *dev,
377                               const struct isl_surf_init_info *restrict info,
378                               enum isl_tiling tiling,
379                               enum isl_msaa_layout msaa_layout,
380                               struct isl_extent3d *image_align_el)
381 {
382    if (ISL_DEV_GEN(dev) >= 9) {
383       gen9_choose_image_alignment_el(dev, info, tiling, msaa_layout,
384                                      image_align_el);
385    } else if (ISL_DEV_GEN(dev) >= 8) {
386       gen8_choose_image_alignment_el(dev, info, tiling, msaa_layout,
387                                      image_align_el);
388    } else if (ISL_DEV_GEN(dev) >= 7) {
389       gen7_choose_image_alignment_el(dev, info, tiling, msaa_layout,
390                                      image_align_el);
391    } else if (ISL_DEV_GEN(dev) >= 6) {
392       gen6_choose_image_alignment_el(dev, info, tiling, msaa_layout,
393                                      image_align_el);
394    } else {
395       gen4_choose_image_alignment_el(dev, info, tiling, msaa_layout,
396                                      image_align_el);
397    }
398 }
399
400 static enum isl_dim_layout
401 isl_surf_choose_dim_layout(const struct isl_device *dev,
402                            enum isl_surf_dim logical_dim)
403 {
404    if (ISL_DEV_GEN(dev) >= 9) {
405       switch (logical_dim) {
406       case ISL_SURF_DIM_1D:
407          return ISL_DIM_LAYOUT_GEN9_1D;
408       case ISL_SURF_DIM_2D:
409       case ISL_SURF_DIM_3D:
410          return ISL_DIM_LAYOUT_GEN4_2D;
411       }
412    } else {
413       switch (logical_dim) {
414       case ISL_SURF_DIM_1D:
415       case ISL_SURF_DIM_2D:
416          return ISL_DIM_LAYOUT_GEN4_2D;
417       case ISL_SURF_DIM_3D:
418          return ISL_DIM_LAYOUT_GEN4_3D;
419       }
420    }
421
422    unreachable("bad isl_surf_dim");
423    return ISL_DIM_LAYOUT_GEN4_2D;
424 }
425
426 /**
427  * Calculate the physical extent of the surface's first level, in units of
428  * surface samples. The result is aligned to the format's compression block.
429  */
430 static void
431 isl_calc_phys_level0_extent_sa(const struct isl_device *dev,
432                                const struct isl_surf_init_info *restrict info,
433                                enum isl_dim_layout dim_layout,
434                                enum isl_tiling tiling,
435                                enum isl_msaa_layout msaa_layout,
436                                struct isl_extent4d *phys_level0_sa)
437 {
438    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
439
440    if (isl_format_is_yuv(info->format))
441       isl_finishme("%s:%s: YUV format", __FILE__, __func__);
442
443    switch (info->dim) {
444    case ISL_SURF_DIM_1D:
445       assert(info->height == 1);
446       assert(info->depth == 1);
447       assert(info->samples == 1);
448       assert(!isl_format_is_compressed(info->format));
449
450       switch (dim_layout) {
451       case ISL_DIM_LAYOUT_GEN4_3D:
452          unreachable("bad isl_dim_layout");
453
454       case ISL_DIM_LAYOUT_GEN9_1D:
455       case ISL_DIM_LAYOUT_GEN4_2D:
456          *phys_level0_sa = (struct isl_extent4d) {
457             .w = info->width,
458             .h = 1,
459             .d = 1,
460             .a = info->array_len,
461          };
462          break;
463       }
464       break;
465
466    case ISL_SURF_DIM_2D:
467       assert(dim_layout == ISL_DIM_LAYOUT_GEN4_2D);
468
469       if (tiling == ISL_TILING_Ys && info->samples > 1)
470          isl_finishme("%s:%s: multisample TileYs layout", __FILE__, __func__);
471
472       switch (msaa_layout) {
473       case ISL_MSAA_LAYOUT_NONE:
474          assert(info->depth == 1);
475          assert(info->samples == 1);
476
477          *phys_level0_sa = (struct isl_extent4d) {
478             .w = isl_align(info->width, fmtl->bw),
479             .h = isl_align(info->height, fmtl->bh),
480             .d = 1,
481             .a = info->array_len,
482          };
483          break;
484
485       case ISL_MSAA_LAYOUT_ARRAY:
486          assert(info->depth == 1);
487          assert(info->array_len == 1);
488          assert(!isl_format_is_compressed(info->format));
489
490          *phys_level0_sa = (struct isl_extent4d) {
491             .w = info->width,
492             .h = info->height,
493             .d = 1,
494             .a = info->samples,
495          };
496          break;
497
498       case ISL_MSAA_LAYOUT_INTERLEAVED:
499          assert(info->depth == 1);
500          assert(info->array_len == 1);
501          assert(!isl_format_is_compressed(info->format));
502
503          *phys_level0_sa = (struct isl_extent4d) {
504             .w = info->width,
505             .h = info->height,
506             .d = 1,
507             .a = 1,
508          };
509
510          isl_msaa_interleaved_scale_px_to_sa(info->samples,
511                                              &phys_level0_sa->w,
512                                              &phys_level0_sa->h);
513          break;
514       }
515       break;
516
517    case ISL_SURF_DIM_3D:
518       assert(info->array_len == 1);
519       assert(info->samples == 1);
520
521       if (fmtl->bd > 1) {
522          isl_finishme("%s:%s: compression block with depth > 1",
523                       __FILE__, __func__);
524       }
525
526       switch (dim_layout) {
527       case ISL_DIM_LAYOUT_GEN9_1D:
528          unreachable("bad isl_dim_layout");
529
530       case ISL_DIM_LAYOUT_GEN4_2D:
531          assert(ISL_DEV_GEN(dev) >= 9);
532
533          *phys_level0_sa = (struct isl_extent4d) {
534             .w = isl_align(info->width, fmtl->bw),
535             .h = isl_align(info->height, fmtl->bh),
536             .d = 1,
537             .a = info->depth,
538          };
539          break;
540
541       case ISL_DIM_LAYOUT_GEN4_3D:
542          assert(ISL_DEV_GEN(dev) < 9);
543          *phys_level0_sa = (struct isl_extent4d) {
544             .w = isl_align(info->width, fmtl->bw),
545             .h = isl_align(info->height, fmtl->bh),
546             .d = info->depth,
547             .a = 1,
548          };
549          break;
550       }
551       break;
552    }
553 }
554
555 /**
556  * A variant of isl_calc_phys_slice0_extent_sa() specific to
557  * ISL_DIM_LAYOUT_GEN4_2D.
558  */
559 static void
560 isl_calc_phys_slice0_extent_sa_gen4_2d(
561       const struct isl_device *dev,
562       const struct isl_surf_init_info *restrict info,
563       enum isl_msaa_layout msaa_layout,
564       const struct isl_extent3d *image_align_sa,
565       const struct isl_extent4d *phys_level0_sa,
566       struct isl_extent2d *phys_slice0_sa)
567 {
568    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
569
570    assert(phys_level0_sa->depth == 1);
571
572    if (info->levels == 1 && msaa_layout != ISL_MSAA_LAYOUT_INTERLEAVED) {
573       /* Do not pad the surface to the image alignment. Instead, pad it only
574        * to the pixel format's block alignment.
575        *
576        * For tiled surfaces, using a reduced alignment here avoids wasting CPU
577        * cycles on the below mipmap layout caluclations. Reducing the
578        * alignment here is safe because we later align the row pitch and array
579        * pitch to the tile boundary. It is safe even for
580        * ISL_MSAA_LAYOUT_INTERLEAVED, because phys_level0_sa is already scaled
581        * to accomodate the interleaved samples.
582        *
583        * For linear surfaces, reducing the alignment here permits us to later
584        * choose an arbitrary, non-aligned row pitch. If the surface backs
585        * a VkBuffer, then an arbitrary pitch may be needed to accomodate
586        * VkBufferImageCopy::bufferRowLength.
587        */
588       *phys_slice0_sa = (struct isl_extent2d) {
589          .w = isl_align_npot(phys_level0_sa->w, fmtl->bw),
590          .h = isl_align_npot(phys_level0_sa->h, fmtl->bh),
591       };
592       return;
593    }
594
595    uint32_t slice_top_w = 0;
596    uint32_t slice_bottom_w = 0;
597    uint32_t slice_left_h = 0;
598    uint32_t slice_right_h = 0;
599
600    uint32_t W0 = phys_level0_sa->w;
601    uint32_t H0 = phys_level0_sa->h;
602
603    for (uint32_t l = 0; l < info->levels; ++l) {
604       uint32_t W = isl_minify(W0, l);
605       uint32_t H = isl_minify(H0, l);
606
607       if (msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED) {
608          /* From the Broadwell PRM >> Volume 5: Memory Views >> Computing Mip Level
609           * Sizes (p133):
610           *
611           *    If the surface is multisampled and it is a depth or stencil
612           *    surface or Multisampled Surface StorageFormat in
613           *    SURFACE_STATE is MSFMT_DEPTH_STENCIL, W_L and H_L must be
614           *    adjusted as follows before proceeding: [...]
615           */
616          isl_msaa_interleaved_scale_px_to_sa(info->samples, &W, &H);
617       }
618
619       uint32_t w = isl_align_npot(W, image_align_sa->w);
620       uint32_t h = isl_align_npot(H, image_align_sa->h);
621
622       if (l == 0) {
623          slice_top_w = w;
624          slice_left_h = h;
625          slice_right_h = h;
626       } else if (l == 1) {
627          slice_bottom_w = w;
628          slice_left_h += h;
629       } else if (l == 2) {
630          slice_bottom_w += w;
631          slice_right_h += h;
632       } else {
633          slice_right_h += h;
634       }
635    }
636
637    *phys_slice0_sa = (struct isl_extent2d) {
638       .w = MAX(slice_top_w, slice_bottom_w),
639       .h = MAX(slice_left_h, slice_right_h),
640    };
641 }
642
643 /**
644  * A variant of isl_calc_phys_slice0_extent_sa() specific to
645  * ISL_DIM_LAYOUT_GEN4_3D.
646  */
647 static void
648 isl_calc_phys_slice0_extent_sa_gen4_3d(
649       const struct isl_device *dev,
650       const struct isl_surf_init_info *restrict info,
651       const struct isl_extent3d *image_align_sa,
652       const struct isl_extent4d *phys_level0_sa,
653       struct isl_extent2d *phys_slice0_sa)
654 {
655    assert(info->samples == 1);
656    assert(phys_level0_sa->array_len == 1);
657
658    uint32_t slice_w = 0;
659    uint32_t slice_h = 0;
660
661    uint32_t W0 = phys_level0_sa->w;
662    uint32_t H0 = phys_level0_sa->h;
663    uint32_t D0 = phys_level0_sa->d;
664
665    for (uint32_t l = 0; l < info->levels; ++l) {
666       uint32_t level_w = isl_align_npot(isl_minify(W0, l), image_align_sa->w);
667       uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa->h);
668       uint32_t level_d = isl_align_npot(isl_minify(D0, l), image_align_sa->d);
669
670       uint32_t max_layers_horiz = MIN(level_d, 1u << l);
671       uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l);
672
673       slice_w = MAX(slice_w, level_w * max_layers_horiz);
674       slice_h += level_h * max_layers_vert;
675    }
676
677    *phys_slice0_sa = (struct isl_extent2d) {
678       .w = slice_w,
679       .h = slice_h,
680    };
681 }
682
683 /**
684  * A variant of isl_calc_phys_slice0_extent_sa() specific to
685  * ISL_DIM_LAYOUT_GEN9_1D.
686  */
687 static void
688 isl_calc_phys_slice0_extent_sa_gen9_1d(
689       const struct isl_device *dev,
690       const struct isl_surf_init_info *restrict info,
691       const struct isl_extent3d *image_align_sa,
692       const struct isl_extent4d *phys_level0_sa,
693       struct isl_extent2d *phys_slice0_sa)
694 {
695    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
696
697    assert(phys_level0_sa->height == 1);
698    assert(phys_level0_sa->depth == 1);
699    assert(info->samples == 1);
700    assert(image_align_sa->w >= fmtl->bw);
701
702    uint32_t slice_w = 0;
703    const uint32_t W0 = phys_level0_sa->w;
704
705    for (uint32_t l = 0; l < info->levels; ++l) {
706       uint32_t W = isl_minify(W0, l);
707       uint32_t w = isl_align_npot(W, image_align_sa->w);
708
709       slice_w += w;
710    }
711
712    *phys_slice0_sa = isl_extent2d(slice_w, 1);
713 }
714
715 /**
716  * Calculate the physical extent of the surface's first array slice, in units
717  * of surface samples. If the surface is multi-leveled, then the result will
718  * be aligned to \a image_align_sa.
719  */
720 static void
721 isl_calc_phys_slice0_extent_sa(const struct isl_device *dev,
722                                const struct isl_surf_init_info *restrict info,
723                                enum isl_dim_layout dim_layout,
724                                enum isl_msaa_layout msaa_layout,
725                                const struct isl_extent3d *image_align_sa,
726                                const struct isl_extent4d *phys_level0_sa,
727                                struct isl_extent2d *phys_slice0_sa)
728 {
729    switch (dim_layout) {
730    case ISL_DIM_LAYOUT_GEN9_1D:
731       isl_calc_phys_slice0_extent_sa_gen9_1d(dev, info,
732                                              image_align_sa, phys_level0_sa,
733                                              phys_slice0_sa);
734       return;
735    case ISL_DIM_LAYOUT_GEN4_2D:
736       isl_calc_phys_slice0_extent_sa_gen4_2d(dev, info, msaa_layout,
737                                              image_align_sa, phys_level0_sa,
738                                              phys_slice0_sa);
739       return;
740    case ISL_DIM_LAYOUT_GEN4_3D:
741       isl_calc_phys_slice0_extent_sa_gen4_3d(dev, info, image_align_sa,
742                                              phys_level0_sa, phys_slice0_sa);
743       return;
744    }
745 }
746
747 /**
748  * Calculate the pitch between physical array slices, in units of rows of
749  * surface elements.
750  */
751 static uint32_t
752 isl_calc_array_pitch_el_rows(const struct isl_device *dev,
753                              const struct isl_surf_init_info *restrict info,
754                              const struct isl_tile_info *tile_info,
755                              enum isl_dim_layout dim_layout,
756                              enum isl_array_pitch_span array_pitch_span,
757                              const struct isl_extent3d *image_align_sa,
758                              const struct isl_extent4d *phys_level0_sa,
759                              const struct isl_extent2d *phys_slice0_sa)
760 {
761    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
762    uint32_t pitch_sa_rows = 0;
763
764    switch (dim_layout) {
765    case ISL_DIM_LAYOUT_GEN9_1D:
766       /* Each row is an array slice */
767       pitch_sa_rows = 1;
768       break;
769    case ISL_DIM_LAYOUT_GEN4_2D:
770       switch (array_pitch_span) {
771       case ISL_ARRAY_PITCH_SPAN_COMPACT:
772          pitch_sa_rows = isl_align_npot(phys_slice0_sa->h, image_align_sa->h);
773          break;
774       case ISL_ARRAY_PITCH_SPAN_FULL: {
775          /* The QPitch equation is found in the Broadwell PRM >> Volume 5:
776           * Memory Views >> Common Surface Formats >> Surface Layout >> 2D
777           * Surfaces >> Surface Arrays.
778           */
779          uint32_t H0_sa = phys_level0_sa->h;
780          uint32_t H1_sa = isl_minify(H0_sa, 1);
781
782          uint32_t h0_sa = isl_align_npot(H0_sa, image_align_sa->h);
783          uint32_t h1_sa = isl_align_npot(H1_sa, image_align_sa->h);
784
785          uint32_t m;
786          if (ISL_DEV_GEN(dev) >= 7) {
787             /* The QPitch equation changed slightly in Ivybridge. */
788             m = 12;
789          } else {
790             m = 11;
791          }
792
793          pitch_sa_rows = h0_sa + h1_sa + (m * image_align_sa->h);
794
795          if (ISL_DEV_GEN(dev) == 6 && info->samples > 1 &&
796              (info->height % 4 == 1)) {
797             /* [SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1:
798              * Graphics Core >> Section 7.18.3.7: Surface Arrays:
799              *
800              *    [SNB] Errata: Sampler MSAA Qpitch will be 4 greater than
801              *    the value calculated in the equation above , for every
802              *    other odd Surface Height starting from 1 i.e. 1,5,9,13.
803              *
804              * XXX(chadv): Is the errata natural corollary of the physical
805              * layout of interleaved samples?
806              */
807             pitch_sa_rows += 4;
808          }
809
810          pitch_sa_rows = isl_align_npot(pitch_sa_rows, fmtl->bh);
811          } /* end case */
812          break;
813       }
814       break;
815    case ISL_DIM_LAYOUT_GEN4_3D:
816       assert(array_pitch_span == ISL_ARRAY_PITCH_SPAN_COMPACT);
817       pitch_sa_rows = isl_align_npot(phys_slice0_sa->h, image_align_sa->h);
818       break;
819    default:
820       unreachable("bad isl_dim_layout");
821       break;
822    }
823
824    assert(pitch_sa_rows % fmtl->bh == 0);
825    uint32_t pitch_el_rows = pitch_sa_rows / fmtl->bh;
826
827    if (ISL_DEV_GEN(dev) >= 9 &&
828        info->dim == ISL_SURF_DIM_3D &&
829        tile_info->tiling != ISL_TILING_LINEAR) {
830       /* From the Skylake BSpec >> RENDER_SURFACE_STATE >> Surface QPitch:
831        *
832        *    Tile Mode != Linear: This field must be set to an integer multiple
833        *    of the tile height
834        */
835       pitch_el_rows = isl_align(pitch_el_rows, tile_info->height);
836    }
837
838    return pitch_el_rows;
839 }
840
841 /**
842  * Calculate the pitch of each surface row, in bytes.
843  */
844 static uint32_t
845 isl_calc_row_pitch(const struct isl_device *dev,
846                    const struct isl_surf_init_info *restrict info,
847                    const struct isl_tile_info *tile_info,
848                    const struct isl_extent3d *image_align_sa,
849                    const struct isl_extent2d *phys_slice0_sa)
850 {
851    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
852
853    uint32_t row_pitch = info->min_pitch;
854
855    /* First, align the surface to a cache line boundary, as the PRM explains
856     * below.
857     *
858     * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
859     * Formats >> Surface Padding Requirements >> Render Target and Media
860     * Surfaces:
861     *
862     *    The data port accesses data (pixels) outside of the surface if they
863     *    are contained in the same cache request as pixels that are within the
864     *    surface. These pixels will not be returned by the requesting message,
865     *    however if these pixels lie outside of defined pages in the GTT,
866     *    a GTT error will result when the cache request is processed. In order
867     *    to avoid these GTT errors, “padding” at the bottom of the surface is
868     *    sometimes necessary.
869     *
870     * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
871     * Formats >> Surface Padding Requirements >> Sampling Engine Surfaces:
872     *
873     *    The sampling engine accesses texels outside of the surface if they
874     *    are contained in the same cache line as texels that are within the
875     *    surface.  These texels will not participate in any calculation
876     *    performed by the sampling engine and will not affect the result of
877     *    any sampling engine operation, however if these texels lie outside of
878     *    defined pages in the GTT, a GTT error will result when the cache line
879     *    is accessed. In order to avoid these GTT errors, “padding” at the
880     *    bottom and right side of a sampling engine surface is sometimes
881     *    necessary.
882     *
883     *    It is possible that a cache line will straddle a page boundary if the
884     *    base address or pitch is not aligned. All pages included in the cache
885     *    lines that are part of the surface must map to valid GTT entries to
886     *    avoid errors. To determine the necessary padding on the bottom and
887     *    right side of the surface, refer to the table in  Alignment Unit Size
888     *    section for the i and j parameters for the surface format in use. The
889     *    surface must then be extended to the next multiple of the alignment
890     *    unit size in each dimension, and all texels contained in this
891     *    extended surface must have valid GTT entries.
892     *
893     *    For example, suppose the surface size is 15 texels by 10 texels and
894     *    the alignment parameters are i=4 and j=2. In this case, the extended
895     *    surface would be 16 by 10. Note that these calculations are done in
896     *    texels, and must be converted to bytes based on the surface format
897     *    being used to determine whether additional pages need to be defined.
898     */
899    assert(phys_slice0_sa->w % fmtl->bw == 0);
900    row_pitch = MAX(row_pitch, fmtl->bs * (phys_slice0_sa->w / fmtl->bw));
901
902    switch (tile_info->tiling) {
903    case ISL_TILING_LINEAR:
904       /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >>
905        * RENDER_SURFACE_STATE Surface Pitch (p349):
906        *
907        *    - For linear render target surfaces and surfaces accessed with the
908        *      typed data port messages, the pitch must be a multiple of the
909        *      element size for non-YUV surface formats.  Pitch must be
910        *      a multiple of 2 * element size for YUV surface formats.
911        *
912        *    - [Requirements for SURFTYPE_BUFFER and SURFTYPE_STRBUF, which we
913        *      ignore because isl doesn't do buffers.]
914        *
915        *    - For other linear surfaces, the pitch can be any multiple of
916        *      bytes.
917        */
918       if (info->usage & ISL_SURF_USAGE_RENDER_TARGET_BIT) {
919          if (isl_format_is_yuv(info->format)) {
920             row_pitch = isl_align_npot(row_pitch, 2 * fmtl->bs);
921          } else  {
922             row_pitch = isl_align_npot(row_pitch, fmtl->bs);
923          }
924       }
925       break;
926    default:
927       /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >>
928        * RENDER_SURFACE_STATE Surface Pitch (p349):
929        *
930        *    - For tiled surfaces, the pitch must be a multiple of the tile
931        *      width.
932        */
933       row_pitch = isl_align(row_pitch, tile_info->width);
934       break;
935    }
936
937    return row_pitch;
938 }
939
940 /**
941  * Calculate the surface's total height, including padding, in units of
942  * surface elements.
943  */
944 static uint32_t
945 isl_calc_total_height_el(const struct isl_device *dev,
946                          const struct isl_surf_init_info *restrict info,
947                          const struct isl_tile_info *tile_info,
948                          uint32_t phys_array_len,
949                          uint32_t row_pitch,
950                          uint32_t array_pitch_el_rows)
951 {
952    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
953
954    uint32_t total_h_el = phys_array_len * array_pitch_el_rows;
955    uint32_t pad_bytes = 0;
956
957    /* From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
958     * Formats >> Surface Padding Requirements >> Render Target and Media
959     * Surfaces:
960     *
961     *   The data port accesses data (pixels) outside of the surface if they
962     *   are contained in the same cache request as pixels that are within the
963     *   surface. These pixels will not be returned by the requesting message,
964     *   however if these pixels lie outside of defined pages in the GTT,
965     *   a GTT error will result when the cache request is processed. In
966     *   order to avoid these GTT errors, “padding” at the bottom of the
967     *   surface is sometimes necessary.
968     *
969     * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
970     * Formats >> Surface Padding Requirements >> Sampling Engine Surfaces:
971     *
972     *    ... Lots of padding requirements, all listed separately below.
973     */
974
975    /* We can safely ignore the first padding requirement, quoted below,
976     * because isl doesn't do buffers.
977     *
978     *    - [pre-BDW] For buffers, which have no inherent “height,” padding
979     *      requirements are different. A buffer must be padded to the next
980     *      multiple of 256 array elements, with an additional 16 bytes added
981     *      beyond that to account for the L1 cache line.
982     */
983
984    /*
985     *    - For compressed textures [...], padding at the bottom of the surface
986     *      is to an even compressed row.
987     */
988    if (isl_format_is_compressed(info->format))
989       total_h_el = isl_align(total_h_el, 2);
990
991    /*
992     *    - For cube surfaces, an additional two rows of padding are required
993     *      at the bottom of the surface.
994     */
995    if (info->usage & ISL_SURF_USAGE_CUBE_BIT)
996       total_h_el += 2;
997
998    /*
999     *    - For packed YUV, 96 bpt, 48 bpt, and 24 bpt surface formats,
1000     *      additional padding is required. These surfaces require an extra row
1001     *      plus 16 bytes of padding at the bottom in addition to the general
1002     *      padding requirements.
1003     */
1004    if (isl_format_is_yuv(info->format) &&
1005        (fmtl->bs == 96 || fmtl->bs == 48|| fmtl->bs == 24)) {
1006       total_h_el += 1;
1007       pad_bytes += 16;
1008    }
1009
1010    /*
1011     *    - For linear surfaces, additional padding of 64 bytes is required at
1012     *      the bottom of the surface. This is in addition to the padding
1013     *      required above.
1014     */
1015    if (tile_info->tiling == ISL_TILING_LINEAR)
1016       pad_bytes += 64;
1017
1018    /* The below text weakens, not strengthens, the padding requirements for
1019     * linear surfaces. Therefore we can safely ignore it.
1020     *
1021     *    - [BDW+] For SURFTYPE_BUFFER, SURFTYPE_1D, and SURFTYPE_2D non-array,
1022     *      non-MSAA, non-mip-mapped surfaces in linear memory, the only
1023     *      padding requirement is to the next aligned 64-byte boundary beyond
1024     *      the end of the surface. The rest of the padding requirements
1025     *      documented above do not apply to these surfaces.
1026     */
1027
1028    /*
1029     *    - [SKL+] For SURFTYPE_2D and SURFTYPE_3D with linear mode and
1030     *      height % 4 != 0, the surface must be padded with
1031     *      4-(height % 4)*Surface Pitch # of bytes.
1032     */
1033    if (ISL_DEV_GEN(dev) >= 9 &&
1034        tile_info->tiling == ISL_TILING_LINEAR &&
1035        (info->dim == ISL_SURF_DIM_2D || info->dim == ISL_SURF_DIM_3D)) {
1036       total_h_el = isl_align(total_h_el, 4);
1037    }
1038
1039    /*
1040     *    - [SKL+] For SURFTYPE_1D with linear mode, the surface must be padded
1041     *      to 4 times the Surface Pitch # of bytes
1042     */
1043    if (ISL_DEV_GEN(dev) >= 9 &&
1044        tile_info->tiling == ISL_TILING_LINEAR &&
1045        info->dim == ISL_SURF_DIM_1D) {
1046       total_h_el += 4;
1047    }
1048
1049    /* Be sloppy. Align any leftover padding to a row boundary. */
1050    total_h_el += isl_align_div_npot(pad_bytes, row_pitch);
1051
1052    return total_h_el;
1053 }
1054
1055 bool
1056 isl_surf_init_s(const struct isl_device *dev,
1057                 struct isl_surf *surf,
1058                 const struct isl_surf_init_info *restrict info)
1059 {
1060    const struct isl_format_layout *fmtl = isl_format_get_layout(info->format);
1061
1062    const struct isl_extent4d logical_level0_px = {
1063       .w = info->width,
1064       .h = info->height,
1065       .d = info->depth,
1066       .a = info->array_len,
1067    };
1068
1069    enum isl_dim_layout dim_layout =
1070       isl_surf_choose_dim_layout(dev, info->dim);
1071
1072    enum isl_tiling tiling;
1073    if (!isl_surf_choose_tiling(dev, info, &tiling))
1074       return false;
1075
1076    struct isl_tile_info tile_info;
1077    if (!isl_tiling_get_info(dev, tiling, fmtl->bs, &tile_info))
1078       return false;
1079
1080    enum isl_msaa_layout msaa_layout;
1081    if (!isl_choose_msaa_layout(dev, info, tiling, &msaa_layout))
1082        return false;
1083
1084    struct isl_extent3d image_align_el;
1085    isl_choose_image_alignment_el(dev, info, tiling, msaa_layout,
1086                                  &image_align_el);
1087
1088    struct isl_extent3d image_align_sa =
1089       isl_extent3d_el_to_sa(info->format, image_align_el);
1090
1091    struct isl_extent4d phys_level0_sa;
1092    isl_calc_phys_level0_extent_sa(dev, info, dim_layout, tiling, msaa_layout,
1093                                   &phys_level0_sa);
1094    assert(phys_level0_sa.w % fmtl->bw == 0);
1095    assert(phys_level0_sa.h % fmtl->bh == 0);
1096
1097    enum isl_array_pitch_span array_pitch_span =
1098       isl_choose_array_pitch_span(dev, info, dim_layout, &phys_level0_sa);
1099
1100    struct isl_extent2d phys_slice0_sa;
1101    isl_calc_phys_slice0_extent_sa(dev, info, dim_layout, msaa_layout,
1102                                   &image_align_sa, &phys_level0_sa,
1103                                   &phys_slice0_sa);
1104    assert(phys_slice0_sa.w % fmtl->bw == 0);
1105    assert(phys_slice0_sa.h % fmtl->bh == 0);
1106
1107    const uint32_t row_pitch = isl_calc_row_pitch(dev, info, &tile_info,
1108                                                  &image_align_sa,
1109                                                  &phys_slice0_sa);
1110
1111    const uint32_t array_pitch_el_rows =
1112       isl_calc_array_pitch_el_rows(dev, info, &tile_info, dim_layout,
1113                                    array_pitch_span, &image_align_sa,
1114                                    &phys_level0_sa, &phys_slice0_sa);
1115
1116    const uint32_t total_h_el =
1117       isl_calc_total_height_el(dev, info, &tile_info,
1118                                phys_level0_sa.array_len, row_pitch,
1119                                array_pitch_el_rows);
1120
1121    const uint32_t total_h_sa = total_h_el * fmtl->bh;
1122    const uint32_t size = row_pitch * isl_align(total_h_sa, tile_info.height);
1123
1124    /* Alignment of surface base address, in bytes */
1125    uint32_t base_alignment = MAX(1, info->min_alignment);
1126    assert(isl_is_pow2(base_alignment) && isl_is_pow2(tile_info.size));
1127    base_alignment = MAX(base_alignment, tile_info.size);
1128
1129    *surf = (struct isl_surf) {
1130       .dim = info->dim,
1131       .dim_layout = dim_layout,
1132       .msaa_layout = msaa_layout,
1133       .tiling = tiling,
1134       .format = info->format,
1135
1136       .levels = info->levels,
1137       .samples = info->samples,
1138
1139       .image_alignment_el = image_align_el,
1140       .logical_level0_px = logical_level0_px,
1141       .phys_level0_sa = phys_level0_sa,
1142
1143       .size = size,
1144       .alignment = base_alignment,
1145       .row_pitch = row_pitch,
1146       .array_pitch_el_rows = array_pitch_el_rows,
1147       .array_pitch_span = array_pitch_span,
1148
1149       .usage = info->usage,
1150    };
1151
1152    return true;
1153 }
1154
1155 void
1156 isl_surf_get_tile_info(const struct isl_device *dev,
1157                        const struct isl_surf *surf,
1158                        struct isl_tile_info *tile_info)
1159 {
1160    const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
1161    isl_tiling_get_info(dev, surf->tiling, fmtl->bs, tile_info);
1162 }
1163
1164 void
1165 isl_surf_fill_state_s(const struct isl_device *dev, void *state,
1166                       const struct isl_surf_fill_state_info *restrict info)
1167 {
1168 #ifndef NDEBUG
1169    isl_surf_usage_flags_t _base_usage =
1170       info->view->usage & (ISL_SURF_USAGE_RENDER_TARGET_BIT |
1171                            ISL_SURF_USAGE_TEXTURE_BIT |
1172                            ISL_SURF_USAGE_STORAGE_BIT);
1173    /* They may only specify one of the above bits at a time */
1174    assert(__builtin_popcount(_base_usage) == 1);
1175    /* The only other allowed bit is ISL_SURF_USAGE_CUBE_BIT */
1176    assert((info->view->usage & ~ISL_SURF_USAGE_CUBE_BIT) == _base_usage);
1177 #endif
1178
1179    if (info->surf->dim == ISL_SURF_DIM_3D) {
1180       assert(info->view->base_array_layer + info->view->array_len <=
1181              info->surf->logical_level0_px.depth);
1182    } else {
1183       assert(info->view->base_array_layer + info->view->array_len <=
1184              info->surf->logical_level0_px.array_len);
1185    }
1186
1187    switch (ISL_DEV_GEN(dev)) {
1188    case 7:
1189       if (ISL_DEV_IS_HASWELL(dev)) {
1190          isl_gen75_surf_fill_state_s(dev, state, info);
1191       } else {
1192          isl_gen7_surf_fill_state_s(dev, state, info);
1193       }
1194       break;
1195    case 8:
1196       isl_gen8_surf_fill_state_s(dev, state, info);
1197       break;
1198    case 9:
1199       isl_gen9_surf_fill_state_s(dev, state, info);
1200       break;
1201    default:
1202       assert(!"Cannot fill surface state for this gen");
1203    }
1204 }
1205
1206 void
1207 isl_buffer_fill_state_s(const struct isl_device *dev, void *state,
1208                         const struct isl_buffer_fill_state_info *restrict info)
1209 {
1210    switch (ISL_DEV_GEN(dev)) {
1211    case 7:
1212       if (ISL_DEV_IS_HASWELL(dev)) {
1213          isl_gen75_buffer_fill_state_s(state, info);
1214       } else {
1215          isl_gen7_buffer_fill_state_s(state, info);
1216       }
1217       break;
1218    case 8:
1219       isl_gen8_buffer_fill_state_s(state, info);
1220       break;
1221    case 9:
1222       isl_gen9_buffer_fill_state_s(state, info);
1223       break;
1224    default:
1225       assert(!"Cannot fill surface state for this gen");
1226    }
1227 }
1228
1229 /**
1230  * A variant of isl_surf_get_image_offset_sa() specific to
1231  * ISL_DIM_LAYOUT_GEN4_2D.
1232  */
1233 static void
1234 get_image_offset_sa_gen4_2d(const struct isl_surf *surf,
1235                             uint32_t level, uint32_t layer,
1236                             uint32_t *x_offset_sa,
1237                             uint32_t *y_offset_sa)
1238 {
1239    assert(level < surf->levels);
1240    assert(layer < surf->phys_level0_sa.array_len);
1241    assert(surf->phys_level0_sa.depth == 1);
1242
1243    const struct isl_extent3d image_align_sa =
1244       isl_surf_get_image_alignment_sa(surf);
1245
1246    const uint32_t W0 = surf->phys_level0_sa.width;
1247    const uint32_t H0 = surf->phys_level0_sa.height;
1248
1249    uint32_t x = 0;
1250    uint32_t y = layer * isl_surf_get_array_pitch_sa_rows(surf);
1251
1252    for (uint32_t l = 0; l < level; ++l) {
1253       if (l == 1) {
1254          uint32_t W = isl_minify(W0, l);
1255
1256          if (surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED)
1257             isl_msaa_interleaved_scale_px_to_sa(surf->samples, &W, NULL);
1258
1259          x += isl_align_npot(W, image_align_sa.w);
1260       } else {
1261          uint32_t H = isl_minify(H0, l);
1262
1263          if (surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED)
1264             isl_msaa_interleaved_scale_px_to_sa(surf->samples, NULL, &H);
1265
1266          y += isl_align_npot(H, image_align_sa.h);
1267       }
1268    }
1269
1270    *x_offset_sa = x;
1271    *y_offset_sa = y;
1272 }
1273
1274 /**
1275  * A variant of isl_surf_get_image_offset_sa() specific to
1276  * ISL_DIM_LAYOUT_GEN4_3D.
1277  */
1278 static void
1279 get_image_offset_sa_gen4_3d(const struct isl_surf *surf,
1280                             uint32_t level, uint32_t logical_z_offset_px,
1281                             uint32_t *x_offset_sa,
1282                             uint32_t *y_offset_sa)
1283 {
1284    assert(level < surf->levels);
1285    assert(logical_z_offset_px < isl_minify(surf->phys_level0_sa.depth, level));
1286    assert(surf->phys_level0_sa.array_len == 1);
1287
1288    const struct isl_extent3d image_align_sa =
1289       isl_surf_get_image_alignment_sa(surf);
1290
1291    const uint32_t W0 = surf->phys_level0_sa.width;
1292    const uint32_t H0 = surf->phys_level0_sa.height;
1293    const uint32_t D0 = surf->phys_level0_sa.depth;
1294
1295    uint32_t x = 0;
1296    uint32_t y = 0;
1297
1298    for (uint32_t l = 0; l < level; ++l) {
1299       const uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa.h);
1300       const uint32_t level_d = isl_align_npot(isl_minify(D0, l), image_align_sa.d);
1301       const uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l);
1302
1303       y += level_h * max_layers_vert;
1304    }
1305
1306    const uint32_t level_w = isl_align_npot(isl_minify(W0, level), image_align_sa.w);
1307    const uint32_t level_h = isl_align_npot(isl_minify(H0, level), image_align_sa.h);
1308    const uint32_t level_d = isl_align_npot(isl_minify(D0, level), image_align_sa.d);
1309
1310    const uint32_t max_layers_horiz = MIN(level_d, 1u << level);
1311
1312    x += level_w * (logical_z_offset_px % max_layers_horiz);
1313    y += level_h * (logical_z_offset_px / max_layers_horiz);
1314
1315    *x_offset_sa = x;
1316    *y_offset_sa = y;
1317 }
1318
1319 /**
1320  * A variant of isl_surf_get_image_offset_sa() specific to
1321  * ISL_DIM_LAYOUT_GEN9_1D.
1322  */
1323 static void
1324 get_image_offset_sa_gen9_1d(const struct isl_surf *surf,
1325                             uint32_t level, uint32_t layer,
1326                             uint32_t *x_offset_sa,
1327                             uint32_t *y_offset_sa)
1328 {
1329    assert(level < surf->levels);
1330    assert(layer < surf->phys_level0_sa.array_len);
1331    assert(surf->phys_level0_sa.height == 1);
1332    assert(surf->phys_level0_sa.depth == 1);
1333    assert(surf->samples == 1);
1334
1335    const uint32_t W0 = surf->phys_level0_sa.width;
1336    const struct isl_extent3d image_align_sa =
1337       isl_surf_get_image_alignment_sa(surf);
1338
1339    uint32_t x = 0;
1340
1341    for (uint32_t l = 0; l < level; ++l) {
1342       uint32_t W = isl_minify(W0, l);
1343       uint32_t w = isl_align_npot(W, image_align_sa.w);
1344
1345       x += w;
1346    }
1347
1348    *x_offset_sa = x;
1349    *y_offset_sa = layer * isl_surf_get_array_pitch_sa_rows(surf);
1350 }
1351
1352 /**
1353  * Calculate the offset, in units of surface samples, to a subimage in the
1354  * surface.
1355  *
1356  * @invariant level < surface levels
1357  * @invariant logical_array_layer < logical array length of surface
1358  * @invariant logical_z_offset_px < logical depth of surface at level
1359  */
1360 static void
1361 get_image_offset_sa(const struct isl_surf *surf,
1362                     uint32_t level,
1363                     uint32_t logical_array_layer,
1364                     uint32_t logical_z_offset_px,
1365                     uint32_t *x_offset_sa,
1366                     uint32_t *y_offset_sa)
1367 {
1368    assert(level < surf->levels);
1369    assert(logical_array_layer < surf->logical_level0_px.array_len);
1370    assert(logical_z_offset_px
1371           < isl_minify(surf->logical_level0_px.depth, level));
1372
1373    switch (surf->dim_layout) {
1374    case ISL_DIM_LAYOUT_GEN9_1D:
1375       get_image_offset_sa_gen9_1d(surf, level, logical_array_layer,
1376                                   x_offset_sa, y_offset_sa);
1377       break;
1378    case ISL_DIM_LAYOUT_GEN4_2D:
1379       get_image_offset_sa_gen4_2d(surf, level, logical_array_layer
1380                                   + logical_z_offset_px,
1381                                   x_offset_sa, y_offset_sa);
1382       break;
1383    case ISL_DIM_LAYOUT_GEN4_3D:
1384       get_image_offset_sa_gen4_3d(surf, level, logical_z_offset_px,
1385                                   x_offset_sa, y_offset_sa);
1386       break;
1387    }
1388 }
1389
1390 void
1391 isl_surf_get_image_offset_el(const struct isl_surf *surf,
1392                              uint32_t level,
1393                              uint32_t logical_array_layer,
1394                              uint32_t logical_z_offset_px,
1395                              uint32_t *x_offset_el,
1396                              uint32_t *y_offset_el)
1397 {
1398    const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
1399
1400    assert(level < surf->levels);
1401    assert(logical_array_layer < surf->logical_level0_px.array_len);
1402    assert(logical_z_offset_px
1403           < isl_minify(surf->logical_level0_px.depth, level));
1404
1405    uint32_t x_offset_sa, y_offset_sa;
1406    get_image_offset_sa(surf, level,
1407                        logical_array_layer,
1408                        logical_z_offset_px,
1409                        &x_offset_sa,
1410                        &y_offset_sa);
1411
1412    *x_offset_el = x_offset_sa / fmtl->bw;
1413    *y_offset_el = y_offset_sa / fmtl->bh;
1414 }
1415
1416 void
1417 isl_surf_get_image_intratile_offset_el_xy(const struct isl_device *dev,
1418                                        const struct isl_surf *surf,
1419                                        uint32_t total_x_offset_el,
1420                                        uint32_t total_y_offset_el,
1421                                        uint32_t *base_address_offset,
1422                                        uint32_t *x_offset_el,
1423                                        uint32_t *y_offset_el)
1424 {
1425    const struct isl_format_layout *fmtl = isl_format_get_layout(surf->format);
1426
1427    struct isl_tile_info tile_info;
1428    isl_surf_get_tile_info(dev, surf, &tile_info);
1429
1430    uint32_t small_y_offset_el = total_y_offset_el % tile_info.height;
1431    uint32_t big_y_offset_el = total_y_offset_el - small_y_offset_el;
1432    uint32_t big_y_offset_B = big_y_offset_el * surf->row_pitch;
1433
1434    uint32_t total_x_offset_B = total_x_offset_el * fmtl->bs;
1435    uint32_t small_x_offset_B = total_x_offset_B % tile_info.width;
1436    uint32_t small_x_offset_el = small_x_offset_B / fmtl->bs;
1437    uint32_t big_x_offset_B = (total_x_offset_B / tile_info.width) * tile_info.size;
1438
1439    *base_address_offset = big_y_offset_B + big_x_offset_B;
1440    *x_offset_el = small_x_offset_el;
1441    *y_offset_el = small_y_offset_el;
1442
1443
1444 }
1445
1446 void
1447 isl_surf_get_image_intratile_offset_el(const struct isl_device *dev,
1448                                        const struct isl_surf *surf,
1449                                        uint32_t level,
1450                                        uint32_t logical_array_layer,
1451                                        uint32_t logical_z_offset,
1452                                        uint32_t *base_address_offset,
1453                                        uint32_t *x_offset_el,
1454                                        uint32_t *y_offset_el)
1455 {
1456    uint32_t total_x_offset_el;
1457    uint32_t total_y_offset_el;
1458    isl_surf_get_image_offset_el(surf, level,
1459                                 logical_array_layer,
1460                                 logical_z_offset,
1461                                 &total_x_offset_el,
1462                                 &total_y_offset_el);
1463
1464    isl_surf_get_image_intratile_offset_el_xy(dev, surf,
1465                                 total_x_offset_el,
1466                                 total_y_offset_el,
1467                                 base_address_offset,
1468                                 x_offset_el,
1469                                 y_offset_el);
1470 }
1471
1472 uint32_t
1473 isl_surf_get_depth_format(const struct isl_device *dev,
1474                           const struct isl_surf *surf)
1475 {
1476    /* Support for separate stencil buffers began in gen5. Support for
1477     * interleaved depthstencil buffers ceased in gen7. The intermediate gens,
1478     * those that supported separate and interleaved stencil, were gen5 and
1479     * gen6.
1480     *
1481     * For a list of all available formats, see the Sandybridge PRM >> Volume
1482     * 2 Part 1: 3D/Media - 3D Pipeline >> 3DSTATE_DEPTH_BUFFER >> Surface
1483     * Format (p321).
1484     */
1485
1486    bool has_stencil = surf->usage & ISL_SURF_USAGE_STENCIL_BIT;
1487
1488    assert(surf->usage & ISL_SURF_USAGE_DEPTH_BIT);
1489
1490    if (has_stencil)
1491       assert(ISL_DEV_GEN(dev) < 7);
1492
1493    switch (surf->format) {
1494    default:
1495       unreachable("bad isl depth format");
1496    case ISL_FORMAT_R32_FLOAT_X8X24_TYPELESS:
1497       assert(ISL_DEV_GEN(dev) < 7);
1498       return 0; /* D32_FLOAT_S8X24_UINT */
1499    case ISL_FORMAT_R32_FLOAT:
1500       assert(!has_stencil);
1501       return 1; /* D32_FLOAT */
1502    case ISL_FORMAT_R24_UNORM_X8_TYPELESS:
1503       if (has_stencil) {
1504          assert(ISL_DEV_GEN(dev) < 7);
1505          return 2; /* D24_UNORM_S8_UINT */
1506       } else {
1507          assert(ISL_DEV_GEN(dev) >= 5);
1508          return 3; /* D24_UNORM_X8_UINT */
1509       }
1510    case ISL_FORMAT_R16_UNORM:
1511       assert(!has_stencil);
1512       return 5; /* D16_UNORM */
1513    }
1514 }