xref: /aosp_15_r20/external/mesa3d/src/nouveau/nil/tiling.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker // Copyright © 2024 Collabora, Ltd.
2*61046927SAndroid Build Coastguard Worker // SPDX-License-Identifier: MIT
3*61046927SAndroid Build Coastguard Worker 
4*61046927SAndroid Build Coastguard Worker use crate::extent::{units, Extent4D};
5*61046927SAndroid Build Coastguard Worker use crate::format::Format;
6*61046927SAndroid Build Coastguard Worker use crate::image::{
7*61046927SAndroid Build Coastguard Worker     ImageDim, ImageUsageFlags, SampleLayout, IMAGE_USAGE_2D_VIEW_BIT,
8*61046927SAndroid Build Coastguard Worker     IMAGE_USAGE_LINEAR_BIT,
9*61046927SAndroid Build Coastguard Worker };
10*61046927SAndroid Build Coastguard Worker use crate::ILog2Ceil;
11*61046927SAndroid Build Coastguard Worker 
12*61046927SAndroid Build Coastguard Worker pub const GOB_WIDTH_B: u32 = 64;
13*61046927SAndroid Build Coastguard Worker pub const GOB_DEPTH: u32 = 1;
14*61046927SAndroid Build Coastguard Worker 
gob_height(gob_height_is_8: bool) -> u3215*61046927SAndroid Build Coastguard Worker pub fn gob_height(gob_height_is_8: bool) -> u32 {
16*61046927SAndroid Build Coastguard Worker     if gob_height_is_8 {
17*61046927SAndroid Build Coastguard Worker         8
18*61046927SAndroid Build Coastguard Worker     } else {
19*61046927SAndroid Build Coastguard Worker         4
20*61046927SAndroid Build Coastguard Worker     }
21*61046927SAndroid Build Coastguard Worker }
22*61046927SAndroid Build Coastguard Worker 
23*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, Default, Copy, PartialEq)]
24*61046927SAndroid Build Coastguard Worker #[repr(C)]
25*61046927SAndroid Build Coastguard Worker pub struct Tiling {
26*61046927SAndroid Build Coastguard Worker     pub is_tiled: bool,
27*61046927SAndroid Build Coastguard Worker     /// Whether the GOB height is 4 or 8
28*61046927SAndroid Build Coastguard Worker     pub gob_height_is_8: bool,
29*61046927SAndroid Build Coastguard Worker     /// log2 of the X tile dimension in GOBs
30*61046927SAndroid Build Coastguard Worker     pub x_log2: u8,
31*61046927SAndroid Build Coastguard Worker     /// log2 of the Y tile dimension in GOBs
32*61046927SAndroid Build Coastguard Worker     pub y_log2: u8,
33*61046927SAndroid Build Coastguard Worker     /// log2 of the z tile dimension in GOBs
34*61046927SAndroid Build Coastguard Worker     pub z_log2: u8,
35*61046927SAndroid Build Coastguard Worker }
36*61046927SAndroid Build Coastguard Worker 
37*61046927SAndroid Build Coastguard Worker impl Tiling {
38*61046927SAndroid Build Coastguard Worker     /// Clamps the tiling to less than 2x the given extent in each dimension.
39*61046927SAndroid Build Coastguard Worker     ///
40*61046927SAndroid Build Coastguard Worker     /// This operation is done by the hardware at each LOD.
clamp(&self, extent_B: Extent4D<units::Bytes>) -> Self41*61046927SAndroid Build Coastguard Worker     pub fn clamp(&self, extent_B: Extent4D<units::Bytes>) -> Self {
42*61046927SAndroid Build Coastguard Worker         let mut tiling = *self;
43*61046927SAndroid Build Coastguard Worker 
44*61046927SAndroid Build Coastguard Worker         if !self.is_tiled {
45*61046927SAndroid Build Coastguard Worker             return tiling;
46*61046927SAndroid Build Coastguard Worker         }
47*61046927SAndroid Build Coastguard Worker 
48*61046927SAndroid Build Coastguard Worker         let tiling_extent_B = self.extent_B();
49*61046927SAndroid Build Coastguard Worker 
50*61046927SAndroid Build Coastguard Worker         if extent_B.width < tiling_extent_B.width
51*61046927SAndroid Build Coastguard Worker             || extent_B.height < tiling_extent_B.height
52*61046927SAndroid Build Coastguard Worker             || extent_B.depth < tiling_extent_B.depth
53*61046927SAndroid Build Coastguard Worker         {
54*61046927SAndroid Build Coastguard Worker             tiling.x_log2 = 0;
55*61046927SAndroid Build Coastguard Worker         }
56*61046927SAndroid Build Coastguard Worker 
57*61046927SAndroid Build Coastguard Worker         let extent_GOB = extent_B.to_GOB(tiling.gob_height_is_8);
58*61046927SAndroid Build Coastguard Worker 
59*61046927SAndroid Build Coastguard Worker         let ceil_h = extent_GOB.height.ilog2_ceil() as u8;
60*61046927SAndroid Build Coastguard Worker         let ceil_d = extent_GOB.depth.ilog2_ceil() as u8;
61*61046927SAndroid Build Coastguard Worker 
62*61046927SAndroid Build Coastguard Worker         tiling.y_log2 = std::cmp::min(tiling.y_log2, ceil_h);
63*61046927SAndroid Build Coastguard Worker         tiling.z_log2 = std::cmp::min(tiling.z_log2, ceil_d);
64*61046927SAndroid Build Coastguard Worker         tiling
65*61046927SAndroid Build Coastguard Worker     }
66*61046927SAndroid Build Coastguard Worker 
size_B(&self) -> u3267*61046927SAndroid Build Coastguard Worker     pub fn size_B(&self) -> u32 {
68*61046927SAndroid Build Coastguard Worker         let extent_B = self.extent_B();
69*61046927SAndroid Build Coastguard Worker         extent_B.width * extent_B.height * extent_B.depth * extent_B.array_len
70*61046927SAndroid Build Coastguard Worker     }
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_tiling_size_B(&self) -> u3273*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_tiling_size_B(&self) -> u32 {
74*61046927SAndroid Build Coastguard Worker         self.size_B()
75*61046927SAndroid Build Coastguard Worker     }
76*61046927SAndroid Build Coastguard Worker 
extent_B(&self) -> Extent4D<units::Bytes>77*61046927SAndroid Build Coastguard Worker     pub fn extent_B(&self) -> Extent4D<units::Bytes> {
78*61046927SAndroid Build Coastguard Worker         if self.is_tiled {
79*61046927SAndroid Build Coastguard Worker             Extent4D::new(
80*61046927SAndroid Build Coastguard Worker                 GOB_WIDTH_B << self.x_log2,
81*61046927SAndroid Build Coastguard Worker                 gob_height(self.gob_height_is_8) << self.y_log2,
82*61046927SAndroid Build Coastguard Worker                 GOB_DEPTH << self.z_log2,
83*61046927SAndroid Build Coastguard Worker                 1,
84*61046927SAndroid Build Coastguard Worker             )
85*61046927SAndroid Build Coastguard Worker         } else {
86*61046927SAndroid Build Coastguard Worker             // We handle linear images in Image::new()
87*61046927SAndroid Build Coastguard Worker             Extent4D::new(1, 1, 1, 1)
88*61046927SAndroid Build Coastguard Worker         }
89*61046927SAndroid Build Coastguard Worker     }
90*61046927SAndroid Build Coastguard Worker }
91*61046927SAndroid Build Coastguard Worker 
sparse_block_extent_el( format: Format, dim: ImageDim, ) -> Extent4D<units::Elements>92*61046927SAndroid Build Coastguard Worker pub fn sparse_block_extent_el(
93*61046927SAndroid Build Coastguard Worker     format: Format,
94*61046927SAndroid Build Coastguard Worker     dim: ImageDim,
95*61046927SAndroid Build Coastguard Worker ) -> Extent4D<units::Elements> {
96*61046927SAndroid Build Coastguard Worker     let bits = format.el_size_B() * 8;
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker     // Taken from Vulkan 1.3.279 spec section entitled "Standard Sparse
99*61046927SAndroid Build Coastguard Worker     // Image Block Shapes".
100*61046927SAndroid Build Coastguard Worker     match dim {
101*61046927SAndroid Build Coastguard Worker         ImageDim::_2D => match bits {
102*61046927SAndroid Build Coastguard Worker             8 => Extent4D::new(256, 256, 1, 1),
103*61046927SAndroid Build Coastguard Worker             16 => Extent4D::new(256, 128, 1, 1),
104*61046927SAndroid Build Coastguard Worker             32 => Extent4D::new(128, 128, 1, 1),
105*61046927SAndroid Build Coastguard Worker             64 => Extent4D::new(128, 64, 1, 1),
106*61046927SAndroid Build Coastguard Worker             128 => Extent4D::new(64, 64, 1, 1),
107*61046927SAndroid Build Coastguard Worker             other => panic!("Invalid texel size {other}"),
108*61046927SAndroid Build Coastguard Worker         },
109*61046927SAndroid Build Coastguard Worker         ImageDim::_3D => match bits {
110*61046927SAndroid Build Coastguard Worker             8 => Extent4D::new(64, 32, 32, 1),
111*61046927SAndroid Build Coastguard Worker             16 => Extent4D::new(32, 32, 32, 1),
112*61046927SAndroid Build Coastguard Worker             32 => Extent4D::new(32, 32, 16, 1),
113*61046927SAndroid Build Coastguard Worker             64 => Extent4D::new(32, 16, 16, 1),
114*61046927SAndroid Build Coastguard Worker             128 => Extent4D::new(16, 16, 16, 1),
115*61046927SAndroid Build Coastguard Worker             _ => panic!("Invalid texel size"),
116*61046927SAndroid Build Coastguard Worker         },
117*61046927SAndroid Build Coastguard Worker         _ => panic!("Invalid sparse image dimension"),
118*61046927SAndroid Build Coastguard Worker     }
119*61046927SAndroid Build Coastguard Worker }
120*61046927SAndroid Build Coastguard Worker 
sparse_block_extent_px( format: Format, dim: ImageDim, sample_layout: SampleLayout, ) -> Extent4D<units::Pixels>121*61046927SAndroid Build Coastguard Worker pub fn sparse_block_extent_px(
122*61046927SAndroid Build Coastguard Worker     format: Format,
123*61046927SAndroid Build Coastguard Worker     dim: ImageDim,
124*61046927SAndroid Build Coastguard Worker     sample_layout: SampleLayout,
125*61046927SAndroid Build Coastguard Worker ) -> Extent4D<units::Pixels> {
126*61046927SAndroid Build Coastguard Worker     sparse_block_extent_el(format, dim)
127*61046927SAndroid Build Coastguard Worker         .to_sa(format)
128*61046927SAndroid Build Coastguard Worker         .to_px(sample_layout)
129*61046927SAndroid Build Coastguard Worker }
130*61046927SAndroid Build Coastguard Worker 
sparse_block_extent_B( format: Format, dim: ImageDim, ) -> Extent4D<units::Bytes>131*61046927SAndroid Build Coastguard Worker pub fn sparse_block_extent_B(
132*61046927SAndroid Build Coastguard Worker     format: Format,
133*61046927SAndroid Build Coastguard Worker     dim: ImageDim,
134*61046927SAndroid Build Coastguard Worker ) -> Extent4D<units::Bytes> {
135*61046927SAndroid Build Coastguard Worker     sparse_block_extent_el(format, dim).to_B(format)
136*61046927SAndroid Build Coastguard Worker }
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker #[no_mangle]
nil_sparse_block_extent_px( format: Format, dim: ImageDim, sample_layout: SampleLayout, ) -> Extent4D<units::Pixels>139*61046927SAndroid Build Coastguard Worker pub extern "C" fn nil_sparse_block_extent_px(
140*61046927SAndroid Build Coastguard Worker     format: Format,
141*61046927SAndroid Build Coastguard Worker     dim: ImageDim,
142*61046927SAndroid Build Coastguard Worker     sample_layout: SampleLayout,
143*61046927SAndroid Build Coastguard Worker ) -> Extent4D<units::Pixels> {
144*61046927SAndroid Build Coastguard Worker     sparse_block_extent_px(format, dim, sample_layout)
145*61046927SAndroid Build Coastguard Worker }
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker impl Tiling {
sparse(format: Format, dim: ImageDim) -> Self148*61046927SAndroid Build Coastguard Worker     pub fn sparse(format: Format, dim: ImageDim) -> Self {
149*61046927SAndroid Build Coastguard Worker         let sparse_block_extent_B = sparse_block_extent_B(format, dim);
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker         assert!(sparse_block_extent_B.width.is_power_of_two());
152*61046927SAndroid Build Coastguard Worker         assert!(sparse_block_extent_B.height.is_power_of_two());
153*61046927SAndroid Build Coastguard Worker         assert!(sparse_block_extent_B.depth.is_power_of_two());
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker         let gob_height_is_8 = true;
156*61046927SAndroid Build Coastguard Worker         let sparse_block_extent_gob =
157*61046927SAndroid Build Coastguard Worker             sparse_block_extent_B.to_GOB(gob_height_is_8);
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker         Self {
160*61046927SAndroid Build Coastguard Worker             is_tiled: true,
161*61046927SAndroid Build Coastguard Worker             gob_height_is_8,
162*61046927SAndroid Build Coastguard Worker             x_log2: sparse_block_extent_gob.width.ilog2().try_into().unwrap(),
163*61046927SAndroid Build Coastguard Worker             y_log2: sparse_block_extent_gob.height.ilog2().try_into().unwrap(),
164*61046927SAndroid Build Coastguard Worker             z_log2: sparse_block_extent_gob.depth.ilog2().try_into().unwrap(),
165*61046927SAndroid Build Coastguard Worker         }
166*61046927SAndroid Build Coastguard Worker     }
167*61046927SAndroid Build Coastguard Worker 
choose( extent_px: Extent4D<units::Pixels>, format: Format, sample_layout: SampleLayout, usage: ImageUsageFlags, ) -> Tiling168*61046927SAndroid Build Coastguard Worker     pub fn choose(
169*61046927SAndroid Build Coastguard Worker         extent_px: Extent4D<units::Pixels>,
170*61046927SAndroid Build Coastguard Worker         format: Format,
171*61046927SAndroid Build Coastguard Worker         sample_layout: SampleLayout,
172*61046927SAndroid Build Coastguard Worker         usage: ImageUsageFlags,
173*61046927SAndroid Build Coastguard Worker     ) -> Tiling {
174*61046927SAndroid Build Coastguard Worker         if (usage & IMAGE_USAGE_LINEAR_BIT) != 0 {
175*61046927SAndroid Build Coastguard Worker             return Default::default();
176*61046927SAndroid Build Coastguard Worker         }
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker         let mut tiling = Tiling {
179*61046927SAndroid Build Coastguard Worker             is_tiled: true,
180*61046927SAndroid Build Coastguard Worker             gob_height_is_8: true,
181*61046927SAndroid Build Coastguard Worker             x_log2: 0,
182*61046927SAndroid Build Coastguard Worker             y_log2: 5,
183*61046927SAndroid Build Coastguard Worker             z_log2: 5,
184*61046927SAndroid Build Coastguard Worker         };
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker         if (usage & IMAGE_USAGE_2D_VIEW_BIT) != 0 {
187*61046927SAndroid Build Coastguard Worker             tiling.z_log2 = 0;
188*61046927SAndroid Build Coastguard Worker         }
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker         tiling.clamp(extent_px.to_B(format, sample_layout))
191*61046927SAndroid Build Coastguard Worker     }
192*61046927SAndroid Build Coastguard Worker }
193