1 /*
2 * Copyright © 2025 Igalia S.L.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #ifndef FREEDRENO_LRZ_LAYOUT_H_
7 #define FREEDRENO_LRZ_LAYOUT_H_
8
9 #include <stdint.h>
10
11 #include "freedreno_layout.h"
12
13 BEGINC;
14
15 struct fdl_lrz_layout {
16 uint32_t lrz_offset;
17 uint32_t lrz_pitch;
18 uint32_t lrz_height;
19 uint32_t lrz_layer_size;
20 uint32_t lrz_fc_offset;
21 uint32_t lrz_fc_size;
22 uint32_t lrz_total_size;
23 };
24
25 void
26 fdl5_lrz_layout_init(struct fdl_lrz_layout *lrz_layout, uint32_t width,
27 uint32_t height, uint32_t nr_samples);
28 ENDC;
29
30 #ifdef __cplusplus
31 #include "common/freedreno_lrz.h"
32
33 template <chip CHIP>
34 static void
fdl6_lrz_layout_init(struct fdl_lrz_layout * lrz_layout,struct fdl_layout * layout,const struct fd_dev_info * dev_info,uint32_t lrz_offset,uint32_t array_layers)35 fdl6_lrz_layout_init(struct fdl_lrz_layout *lrz_layout,
36 struct fdl_layout *layout,
37 const struct fd_dev_info *dev_info, uint32_t lrz_offset,
38 uint32_t array_layers)
39 {
40 unsigned width = layout->width0;
41 unsigned height = layout->height0;
42
43 /* LRZ buffer is super-sampled */
44 switch (layout->nr_samples) {
45 case 8:
46 height *= 2;
47 FALLTHROUGH;
48 case 4:
49 width *= 2;
50 FALLTHROUGH;
51 case 2:
52 height *= 2;
53 break;
54 default:
55 break;
56 }
57
58 unsigned lrz_pitch = align(DIV_ROUND_UP(width, 8), 32);
59 unsigned lrz_height = align(DIV_ROUND_UP(height, 8), 32);
60
61 lrz_layout->lrz_offset = lrz_offset;
62 lrz_layout->lrz_height = lrz_height;
63 lrz_layout->lrz_pitch = lrz_pitch;
64 lrz_layout->lrz_layer_size = lrz_pitch * lrz_height * sizeof(uint16_t);
65
66 unsigned nblocksx = DIV_ROUND_UP(DIV_ROUND_UP(width, 8), 16);
67 unsigned nblocksy = DIV_ROUND_UP(DIV_ROUND_UP(height, 8), 4);
68
69 /* Fast-clear buffer is 1bit/block */
70 lrz_layout->lrz_fc_size =
71 DIV_ROUND_UP(nblocksx * nblocksy, 8) * array_layers;
72
73 /* Fast-clear buffer cannot be larger than 512 bytes on A6XX and 1024 bytes
74 * on A7XX (HW limitation) */
75 if (!dev_info->a6xx.enable_lrz_fast_clear ||
76 lrz_layout->lrz_fc_size > fd_lrzfc_layout<CHIP>::FC_SIZE) {
77 lrz_layout->lrz_fc_size = 0;
78 }
79
80 uint32_t lrz_size = lrz_layout->lrz_layer_size * array_layers;
81 if (dev_info->a6xx.enable_lrz_fast_clear ||
82 dev_info->a6xx.has_lrz_dir_tracking) {
83 lrz_layout->lrz_fc_offset =
84 lrz_layout->lrz_offset + lrz_size;
85 lrz_size += sizeof(fd_lrzfc_layout<CHIP>);
86 }
87
88 lrz_layout->lrz_total_size = lrz_size;
89
90 uint32_t lrz_clear_height = lrz_layout->lrz_height * array_layers;
91 if (((lrz_clear_height - 1) >> 14) > 0) {
92 /* For simplicity bail out if LRZ cannot be cleared in one go. */
93 lrz_layout->lrz_height = 0;
94 lrz_layout->lrz_total_size = 0;
95 }
96 }
97 #endif
98
99 #endif
100