2 * Copyright 2015 Intel Corporation
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:
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
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
36 void PRINTFLIKE(3, 4) UNUSED
37 __isl_finishme(const char *file
, int line
, const char *fmt
, ...)
43 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
46 fprintf(stderr
, "%s:%d: FINISHME: %s\n", file
, line
, buf
);
50 isl_device_init(struct isl_device
*dev
,
51 const struct brw_device_info
*info
,
52 bool has_bit6_swizzling
)
55 dev
->use_separate_stencil
= ISL_DEV_GEN(dev
) >= 6;
56 dev
->has_bit6_swizzling
= has_bit6_swizzling
;
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.
62 assert(ISL_DEV_GEN(dev
) == dev
->info
->gen
);
63 assert(ISL_DEV_USE_SEPARATE_STENCIL(dev
) == dev
->use_separate_stencil
);
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
));
73 * @brief Query the set of multisamples supported by the device.
75 * This function always returns non-zero, as ISL_SAMPLE_COUNT_1_BIT is always
78 isl_sample_count_mask_t ATTRIBUTE_CONST
79 isl_device_get_sample_counts(struct isl_device
*dev
)
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
;
100 return ISL_SAMPLE_COUNT_1_BIT
;
105 * @param[out] info is written only on success
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
)
113 const uint32_t bs
= format_block_size
;
114 uint32_t width
, height
;
119 case ISL_TILING_LINEAR
:
135 /* XXX: Should W tile be same as Y? */
141 case ISL_TILING_Ys
: {
142 if (ISL_DEV_GEN(dev
) < 9)
145 if (!isl_is_pow2(bs
))
148 bool is_Ys
= tiling
== ISL_TILING_Ys
;
150 width
= 1 << (6 + (ffs(bs
) / 2) + (2 * is_Ys
));
151 height
= 1 << (6 - (ffs(bs
) / 2) + (2 * is_Ys
));
156 unreachable("not reached");
159 *tile_info
= (struct isl_tile_info
) {
163 .size
= width
* height
,
170 isl_tiling_get_extent(const struct isl_device
*dev
,
171 enum isl_tiling tiling
,
172 uint32_t format_block_size
,
173 struct isl_extent2d
*e
)
175 struct isl_tile_info tile_info
;
176 isl_tiling_get_info(dev
, tiling
, format_block_size
, &tile_info
);
177 *e
= isl_extent2d(tile_info
.width
, tile_info
.height
);
181 * @param[out] tiling is set only on success
184 isl_surf_choose_tiling(const struct isl_device
*dev
,
185 const struct isl_surf_init_info
*restrict info
,
186 enum isl_tiling
*tiling
)
188 isl_tiling_flags_t tiling_flags
= info
->tiling_flags
;
190 /* Filter if multiple tiling options are given */
191 if (!isl_is_pow2(tiling_flags
)) {
192 if (ISL_DEV_GEN(dev
) >= 7) {
193 gen7_filter_tiling(dev
, info
, &tiling_flags
);
195 isl_finishme("%s: gen%u", __func__
, ISL_DEV_GEN(dev
));
196 gen7_filter_tiling(dev
, info
, &tiling_flags
);
200 #define CHOOSE(__tiling) \
202 if (tiling_flags & (1u << (__tiling))) { \
203 *tiling = (__tiling); \
208 /* Of the tiling modes remaining, choose the one that offers the best
212 if (info
->dim
== ISL_SURF_DIM_1D
) {
213 /* Prefer linear for 1D surfaces because they do not benefit from
214 * tiling. To the contrary, tiling leads to wasted memory and poor
215 * memory locality due to the swizzling and alignment restrictions
216 * required in tiled surfaces.
218 CHOOSE(ISL_TILING_LINEAR
);
221 CHOOSE(ISL_TILING_Ys
);
222 CHOOSE(ISL_TILING_Yf
);
223 CHOOSE(ISL_TILING_Y0
);
224 CHOOSE(ISL_TILING_X
);
225 CHOOSE(ISL_TILING_W
);
226 CHOOSE(ISL_TILING_LINEAR
);
230 /* No tiling mode accomodates the inputs. */
235 isl_choose_msaa_layout(const struct isl_device
*dev
,
236 const struct isl_surf_init_info
*info
,
237 enum isl_tiling tiling
,
238 enum isl_msaa_layout
*msaa_layout
)
240 if (ISL_DEV_GEN(dev
) >= 8) {
241 return gen8_choose_msaa_layout(dev
, info
, tiling
, msaa_layout
);
242 } else if (ISL_DEV_GEN(dev
) >= 7) {
243 return gen7_choose_msaa_layout(dev
, info
, tiling
, msaa_layout
);
244 } else if (ISL_DEV_GEN(dev
) >= 6) {
245 return gen6_choose_msaa_layout(dev
, info
, tiling
, msaa_layout
);
247 return gen4_choose_msaa_layout(dev
, info
, tiling
, msaa_layout
);
252 isl_msaa_interleaved_scale_px_to_sa(uint32_t samples
,
253 uint32_t *width
, uint32_t *height
)
255 assert(isl_is_pow2(samples
));
257 /* From the Broadwell PRM >> Volume 5: Memory Views >> Computing Mip Level
260 * If the surface is multisampled and it is a depth or stencil surface
261 * or Multisampled Surface StorageFormat in SURFACE_STATE is
262 * MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows before
266 *width
= isl_align(*width
, 2) << ((ffs(samples
) - 0) / 2);
268 *height
= isl_align(*height
, 2) << ((ffs(samples
) - 1) / 2);
271 static enum isl_array_pitch_span
272 isl_choose_array_pitch_span(const struct isl_device
*dev
,
273 const struct isl_surf_init_info
*restrict info
,
274 enum isl_dim_layout dim_layout
,
275 const struct isl_extent4d
*phys_level0_sa
)
277 switch (dim_layout
) {
278 case ISL_DIM_LAYOUT_GEN9_1D
:
279 case ISL_DIM_LAYOUT_GEN4_2D
:
280 if (ISL_DEV_GEN(dev
) >= 8) {
281 /* QPitch becomes programmable in Broadwell. So choose the
282 * most compact QPitch possible in order to conserve memory.
284 * From the Broadwell PRM >> Volume 2d: Command Reference: Structures
285 * >> RENDER_SURFACE_STATE Surface QPitch (p325):
287 * - Software must ensure that this field is set to a value
288 * sufficiently large such that the array slices in the surface
289 * do not overlap. Refer to the Memory Data Formats section for
290 * information on how surfaces are stored in memory.
292 * - This field specifies the distance in rows between array
293 * slices. It is used only in the following cases:
295 * - Surface Array is enabled OR
296 * - Number of Mulitsamples is not NUMSAMPLES_1 and
297 * Multisampled Surface Storage Format set to MSFMT_MSS OR
298 * - Surface Type is SURFTYPE_CUBE
300 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
301 } else if (ISL_DEV_GEN(dev
) >= 7) {
302 /* Note that Ivybridge introduces
303 * RENDER_SURFACE_STATE.SurfaceArraySpacing, which provides the
304 * driver more control over the QPitch.
307 if (phys_level0_sa
->array_len
== 1) {
308 /* The hardware will never use the QPitch. So choose the most
309 * compact QPitch possible in order to conserve memory.
311 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
314 if (isl_surf_usage_is_depth_or_stencil(info
->usage
)) {
315 /* From the Ivybridge PRM >> Volume 1 Part 1: Graphics Core >>
316 * Section 6.18.4.7: Surface Arrays (p112):
318 * If Surface Array Spacing is set to ARYSPC_FULL (note that
319 * the depth buffer and stencil buffer have an implied value of
322 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
325 if (info
->levels
== 1) {
326 /* We are able to set RENDER_SURFACE_STATE.SurfaceArraySpacing
329 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
332 return ISL_ARRAY_PITCH_SPAN_FULL
;
333 } else if ((ISL_DEV_GEN(dev
) == 5 || ISL_DEV_GEN(dev
) == 6) &&
334 ISL_DEV_USE_SEPARATE_STENCIL(dev
) &&
335 isl_surf_usage_is_stencil(info
->usage
)) {
336 /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1:
337 * Graphics Core >> Section 7.18.3.7: Surface Arrays:
339 * The separate stencil buffer does not support mip mapping, thus
340 * the storage for LODs other than LOD 0 is not needed.
342 assert(info
->levels
== 1);
343 assert(phys_level0_sa
->array_len
== 1);
344 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
346 if ((ISL_DEV_GEN(dev
) == 5 || ISL_DEV_GEN(dev
) == 6) &&
347 ISL_DEV_USE_SEPARATE_STENCIL(dev
) &&
348 isl_surf_usage_is_stencil(info
->usage
)) {
349 /* [ILK-SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1:
350 * Graphics Core >> Section 7.18.3.7: Surface Arrays:
352 * The separate stencil buffer does not support mip mapping,
353 * thus the storage for LODs other than LOD 0 is not needed.
355 assert(info
->levels
== 1);
356 assert(phys_level0_sa
->array_len
== 1);
357 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
360 if (phys_level0_sa
->array_len
== 1) {
361 /* The hardware will never use the QPitch. So choose the most
362 * compact QPitch possible in order to conserve memory.
364 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
367 return ISL_ARRAY_PITCH_SPAN_FULL
;
370 case ISL_DIM_LAYOUT_GEN4_3D
:
371 /* The hardware will never use the QPitch. So choose the most
372 * compact QPitch possible in order to conserve memory.
374 return ISL_ARRAY_PITCH_SPAN_COMPACT
;
377 unreachable("bad isl_dim_layout");
378 return ISL_ARRAY_PITCH_SPAN_FULL
;
382 isl_choose_image_alignment_el(const struct isl_device
*dev
,
383 const struct isl_surf_init_info
*restrict info
,
384 enum isl_tiling tiling
,
385 enum isl_msaa_layout msaa_layout
,
386 struct isl_extent3d
*image_align_el
)
388 if (ISL_DEV_GEN(dev
) >= 9) {
389 gen9_choose_image_alignment_el(dev
, info
, tiling
, msaa_layout
,
391 } else if (ISL_DEV_GEN(dev
) >= 8) {
392 gen8_choose_image_alignment_el(dev
, info
, tiling
, msaa_layout
,
394 } else if (ISL_DEV_GEN(dev
) >= 7) {
395 gen7_choose_image_alignment_el(dev
, info
, tiling
, msaa_layout
,
397 } else if (ISL_DEV_GEN(dev
) >= 6) {
398 gen6_choose_image_alignment_el(dev
, info
, tiling
, msaa_layout
,
401 gen4_choose_image_alignment_el(dev
, info
, tiling
, msaa_layout
,
406 static enum isl_dim_layout
407 isl_surf_choose_dim_layout(const struct isl_device
*dev
,
408 enum isl_surf_dim logical_dim
)
410 if (ISL_DEV_GEN(dev
) >= 9) {
411 switch (logical_dim
) {
412 case ISL_SURF_DIM_1D
:
413 return ISL_DIM_LAYOUT_GEN9_1D
;
414 case ISL_SURF_DIM_2D
:
415 case ISL_SURF_DIM_3D
:
416 return ISL_DIM_LAYOUT_GEN4_2D
;
419 switch (logical_dim
) {
420 case ISL_SURF_DIM_1D
:
421 case ISL_SURF_DIM_2D
:
422 return ISL_DIM_LAYOUT_GEN4_2D
;
423 case ISL_SURF_DIM_3D
:
424 return ISL_DIM_LAYOUT_GEN4_3D
;
428 unreachable("bad isl_surf_dim");
429 return ISL_DIM_LAYOUT_GEN4_2D
;
433 * Calculate the physical extent of the surface's first level, in units of
434 * surface samples. The result is aligned to the format's compression block.
437 isl_calc_phys_level0_extent_sa(const struct isl_device
*dev
,
438 const struct isl_surf_init_info
*restrict info
,
439 enum isl_dim_layout dim_layout
,
440 enum isl_tiling tiling
,
441 enum isl_msaa_layout msaa_layout
,
442 struct isl_extent4d
*phys_level0_sa
)
444 const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
446 if (isl_format_is_yuv(info
->format
))
447 isl_finishme("%s:%s: YUV format", __FILE__
, __func__
);
450 case ISL_SURF_DIM_1D
:
451 assert(info
->height
== 1);
452 assert(info
->depth
== 1);
453 assert(info
->samples
== 1);
454 assert(!isl_format_is_compressed(info
->format
));
456 switch (dim_layout
) {
457 case ISL_DIM_LAYOUT_GEN4_3D
:
458 unreachable("bad isl_dim_layout");
460 case ISL_DIM_LAYOUT_GEN9_1D
:
461 case ISL_DIM_LAYOUT_GEN4_2D
:
462 *phys_level0_sa
= (struct isl_extent4d
) {
466 .a
= info
->array_len
,
472 case ISL_SURF_DIM_2D
:
473 assert(dim_layout
== ISL_DIM_LAYOUT_GEN4_2D
);
475 if (tiling
== ISL_TILING_Ys
&& info
->samples
> 1)
476 isl_finishme("%s:%s: multisample TileYs layout", __FILE__
, __func__
);
478 switch (msaa_layout
) {
479 case ISL_MSAA_LAYOUT_NONE
:
480 assert(info
->depth
== 1);
481 assert(info
->samples
== 1);
483 *phys_level0_sa
= (struct isl_extent4d
) {
484 .w
= isl_align(info
->width
, fmtl
->bw
),
485 .h
= isl_align(info
->height
, fmtl
->bh
),
487 .a
= info
->array_len
,
491 case ISL_MSAA_LAYOUT_ARRAY
:
492 assert(info
->depth
== 1);
493 assert(info
->array_len
== 1);
494 assert(!isl_format_is_compressed(info
->format
));
496 *phys_level0_sa
= (struct isl_extent4d
) {
504 case ISL_MSAA_LAYOUT_INTERLEAVED
:
505 assert(info
->depth
== 1);
506 assert(info
->array_len
== 1);
507 assert(!isl_format_is_compressed(info
->format
));
509 *phys_level0_sa
= (struct isl_extent4d
) {
516 isl_msaa_interleaved_scale_px_to_sa(info
->samples
,
523 case ISL_SURF_DIM_3D
:
524 assert(info
->array_len
== 1);
525 assert(info
->samples
== 1);
528 isl_finishme("%s:%s: compression block with depth > 1",
532 switch (dim_layout
) {
533 case ISL_DIM_LAYOUT_GEN9_1D
:
534 unreachable("bad isl_dim_layout");
536 case ISL_DIM_LAYOUT_GEN4_2D
:
537 assert(ISL_DEV_GEN(dev
) >= 9);
539 *phys_level0_sa
= (struct isl_extent4d
) {
540 .w
= isl_align(info
->width
, fmtl
->bw
),
541 .h
= isl_align(info
->height
, fmtl
->bh
),
547 case ISL_DIM_LAYOUT_GEN4_3D
:
548 assert(ISL_DEV_GEN(dev
) < 9);
549 *phys_level0_sa
= (struct isl_extent4d
) {
550 .w
= isl_align(info
->width
, fmtl
->bw
),
551 .h
= isl_align(info
->height
, fmtl
->bh
),
562 * A variant of isl_calc_phys_slice0_extent_sa() specific to
563 * ISL_DIM_LAYOUT_GEN4_2D.
566 isl_calc_phys_slice0_extent_sa_gen4_2d(
567 const struct isl_device
*dev
,
568 const struct isl_surf_init_info
*restrict info
,
569 enum isl_msaa_layout msaa_layout
,
570 const struct isl_extent3d
*image_align_sa
,
571 const struct isl_extent4d
*phys_level0_sa
,
572 struct isl_extent2d
*phys_slice0_sa
)
574 const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
576 assert(phys_level0_sa
->depth
== 1);
578 if (info
->levels
== 1 && msaa_layout
!= ISL_MSAA_LAYOUT_INTERLEAVED
) {
579 /* Do not pad the surface to the image alignment. Instead, pad it only
580 * to the pixel format's block alignment.
582 * For tiled surfaces, using a reduced alignment here avoids wasting CPU
583 * cycles on the below mipmap layout caluclations. Reducing the
584 * alignment here is safe because we later align the row pitch and array
585 * pitch to the tile boundary. It is safe even for
586 * ISL_MSAA_LAYOUT_INTERLEAVED, because phys_level0_sa is already scaled
587 * to accomodate the interleaved samples.
589 * For linear surfaces, reducing the alignment here permits us to later
590 * choose an arbitrary, non-aligned row pitch. If the surface backs
591 * a VkBuffer, then an arbitrary pitch may be needed to accomodate
592 * VkBufferImageCopy::bufferRowLength.
594 *phys_slice0_sa
= (struct isl_extent2d
) {
595 .w
= isl_align_npot(phys_level0_sa
->w
, fmtl
->bw
),
596 .h
= isl_align_npot(phys_level0_sa
->h
, fmtl
->bh
),
601 uint32_t slice_top_w
= 0;
602 uint32_t slice_bottom_w
= 0;
603 uint32_t slice_left_h
= 0;
604 uint32_t slice_right_h
= 0;
606 uint32_t W0
= phys_level0_sa
->w
;
607 uint32_t H0
= phys_level0_sa
->h
;
609 for (uint32_t l
= 0; l
< info
->levels
; ++l
) {
610 uint32_t W
= isl_minify(W0
, l
);
611 uint32_t H
= isl_minify(H0
, l
);
613 if (msaa_layout
== ISL_MSAA_LAYOUT_INTERLEAVED
) {
614 /* From the Broadwell PRM >> Volume 5: Memory Views >> Computing Mip Level
617 * If the surface is multisampled and it is a depth or stencil
618 * surface or Multisampled Surface StorageFormat in
619 * SURFACE_STATE is MSFMT_DEPTH_STENCIL, W_L and H_L must be
620 * adjusted as follows before proceeding: [...]
622 isl_msaa_interleaved_scale_px_to_sa(info
->samples
, &W
, &H
);
625 uint32_t w
= isl_align_npot(W
, image_align_sa
->w
);
626 uint32_t h
= isl_align_npot(H
, image_align_sa
->h
);
643 *phys_slice0_sa
= (struct isl_extent2d
) {
644 .w
= MAX(slice_top_w
, slice_bottom_w
),
645 .h
= MAX(slice_left_h
, slice_right_h
),
650 * A variant of isl_calc_phys_slice0_extent_sa() specific to
651 * ISL_DIM_LAYOUT_GEN4_3D.
654 isl_calc_phys_slice0_extent_sa_gen4_3d(
655 const struct isl_device
*dev
,
656 const struct isl_surf_init_info
*restrict info
,
657 const struct isl_extent3d
*image_align_sa
,
658 const struct isl_extent4d
*phys_level0_sa
,
659 struct isl_extent2d
*phys_slice0_sa
)
661 assert(info
->samples
== 1);
662 assert(phys_level0_sa
->array_len
== 1);
664 uint32_t slice_w
= 0;
665 uint32_t slice_h
= 0;
667 uint32_t W0
= phys_level0_sa
->w
;
668 uint32_t H0
= phys_level0_sa
->h
;
669 uint32_t D0
= phys_level0_sa
->d
;
671 for (uint32_t l
= 0; l
< info
->levels
; ++l
) {
672 uint32_t level_w
= isl_align_npot(isl_minify(W0
, l
), image_align_sa
->w
);
673 uint32_t level_h
= isl_align_npot(isl_minify(H0
, l
), image_align_sa
->h
);
674 uint32_t level_d
= isl_align_npot(isl_minify(D0
, l
), image_align_sa
->d
);
676 uint32_t max_layers_horiz
= MIN(level_d
, 1u << l
);
677 uint32_t max_layers_vert
= isl_align(level_d
, 1u << l
) / (1u << l
);
679 slice_w
= MAX(slice_w
, level_w
* max_layers_horiz
);
680 slice_h
+= level_h
* max_layers_vert
;
683 *phys_slice0_sa
= (struct isl_extent2d
) {
690 * A variant of isl_calc_phys_slice0_extent_sa() specific to
691 * ISL_DIM_LAYOUT_GEN9_1D.
694 isl_calc_phys_slice0_extent_sa_gen9_1d(
695 const struct isl_device
*dev
,
696 const struct isl_surf_init_info
*restrict info
,
697 const struct isl_extent3d
*image_align_sa
,
698 const struct isl_extent4d
*phys_level0_sa
,
699 struct isl_extent2d
*phys_slice0_sa
)
701 MAYBE_UNUSED
const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
703 assert(phys_level0_sa
->height
== 1);
704 assert(phys_level0_sa
->depth
== 1);
705 assert(info
->samples
== 1);
706 assert(image_align_sa
->w
>= fmtl
->bw
);
708 uint32_t slice_w
= 0;
709 const uint32_t W0
= phys_level0_sa
->w
;
711 for (uint32_t l
= 0; l
< info
->levels
; ++l
) {
712 uint32_t W
= isl_minify(W0
, l
);
713 uint32_t w
= isl_align_npot(W
, image_align_sa
->w
);
718 *phys_slice0_sa
= isl_extent2d(slice_w
, 1);
722 * Calculate the physical extent of the surface's first array slice, in units
723 * of surface samples. If the surface is multi-leveled, then the result will
724 * be aligned to \a image_align_sa.
727 isl_calc_phys_slice0_extent_sa(const struct isl_device
*dev
,
728 const struct isl_surf_init_info
*restrict info
,
729 enum isl_dim_layout dim_layout
,
730 enum isl_msaa_layout msaa_layout
,
731 const struct isl_extent3d
*image_align_sa
,
732 const struct isl_extent4d
*phys_level0_sa
,
733 struct isl_extent2d
*phys_slice0_sa
)
735 switch (dim_layout
) {
736 case ISL_DIM_LAYOUT_GEN9_1D
:
737 isl_calc_phys_slice0_extent_sa_gen9_1d(dev
, info
,
738 image_align_sa
, phys_level0_sa
,
741 case ISL_DIM_LAYOUT_GEN4_2D
:
742 isl_calc_phys_slice0_extent_sa_gen4_2d(dev
, info
, msaa_layout
,
743 image_align_sa
, phys_level0_sa
,
746 case ISL_DIM_LAYOUT_GEN4_3D
:
747 isl_calc_phys_slice0_extent_sa_gen4_3d(dev
, info
, image_align_sa
,
748 phys_level0_sa
, phys_slice0_sa
);
754 * Calculate the pitch between physical array slices, in units of rows of
758 isl_calc_array_pitch_el_rows(const struct isl_device
*dev
,
759 const struct isl_surf_init_info
*restrict info
,
760 const struct isl_tile_info
*tile_info
,
761 enum isl_dim_layout dim_layout
,
762 enum isl_array_pitch_span array_pitch_span
,
763 const struct isl_extent3d
*image_align_sa
,
764 const struct isl_extent4d
*phys_level0_sa
,
765 const struct isl_extent2d
*phys_slice0_sa
)
767 const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
768 uint32_t pitch_sa_rows
= 0;
770 switch (dim_layout
) {
771 case ISL_DIM_LAYOUT_GEN9_1D
:
772 /* Each row is an array slice */
775 case ISL_DIM_LAYOUT_GEN4_2D
:
776 switch (array_pitch_span
) {
777 case ISL_ARRAY_PITCH_SPAN_COMPACT
:
778 pitch_sa_rows
= isl_align_npot(phys_slice0_sa
->h
, image_align_sa
->h
);
780 case ISL_ARRAY_PITCH_SPAN_FULL
: {
781 /* The QPitch equation is found in the Broadwell PRM >> Volume 5:
782 * Memory Views >> Common Surface Formats >> Surface Layout >> 2D
783 * Surfaces >> Surface Arrays.
785 uint32_t H0_sa
= phys_level0_sa
->h
;
786 uint32_t H1_sa
= isl_minify(H0_sa
, 1);
788 uint32_t h0_sa
= isl_align_npot(H0_sa
, image_align_sa
->h
);
789 uint32_t h1_sa
= isl_align_npot(H1_sa
, image_align_sa
->h
);
792 if (ISL_DEV_GEN(dev
) >= 7) {
793 /* The QPitch equation changed slightly in Ivybridge. */
799 pitch_sa_rows
= h0_sa
+ h1_sa
+ (m
* image_align_sa
->h
);
801 if (ISL_DEV_GEN(dev
) == 6 && info
->samples
> 1 &&
802 (info
->height
% 4 == 1)) {
803 /* [SNB] Errata from the Sandy Bridge PRM >> Volume 4 Part 1:
804 * Graphics Core >> Section 7.18.3.7: Surface Arrays:
806 * [SNB] Errata: Sampler MSAA Qpitch will be 4 greater than
807 * the value calculated in the equation above , for every
808 * other odd Surface Height starting from 1 i.e. 1,5,9,13.
810 * XXX(chadv): Is the errata natural corollary of the physical
811 * layout of interleaved samples?
816 pitch_sa_rows
= isl_align_npot(pitch_sa_rows
, fmtl
->bh
);
821 case ISL_DIM_LAYOUT_GEN4_3D
:
822 assert(array_pitch_span
== ISL_ARRAY_PITCH_SPAN_COMPACT
);
823 pitch_sa_rows
= isl_align_npot(phys_slice0_sa
->h
, image_align_sa
->h
);
826 unreachable("bad isl_dim_layout");
830 assert(pitch_sa_rows
% fmtl
->bh
== 0);
831 uint32_t pitch_el_rows
= pitch_sa_rows
/ fmtl
->bh
;
833 if (ISL_DEV_GEN(dev
) >= 9 &&
834 info
->dim
== ISL_SURF_DIM_3D
&&
835 tile_info
->tiling
!= ISL_TILING_LINEAR
) {
836 /* From the Skylake BSpec >> RENDER_SURFACE_STATE >> Surface QPitch:
838 * Tile Mode != Linear: This field must be set to an integer multiple
841 pitch_el_rows
= isl_align(pitch_el_rows
, tile_info
->height
);
844 return pitch_el_rows
;
848 * Calculate the pitch of each surface row, in bytes.
851 isl_calc_row_pitch(const struct isl_device
*dev
,
852 const struct isl_surf_init_info
*restrict info
,
853 const struct isl_tile_info
*tile_info
,
854 const struct isl_extent3d
*image_align_sa
,
855 const struct isl_extent2d
*phys_slice0_sa
)
857 const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
859 uint32_t row_pitch
= info
->min_pitch
;
861 /* First, align the surface to a cache line boundary, as the PRM explains
864 * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
865 * Formats >> Surface Padding Requirements >> Render Target and Media
868 * The data port accesses data (pixels) outside of the surface if they
869 * are contained in the same cache request as pixels that are within the
870 * surface. These pixels will not be returned by the requesting message,
871 * however if these pixels lie outside of defined pages in the GTT,
872 * a GTT error will result when the cache request is processed. In order
873 * to avoid these GTT errors, “padding” at the bottom of the surface is
874 * sometimes necessary.
876 * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
877 * Formats >> Surface Padding Requirements >> Sampling Engine Surfaces:
879 * The sampling engine accesses texels outside of the surface if they
880 * are contained in the same cache line as texels that are within the
881 * surface. These texels will not participate in any calculation
882 * performed by the sampling engine and will not affect the result of
883 * any sampling engine operation, however if these texels lie outside of
884 * defined pages in the GTT, a GTT error will result when the cache line
885 * is accessed. In order to avoid these GTT errors, “padding” at the
886 * bottom and right side of a sampling engine surface is sometimes
889 * It is possible that a cache line will straddle a page boundary if the
890 * base address or pitch is not aligned. All pages included in the cache
891 * lines that are part of the surface must map to valid GTT entries to
892 * avoid errors. To determine the necessary padding on the bottom and
893 * right side of the surface, refer to the table in Alignment Unit Size
894 * section for the i and j parameters for the surface format in use. The
895 * surface must then be extended to the next multiple of the alignment
896 * unit size in each dimension, and all texels contained in this
897 * extended surface must have valid GTT entries.
899 * For example, suppose the surface size is 15 texels by 10 texels and
900 * the alignment parameters are i=4 and j=2. In this case, the extended
901 * surface would be 16 by 10. Note that these calculations are done in
902 * texels, and must be converted to bytes based on the surface format
903 * being used to determine whether additional pages need to be defined.
905 assert(phys_slice0_sa
->w
% fmtl
->bw
== 0);
906 row_pitch
= MAX(row_pitch
, fmtl
->bs
* (phys_slice0_sa
->w
/ fmtl
->bw
));
908 switch (tile_info
->tiling
) {
909 case ISL_TILING_LINEAR
:
910 /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >>
911 * RENDER_SURFACE_STATE Surface Pitch (p349):
913 * - For linear render target surfaces and surfaces accessed with the
914 * typed data port messages, the pitch must be a multiple of the
915 * element size for non-YUV surface formats. Pitch must be
916 * a multiple of 2 * element size for YUV surface formats.
918 * - [Requirements for SURFTYPE_BUFFER and SURFTYPE_STRBUF, which we
919 * ignore because isl doesn't do buffers.]
921 * - For other linear surfaces, the pitch can be any multiple of
924 if (info
->usage
& ISL_SURF_USAGE_RENDER_TARGET_BIT
) {
925 if (isl_format_is_yuv(info
->format
)) {
926 row_pitch
= isl_align_npot(row_pitch
, 2 * fmtl
->bs
);
928 row_pitch
= isl_align_npot(row_pitch
, fmtl
->bs
);
933 /* From the Broadwel PRM >> Volume 2d: Command Reference: Structures >>
934 * RENDER_SURFACE_STATE Surface Pitch (p349):
936 * - For tiled surfaces, the pitch must be a multiple of the tile
939 row_pitch
= isl_align(row_pitch
, tile_info
->width
);
947 * Calculate the surface's total height, including padding, in units of
951 isl_calc_total_height_el(const struct isl_device
*dev
,
952 const struct isl_surf_init_info
*restrict info
,
953 const struct isl_tile_info
*tile_info
,
954 uint32_t phys_array_len
,
956 uint32_t array_pitch_el_rows
)
958 const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
960 uint32_t total_h_el
= phys_array_len
* array_pitch_el_rows
;
961 uint32_t pad_bytes
= 0;
963 /* From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
964 * Formats >> Surface Padding Requirements >> Render Target and Media
967 * The data port accesses data (pixels) outside of the surface if they
968 * are contained in the same cache request as pixels that are within the
969 * surface. These pixels will not be returned by the requesting message,
970 * however if these pixels lie outside of defined pages in the GTT,
971 * a GTT error will result when the cache request is processed. In
972 * order to avoid these GTT errors, “padding” at the bottom of the
973 * surface is sometimes necessary.
975 * From the Broadwell PRM >> Volume 5: Memory Views >> Common Surface
976 * Formats >> Surface Padding Requirements >> Sampling Engine Surfaces:
978 * ... Lots of padding requirements, all listed separately below.
981 /* We can safely ignore the first padding requirement, quoted below,
982 * because isl doesn't do buffers.
984 * - [pre-BDW] For buffers, which have no inherent “height,” padding
985 * requirements are different. A buffer must be padded to the next
986 * multiple of 256 array elements, with an additional 16 bytes added
987 * beyond that to account for the L1 cache line.
991 * - For compressed textures [...], padding at the bottom of the surface
992 * is to an even compressed row.
994 if (isl_format_is_compressed(info
->format
))
995 total_h_el
= isl_align(total_h_el
, 2);
998 * - For cube surfaces, an additional two rows of padding are required
999 * at the bottom of the surface.
1001 if (info
->usage
& ISL_SURF_USAGE_CUBE_BIT
)
1005 * - For packed YUV, 96 bpt, 48 bpt, and 24 bpt surface formats,
1006 * additional padding is required. These surfaces require an extra row
1007 * plus 16 bytes of padding at the bottom in addition to the general
1008 * padding requirements.
1010 if (isl_format_is_yuv(info
->format
) &&
1011 (fmtl
->bs
== 96 || fmtl
->bs
== 48|| fmtl
->bs
== 24)) {
1017 * - For linear surfaces, additional padding of 64 bytes is required at
1018 * the bottom of the surface. This is in addition to the padding
1021 if (tile_info
->tiling
== ISL_TILING_LINEAR
)
1024 /* The below text weakens, not strengthens, the padding requirements for
1025 * linear surfaces. Therefore we can safely ignore it.
1027 * - [BDW+] For SURFTYPE_BUFFER, SURFTYPE_1D, and SURFTYPE_2D non-array,
1028 * non-MSAA, non-mip-mapped surfaces in linear memory, the only
1029 * padding requirement is to the next aligned 64-byte boundary beyond
1030 * the end of the surface. The rest of the padding requirements
1031 * documented above do not apply to these surfaces.
1035 * - [SKL+] For SURFTYPE_2D and SURFTYPE_3D with linear mode and
1036 * height % 4 != 0, the surface must be padded with
1037 * 4-(height % 4)*Surface Pitch # of bytes.
1039 if (ISL_DEV_GEN(dev
) >= 9 &&
1040 tile_info
->tiling
== ISL_TILING_LINEAR
&&
1041 (info
->dim
== ISL_SURF_DIM_2D
|| info
->dim
== ISL_SURF_DIM_3D
)) {
1042 total_h_el
= isl_align(total_h_el
, 4);
1046 * - [SKL+] For SURFTYPE_1D with linear mode, the surface must be padded
1047 * to 4 times the Surface Pitch # of bytes
1049 if (ISL_DEV_GEN(dev
) >= 9 &&
1050 tile_info
->tiling
== ISL_TILING_LINEAR
&&
1051 info
->dim
== ISL_SURF_DIM_1D
) {
1055 /* Be sloppy. Align any leftover padding to a row boundary. */
1056 total_h_el
+= isl_align_div_npot(pad_bytes
, row_pitch
);
1062 isl_surf_init_s(const struct isl_device
*dev
,
1063 struct isl_surf
*surf
,
1064 const struct isl_surf_init_info
*restrict info
)
1066 const struct isl_format_layout
*fmtl
= isl_format_get_layout(info
->format
);
1068 const struct isl_extent4d logical_level0_px
= {
1072 .a
= info
->array_len
,
1075 enum isl_dim_layout dim_layout
=
1076 isl_surf_choose_dim_layout(dev
, info
->dim
);
1078 enum isl_tiling tiling
;
1079 if (!isl_surf_choose_tiling(dev
, info
, &tiling
))
1082 struct isl_tile_info tile_info
;
1083 if (!isl_tiling_get_info(dev
, tiling
, fmtl
->bs
, &tile_info
))
1086 enum isl_msaa_layout msaa_layout
;
1087 if (!isl_choose_msaa_layout(dev
, info
, tiling
, &msaa_layout
))
1090 struct isl_extent3d image_align_el
;
1091 isl_choose_image_alignment_el(dev
, info
, tiling
, msaa_layout
,
1094 struct isl_extent3d image_align_sa
=
1095 isl_extent3d_el_to_sa(info
->format
, image_align_el
);
1097 struct isl_extent4d phys_level0_sa
;
1098 isl_calc_phys_level0_extent_sa(dev
, info
, dim_layout
, tiling
, msaa_layout
,
1100 assert(phys_level0_sa
.w
% fmtl
->bw
== 0);
1101 assert(phys_level0_sa
.h
% fmtl
->bh
== 0);
1103 enum isl_array_pitch_span array_pitch_span
=
1104 isl_choose_array_pitch_span(dev
, info
, dim_layout
, &phys_level0_sa
);
1106 struct isl_extent2d phys_slice0_sa
;
1107 isl_calc_phys_slice0_extent_sa(dev
, info
, dim_layout
, msaa_layout
,
1108 &image_align_sa
, &phys_level0_sa
,
1110 assert(phys_slice0_sa
.w
% fmtl
->bw
== 0);
1111 assert(phys_slice0_sa
.h
% fmtl
->bh
== 0);
1113 const uint32_t row_pitch
= isl_calc_row_pitch(dev
, info
, &tile_info
,
1117 const uint32_t array_pitch_el_rows
=
1118 isl_calc_array_pitch_el_rows(dev
, info
, &tile_info
, dim_layout
,
1119 array_pitch_span
, &image_align_sa
,
1120 &phys_level0_sa
, &phys_slice0_sa
);
1122 const uint32_t total_h_el
=
1123 isl_calc_total_height_el(dev
, info
, &tile_info
,
1124 phys_level0_sa
.array_len
, row_pitch
,
1125 array_pitch_el_rows
);
1127 const uint32_t total_h_sa
= total_h_el
* fmtl
->bh
;
1128 const uint32_t size
= row_pitch
* isl_align(total_h_sa
, tile_info
.height
);
1130 /* Alignment of surface base address, in bytes */
1131 uint32_t base_alignment
= MAX(1, info
->min_alignment
);
1132 assert(isl_is_pow2(base_alignment
) && isl_is_pow2(tile_info
.size
));
1133 base_alignment
= MAX(base_alignment
, tile_info
.size
);
1135 *surf
= (struct isl_surf
) {
1137 .dim_layout
= dim_layout
,
1138 .msaa_layout
= msaa_layout
,
1140 .format
= info
->format
,
1142 .levels
= info
->levels
,
1143 .samples
= info
->samples
,
1145 .image_alignment_el
= image_align_el
,
1146 .logical_level0_px
= logical_level0_px
,
1147 .phys_level0_sa
= phys_level0_sa
,
1150 .alignment
= base_alignment
,
1151 .row_pitch
= row_pitch
,
1152 .array_pitch_el_rows
= array_pitch_el_rows
,
1153 .array_pitch_span
= array_pitch_span
,
1155 .usage
= info
->usage
,
1162 isl_surf_get_tile_info(const struct isl_device
*dev
,
1163 const struct isl_surf
*surf
,
1164 struct isl_tile_info
*tile_info
)
1166 const struct isl_format_layout
*fmtl
= isl_format_get_layout(surf
->format
);
1167 isl_tiling_get_info(dev
, surf
->tiling
, fmtl
->bs
, tile_info
);
1171 isl_surf_fill_state_s(const struct isl_device
*dev
, void *state
,
1172 const struct isl_surf_fill_state_info
*restrict info
)
1175 isl_surf_usage_flags_t _base_usage
=
1176 info
->view
->usage
& (ISL_SURF_USAGE_RENDER_TARGET_BIT
|
1177 ISL_SURF_USAGE_TEXTURE_BIT
|
1178 ISL_SURF_USAGE_STORAGE_BIT
);
1179 /* They may only specify one of the above bits at a time */
1180 assert(__builtin_popcount(_base_usage
) == 1);
1181 /* The only other allowed bit is ISL_SURF_USAGE_CUBE_BIT */
1182 assert((info
->view
->usage
& ~ISL_SURF_USAGE_CUBE_BIT
) == _base_usage
);
1185 if (info
->surf
->dim
== ISL_SURF_DIM_3D
) {
1186 assert(info
->view
->base_array_layer
+ info
->view
->array_len
<=
1187 info
->surf
->logical_level0_px
.depth
);
1189 assert(info
->view
->base_array_layer
+ info
->view
->array_len
<=
1190 info
->surf
->logical_level0_px
.array_len
);
1193 switch (ISL_DEV_GEN(dev
)) {
1195 if (ISL_DEV_IS_HASWELL(dev
)) {
1196 isl_gen75_surf_fill_state_s(dev
, state
, info
);
1198 isl_gen7_surf_fill_state_s(dev
, state
, info
);
1202 isl_gen8_surf_fill_state_s(dev
, state
, info
);
1205 isl_gen9_surf_fill_state_s(dev
, state
, info
);
1208 assert(!"Cannot fill surface state for this gen");
1213 isl_buffer_fill_state_s(const struct isl_device
*dev
, void *state
,
1214 const struct isl_buffer_fill_state_info
*restrict info
)
1216 switch (ISL_DEV_GEN(dev
)) {
1218 if (ISL_DEV_IS_HASWELL(dev
)) {
1219 isl_gen75_buffer_fill_state_s(state
, info
);
1221 isl_gen7_buffer_fill_state_s(state
, info
);
1225 isl_gen8_buffer_fill_state_s(state
, info
);
1228 isl_gen9_buffer_fill_state_s(state
, info
);
1231 assert(!"Cannot fill surface state for this gen");
1236 * A variant of isl_surf_get_image_offset_sa() specific to
1237 * ISL_DIM_LAYOUT_GEN4_2D.
1240 get_image_offset_sa_gen4_2d(const struct isl_surf
*surf
,
1241 uint32_t level
, uint32_t layer
,
1242 uint32_t *x_offset_sa
,
1243 uint32_t *y_offset_sa
)
1245 assert(level
< surf
->levels
);
1246 assert(layer
< surf
->phys_level0_sa
.array_len
);
1247 assert(surf
->phys_level0_sa
.depth
== 1);
1249 const struct isl_extent3d image_align_sa
=
1250 isl_surf_get_image_alignment_sa(surf
);
1252 const uint32_t W0
= surf
->phys_level0_sa
.width
;
1253 const uint32_t H0
= surf
->phys_level0_sa
.height
;
1256 uint32_t y
= layer
* isl_surf_get_array_pitch_sa_rows(surf
);
1258 for (uint32_t l
= 0; l
< level
; ++l
) {
1260 uint32_t W
= isl_minify(W0
, l
);
1262 if (surf
->msaa_layout
== ISL_MSAA_LAYOUT_INTERLEAVED
)
1263 isl_msaa_interleaved_scale_px_to_sa(surf
->samples
, &W
, NULL
);
1265 x
+= isl_align_npot(W
, image_align_sa
.w
);
1267 uint32_t H
= isl_minify(H0
, l
);
1269 if (surf
->msaa_layout
== ISL_MSAA_LAYOUT_INTERLEAVED
)
1270 isl_msaa_interleaved_scale_px_to_sa(surf
->samples
, NULL
, &H
);
1272 y
+= isl_align_npot(H
, image_align_sa
.h
);
1281 * A variant of isl_surf_get_image_offset_sa() specific to
1282 * ISL_DIM_LAYOUT_GEN4_3D.
1285 get_image_offset_sa_gen4_3d(const struct isl_surf
*surf
,
1286 uint32_t level
, uint32_t logical_z_offset_px
,
1287 uint32_t *x_offset_sa
,
1288 uint32_t *y_offset_sa
)
1290 assert(level
< surf
->levels
);
1291 assert(logical_z_offset_px
< isl_minify(surf
->phys_level0_sa
.depth
, level
));
1292 assert(surf
->phys_level0_sa
.array_len
== 1);
1294 const struct isl_extent3d image_align_sa
=
1295 isl_surf_get_image_alignment_sa(surf
);
1297 const uint32_t W0
= surf
->phys_level0_sa
.width
;
1298 const uint32_t H0
= surf
->phys_level0_sa
.height
;
1299 const uint32_t D0
= surf
->phys_level0_sa
.depth
;
1304 for (uint32_t l
= 0; l
< level
; ++l
) {
1305 const uint32_t level_h
= isl_align_npot(isl_minify(H0
, l
), image_align_sa
.h
);
1306 const uint32_t level_d
= isl_align_npot(isl_minify(D0
, l
), image_align_sa
.d
);
1307 const uint32_t max_layers_vert
= isl_align(level_d
, 1u << l
) / (1u << l
);
1309 y
+= level_h
* max_layers_vert
;
1312 const uint32_t level_w
= isl_align_npot(isl_minify(W0
, level
), image_align_sa
.w
);
1313 const uint32_t level_h
= isl_align_npot(isl_minify(H0
, level
), image_align_sa
.h
);
1314 const uint32_t level_d
= isl_align_npot(isl_minify(D0
, level
), image_align_sa
.d
);
1316 const uint32_t max_layers_horiz
= MIN(level_d
, 1u << level
);
1318 x
+= level_w
* (logical_z_offset_px
% max_layers_horiz
);
1319 y
+= level_h
* (logical_z_offset_px
/ max_layers_horiz
);
1326 * A variant of isl_surf_get_image_offset_sa() specific to
1327 * ISL_DIM_LAYOUT_GEN9_1D.
1330 get_image_offset_sa_gen9_1d(const struct isl_surf
*surf
,
1331 uint32_t level
, uint32_t layer
,
1332 uint32_t *x_offset_sa
,
1333 uint32_t *y_offset_sa
)
1335 assert(level
< surf
->levels
);
1336 assert(layer
< surf
->phys_level0_sa
.array_len
);
1337 assert(surf
->phys_level0_sa
.height
== 1);
1338 assert(surf
->phys_level0_sa
.depth
== 1);
1339 assert(surf
->samples
== 1);
1341 const uint32_t W0
= surf
->phys_level0_sa
.width
;
1342 const struct isl_extent3d image_align_sa
=
1343 isl_surf_get_image_alignment_sa(surf
);
1347 for (uint32_t l
= 0; l
< level
; ++l
) {
1348 uint32_t W
= isl_minify(W0
, l
);
1349 uint32_t w
= isl_align_npot(W
, image_align_sa
.w
);
1355 *y_offset_sa
= layer
* isl_surf_get_array_pitch_sa_rows(surf
);
1359 * Calculate the offset, in units of surface samples, to a subimage in the
1362 * @invariant level < surface levels
1363 * @invariant logical_array_layer < logical array length of surface
1364 * @invariant logical_z_offset_px < logical depth of surface at level
1367 get_image_offset_sa(const struct isl_surf
*surf
,
1369 uint32_t logical_array_layer
,
1370 uint32_t logical_z_offset_px
,
1371 uint32_t *x_offset_sa
,
1372 uint32_t *y_offset_sa
)
1374 assert(level
< surf
->levels
);
1375 assert(logical_array_layer
< surf
->logical_level0_px
.array_len
);
1376 assert(logical_z_offset_px
1377 < isl_minify(surf
->logical_level0_px
.depth
, level
));
1379 switch (surf
->dim_layout
) {
1380 case ISL_DIM_LAYOUT_GEN9_1D
:
1381 get_image_offset_sa_gen9_1d(surf
, level
, logical_array_layer
,
1382 x_offset_sa
, y_offset_sa
);
1384 case ISL_DIM_LAYOUT_GEN4_2D
:
1385 get_image_offset_sa_gen4_2d(surf
, level
, logical_array_layer
1386 + logical_z_offset_px
,
1387 x_offset_sa
, y_offset_sa
);
1389 case ISL_DIM_LAYOUT_GEN4_3D
:
1390 get_image_offset_sa_gen4_3d(surf
, level
, logical_z_offset_px
,
1391 x_offset_sa
, y_offset_sa
);
1395 unreachable("not reached");
1400 isl_surf_get_image_offset_el(const struct isl_surf
*surf
,
1402 uint32_t logical_array_layer
,
1403 uint32_t logical_z_offset_px
,
1404 uint32_t *x_offset_el
,
1405 uint32_t *y_offset_el
)
1407 const struct isl_format_layout
*fmtl
= isl_format_get_layout(surf
->format
);
1409 assert(level
< surf
->levels
);
1410 assert(logical_array_layer
< surf
->logical_level0_px
.array_len
);
1411 assert(logical_z_offset_px
1412 < isl_minify(surf
->logical_level0_px
.depth
, level
));
1414 uint32_t x_offset_sa
, y_offset_sa
;
1415 get_image_offset_sa(surf
, level
,
1416 logical_array_layer
,
1417 logical_z_offset_px
,
1421 *x_offset_el
= x_offset_sa
/ fmtl
->bw
;
1422 *y_offset_el
= y_offset_sa
/ fmtl
->bh
;
1426 isl_tiling_get_intratile_offset_el(const struct isl_device
*dev
,
1427 enum isl_tiling tiling
,
1430 uint32_t total_x_offset_el
,
1431 uint32_t total_y_offset_el
,
1432 uint32_t *base_address_offset
,
1433 uint32_t *x_offset_el
,
1434 uint32_t *y_offset_el
)
1436 struct isl_tile_info tile_info
;
1437 isl_tiling_get_info(dev
, tiling
, bs
, &tile_info
);
1439 /* This function only really works for power-of-two surfaces. In
1440 * theory, we could make it work for non-power-of-two surfaces by going
1441 * to the left until we find a block that is bs-aligned. The Vulkan
1442 * driver doesn't use non-power-of-two tiled surfaces so we'll leave
1443 * this unimplemented for now.
1445 assert(tiling
== ISL_TILING_LINEAR
|| isl_is_pow2(bs
));
1447 uint32_t small_y_offset_el
= total_y_offset_el
% tile_info
.height
;
1448 uint32_t big_y_offset_el
= total_y_offset_el
- small_y_offset_el
;
1449 uint32_t big_y_offset_B
= big_y_offset_el
* row_pitch
;
1451 uint32_t total_x_offset_B
= total_x_offset_el
* bs
;
1452 uint32_t small_x_offset_B
= total_x_offset_B
% tile_info
.width
;
1453 uint32_t small_x_offset_el
= small_x_offset_B
/ bs
;
1454 uint32_t big_x_offset_B
= (total_x_offset_B
/ tile_info
.width
) * tile_info
.size
;
1456 *base_address_offset
= big_y_offset_B
+ big_x_offset_B
;
1457 *x_offset_el
= small_x_offset_el
;
1458 *y_offset_el
= small_y_offset_el
;
1462 isl_surf_get_depth_format(const struct isl_device
*dev
,
1463 const struct isl_surf
*surf
)
1465 /* Support for separate stencil buffers began in gen5. Support for
1466 * interleaved depthstencil buffers ceased in gen7. The intermediate gens,
1467 * those that supported separate and interleaved stencil, were gen5 and
1470 * For a list of all available formats, see the Sandybridge PRM >> Volume
1471 * 2 Part 1: 3D/Media - 3D Pipeline >> 3DSTATE_DEPTH_BUFFER >> Surface
1475 bool has_stencil
= surf
->usage
& ISL_SURF_USAGE_STENCIL_BIT
;
1477 assert(surf
->usage
& ISL_SURF_USAGE_DEPTH_BIT
);
1480 assert(ISL_DEV_GEN(dev
) < 7);
1482 switch (surf
->format
) {
1484 unreachable("bad isl depth format");
1485 case ISL_FORMAT_R32_FLOAT_X8X24_TYPELESS
:
1486 assert(ISL_DEV_GEN(dev
) < 7);
1487 return 0; /* D32_FLOAT_S8X24_UINT */
1488 case ISL_FORMAT_R32_FLOAT
:
1489 assert(!has_stencil
);
1490 return 1; /* D32_FLOAT */
1491 case ISL_FORMAT_R24_UNORM_X8_TYPELESS
:
1493 assert(ISL_DEV_GEN(dev
) < 7);
1494 return 2; /* D24_UNORM_S8_UINT */
1496 assert(ISL_DEV_GEN(dev
) >= 5);
1497 return 3; /* D24_UNORM_X8_UINT */
1499 case ISL_FORMAT_R16_UNORM
:
1500 assert(!has_stencil
);
1501 return 5; /* D16_UNORM */