xref: /aosp_15_r20/external/mesa3d/src/nouveau/nil/image.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::modifiers::*;
7*61046927SAndroid Build Coastguard Worker use crate::tiling::Tiling;
8*61046927SAndroid Build Coastguard Worker use crate::Minify;
9*61046927SAndroid Build Coastguard Worker 
10*61046927SAndroid Build Coastguard Worker use nil_rs_bindings::*;
11*61046927SAndroid Build Coastguard Worker use nvidia_headers::classes::{cl9097, clc597};
12*61046927SAndroid Build Coastguard Worker 
13*61046927SAndroid Build Coastguard Worker pub const MAX_LEVELS: usize = 16;
14*61046927SAndroid Build Coastguard Worker 
15*61046927SAndroid Build Coastguard Worker pub type ImageUsageFlags = u8;
16*61046927SAndroid Build Coastguard Worker pub const IMAGE_USAGE_2D_VIEW_BIT: ImageUsageFlags = 1 << 0;
17*61046927SAndroid Build Coastguard Worker pub const IMAGE_USAGE_LINEAR_BIT: ImageUsageFlags = 1 << 1;
18*61046927SAndroid Build Coastguard Worker pub const IMAGE_USAGE_SPARSE_RESIDENCY_BIT: ImageUsageFlags = 1 << 2;
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, Copy, PartialEq, Default)]
21*61046927SAndroid Build Coastguard Worker #[repr(u8)]
22*61046927SAndroid Build Coastguard Worker pub enum ImageDim {
23*61046927SAndroid Build Coastguard Worker     #[default]
24*61046927SAndroid Build Coastguard Worker     _1D = 1,
25*61046927SAndroid Build Coastguard Worker     _2D = 2,
26*61046927SAndroid Build Coastguard Worker     _3D = 3,
27*61046927SAndroid Build Coastguard Worker }
28*61046927SAndroid Build Coastguard Worker 
29*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, Copy, PartialEq, Default)]
30*61046927SAndroid Build Coastguard Worker #[repr(u8)]
31*61046927SAndroid Build Coastguard Worker pub enum SampleLayout {
32*61046927SAndroid Build Coastguard Worker     _1x1 = 0,
33*61046927SAndroid Build Coastguard Worker     _2x1 = 1,
34*61046927SAndroid Build Coastguard Worker     _2x2 = 2,
35*61046927SAndroid Build Coastguard Worker     _4x2 = 3,
36*61046927SAndroid Build Coastguard Worker     _4x4 = 4,
37*61046927SAndroid Build Coastguard Worker     #[default]
38*61046927SAndroid Build Coastguard Worker     Invalid = 5,
39*61046927SAndroid Build Coastguard Worker }
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker impl SampleLayout {
42*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_choose_sample_layout(samples: u32) -> SampleLayout43*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_choose_sample_layout(samples: u32) -> SampleLayout {
44*61046927SAndroid Build Coastguard Worker         Self::choose_sample_layout(samples)
45*61046927SAndroid Build Coastguard Worker     }
46*61046927SAndroid Build Coastguard Worker 
choose_sample_layout(samples: u32) -> SampleLayout47*61046927SAndroid Build Coastguard Worker     pub fn choose_sample_layout(samples: u32) -> SampleLayout {
48*61046927SAndroid Build Coastguard Worker         match samples {
49*61046927SAndroid Build Coastguard Worker             1 => SampleLayout::_1x1,
50*61046927SAndroid Build Coastguard Worker             2 => SampleLayout::_2x1,
51*61046927SAndroid Build Coastguard Worker             4 => SampleLayout::_2x2,
52*61046927SAndroid Build Coastguard Worker             8 => SampleLayout::_4x2,
53*61046927SAndroid Build Coastguard Worker             16 => SampleLayout::_4x4,
54*61046927SAndroid Build Coastguard Worker             _ => SampleLayout::Invalid,
55*61046927SAndroid Build Coastguard Worker         }
56*61046927SAndroid Build Coastguard Worker     }
57*61046927SAndroid Build Coastguard Worker 
px_extent_sa(&self) -> Extent4D<units::Samples>58*61046927SAndroid Build Coastguard Worker     pub fn px_extent_sa(&self) -> Extent4D<units::Samples> {
59*61046927SAndroid Build Coastguard Worker         match self {
60*61046927SAndroid Build Coastguard Worker             SampleLayout::_1x1 => Extent4D::new(1, 1, 1, 1),
61*61046927SAndroid Build Coastguard Worker             SampleLayout::_2x1 => Extent4D::new(2, 1, 1, 1),
62*61046927SAndroid Build Coastguard Worker             SampleLayout::_2x2 => Extent4D::new(2, 2, 1, 1),
63*61046927SAndroid Build Coastguard Worker             SampleLayout::_4x2 => Extent4D::new(4, 2, 1, 1),
64*61046927SAndroid Build Coastguard Worker             SampleLayout::_4x4 => Extent4D::new(4, 4, 1, 1),
65*61046927SAndroid Build Coastguard Worker             SampleLayout::Invalid => panic!("Invalid sample layout"),
66*61046927SAndroid Build Coastguard Worker         }
67*61046927SAndroid Build Coastguard Worker     }
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_px_extent_sa(self) -> Extent4D<units::Samples>70*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_px_extent_sa(self) -> Extent4D<units::Samples> {
71*61046927SAndroid Build Coastguard Worker         self.px_extent_sa()
72*61046927SAndroid Build Coastguard Worker     }
73*61046927SAndroid Build Coastguard Worker }
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, Copy, PartialEq)]
76*61046927SAndroid Build Coastguard Worker #[repr(C)]
77*61046927SAndroid Build Coastguard Worker pub struct ImageInitInfo {
78*61046927SAndroid Build Coastguard Worker     pub dim: ImageDim,
79*61046927SAndroid Build Coastguard Worker     pub format: Format,
80*61046927SAndroid Build Coastguard Worker     pub extent_px: Extent4D<units::Pixels>,
81*61046927SAndroid Build Coastguard Worker     pub levels: u32,
82*61046927SAndroid Build Coastguard Worker     pub samples: u32,
83*61046927SAndroid Build Coastguard Worker     pub usage: ImageUsageFlags,
84*61046927SAndroid Build Coastguard Worker     pub modifier: u64,
85*61046927SAndroid Build Coastguard Worker     pub explicit_row_stride_B: u32,
86*61046927SAndroid Build Coastguard Worker }
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker /// Represents the data layout of a single slice (level + lod) of an image.
89*61046927SAndroid Build Coastguard Worker #[repr(C)]
90*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, Copy, PartialEq, Default)]
91*61046927SAndroid Build Coastguard Worker pub struct ImageLevel {
92*61046927SAndroid Build Coastguard Worker     pub offset_B: u64,
93*61046927SAndroid Build Coastguard Worker     pub tiling: Tiling,
94*61046927SAndroid Build Coastguard Worker     pub row_stride_B: u32,
95*61046927SAndroid Build Coastguard Worker }
96*61046927SAndroid Build Coastguard Worker 
97*61046927SAndroid Build Coastguard Worker #[repr(C)]
98*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, PartialEq)]
99*61046927SAndroid Build Coastguard Worker pub struct Image {
100*61046927SAndroid Build Coastguard Worker     pub dim: ImageDim,
101*61046927SAndroid Build Coastguard Worker     pub format: Format,
102*61046927SAndroid Build Coastguard Worker     pub extent_px: Extent4D<units::Pixels>,
103*61046927SAndroid Build Coastguard Worker     pub sample_layout: SampleLayout,
104*61046927SAndroid Build Coastguard Worker     pub num_levels: u32,
105*61046927SAndroid Build Coastguard Worker     pub mip_tail_first_lod: u32,
106*61046927SAndroid Build Coastguard Worker     pub levels: [ImageLevel; MAX_LEVELS],
107*61046927SAndroid Build Coastguard Worker     pub array_stride_B: u64,
108*61046927SAndroid Build Coastguard Worker     pub align_B: u32,
109*61046927SAndroid Build Coastguard Worker     pub size_B: u64,
110*61046927SAndroid Build Coastguard Worker     pub compressed: bool,
111*61046927SAndroid Build Coastguard Worker     pub tile_mode: u16,
112*61046927SAndroid Build Coastguard Worker     pub pte_kind: u8,
113*61046927SAndroid Build Coastguard Worker }
114*61046927SAndroid Build Coastguard Worker 
115*61046927SAndroid Build Coastguard Worker impl Image {
116*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_new( dev: &nil_rs_bindings::nv_device_info, info: &ImageInitInfo, ) -> Self117*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_new(
118*61046927SAndroid Build Coastguard Worker         dev: &nil_rs_bindings::nv_device_info,
119*61046927SAndroid Build Coastguard Worker         info: &ImageInitInfo,
120*61046927SAndroid Build Coastguard Worker     ) -> Self {
121*61046927SAndroid Build Coastguard Worker         Self::new(dev, info)
122*61046927SAndroid Build Coastguard Worker     }
123*61046927SAndroid Build Coastguard Worker 
new( dev: &nil_rs_bindings::nv_device_info, info: &ImageInitInfo, ) -> Self124*61046927SAndroid Build Coastguard Worker     pub fn new(
125*61046927SAndroid Build Coastguard Worker         dev: &nil_rs_bindings::nv_device_info,
126*61046927SAndroid Build Coastguard Worker         info: &ImageInitInfo,
127*61046927SAndroid Build Coastguard Worker     ) -> Self {
128*61046927SAndroid Build Coastguard Worker         match info.dim {
129*61046927SAndroid Build Coastguard Worker             ImageDim::_1D => {
130*61046927SAndroid Build Coastguard Worker                 assert!(info.extent_px.height == 1);
131*61046927SAndroid Build Coastguard Worker                 assert!(info.extent_px.depth == 1);
132*61046927SAndroid Build Coastguard Worker                 assert!(info.samples == 1);
133*61046927SAndroid Build Coastguard Worker             }
134*61046927SAndroid Build Coastguard Worker             ImageDim::_2D => {
135*61046927SAndroid Build Coastguard Worker                 assert!(info.extent_px.depth == 1);
136*61046927SAndroid Build Coastguard Worker             }
137*61046927SAndroid Build Coastguard Worker             ImageDim::_3D => {
138*61046927SAndroid Build Coastguard Worker                 assert!(info.extent_px.array_len == 1);
139*61046927SAndroid Build Coastguard Worker                 assert!(info.samples == 1);
140*61046927SAndroid Build Coastguard Worker             }
141*61046927SAndroid Build Coastguard Worker         }
142*61046927SAndroid Build Coastguard Worker 
143*61046927SAndroid Build Coastguard Worker         let sample_layout = SampleLayout::choose_sample_layout(info.samples);
144*61046927SAndroid Build Coastguard Worker 
145*61046927SAndroid Build Coastguard Worker         let tiling = if info.modifier != DRM_FORMAT_MOD_INVALID {
146*61046927SAndroid Build Coastguard Worker             assert!((info.usage & IMAGE_USAGE_SPARSE_RESIDENCY_BIT) == 0);
147*61046927SAndroid Build Coastguard Worker             assert!(info.dim == ImageDim::_2D);
148*61046927SAndroid Build Coastguard Worker             assert!(sample_layout == SampleLayout::_1x1);
149*61046927SAndroid Build Coastguard Worker             if info.modifier == DRM_FORMAT_MOD_LINEAR {
150*61046927SAndroid Build Coastguard Worker                 Tiling::default()
151*61046927SAndroid Build Coastguard Worker             } else {
152*61046927SAndroid Build Coastguard Worker                 let bl_mod =
153*61046927SAndroid Build Coastguard Worker                     BlockLinearModifier::try_from(info.modifier).unwrap();
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker                 // We don't support compression yet
156*61046927SAndroid Build Coastguard Worker                 assert!(bl_mod.compression_type() == CompressionType::None);
157*61046927SAndroid Build Coastguard Worker 
158*61046927SAndroid Build Coastguard Worker                 bl_mod
159*61046927SAndroid Build Coastguard Worker                     .tiling()
160*61046927SAndroid Build Coastguard Worker                     .clamp(info.extent_px.to_B(info.format, sample_layout))
161*61046927SAndroid Build Coastguard Worker             }
162*61046927SAndroid Build Coastguard Worker         } else if (info.usage & IMAGE_USAGE_SPARSE_RESIDENCY_BIT) != 0 {
163*61046927SAndroid Build Coastguard Worker             Tiling::sparse(info.format, info.dim)
164*61046927SAndroid Build Coastguard Worker         } else {
165*61046927SAndroid Build Coastguard Worker             Tiling::choose(
166*61046927SAndroid Build Coastguard Worker                 info.extent_px,
167*61046927SAndroid Build Coastguard Worker                 info.format,
168*61046927SAndroid Build Coastguard Worker                 sample_layout,
169*61046927SAndroid Build Coastguard Worker                 info.usage,
170*61046927SAndroid Build Coastguard Worker             )
171*61046927SAndroid Build Coastguard Worker         };
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker         let mut image = Self {
174*61046927SAndroid Build Coastguard Worker             dim: info.dim,
175*61046927SAndroid Build Coastguard Worker             format: info.format,
176*61046927SAndroid Build Coastguard Worker             extent_px: info.extent_px,
177*61046927SAndroid Build Coastguard Worker             sample_layout,
178*61046927SAndroid Build Coastguard Worker             num_levels: info.levels,
179*61046927SAndroid Build Coastguard Worker             levels: [ImageLevel::default(); MAX_LEVELS as usize],
180*61046927SAndroid Build Coastguard Worker             array_stride_B: 0,
181*61046927SAndroid Build Coastguard Worker             align_B: 0,
182*61046927SAndroid Build Coastguard Worker             size_B: 0,
183*61046927SAndroid Build Coastguard Worker             compressed: false,
184*61046927SAndroid Build Coastguard Worker             tile_mode: 0,
185*61046927SAndroid Build Coastguard Worker             pte_kind: 0,
186*61046927SAndroid Build Coastguard Worker             mip_tail_first_lod: 0,
187*61046927SAndroid Build Coastguard Worker         };
188*61046927SAndroid Build Coastguard Worker 
189*61046927SAndroid Build Coastguard Worker         if (info.usage & IMAGE_USAGE_SPARSE_RESIDENCY_BIT) != 0 {
190*61046927SAndroid Build Coastguard Worker             image.mip_tail_first_lod = info.levels;
191*61046927SAndroid Build Coastguard Worker         }
192*61046927SAndroid Build Coastguard Worker 
193*61046927SAndroid Build Coastguard Worker         let mut layer_size_B = 0;
194*61046927SAndroid Build Coastguard Worker         for level in 0..info.levels {
195*61046927SAndroid Build Coastguard Worker             let mut lvl_ext_B = image.level_extent_B(level);
196*61046927SAndroid Build Coastguard Worker 
197*61046927SAndroid Build Coastguard Worker             // NVIDIA images are layed out as an array of 1/2/3D images, each of
198*61046927SAndroid Build Coastguard Worker             // which may have multiple miplevels.  For the purposes of computing
199*61046927SAndroid Build Coastguard Worker             // the size of a miplevel, we don't care about arrays.
200*61046927SAndroid Build Coastguard Worker             lvl_ext_B.array_len = 1;
201*61046927SAndroid Build Coastguard Worker 
202*61046927SAndroid Build Coastguard Worker             if tiling.is_tiled {
203*61046927SAndroid Build Coastguard Worker                 let lvl_tiling = tiling.clamp(lvl_ext_B);
204*61046927SAndroid Build Coastguard Worker 
205*61046927SAndroid Build Coastguard Worker                 if tiling != lvl_tiling {
206*61046927SAndroid Build Coastguard Worker                     image.mip_tail_first_lod =
207*61046927SAndroid Build Coastguard Worker                         std::cmp::min(image.mip_tail_first_lod, level);
208*61046927SAndroid Build Coastguard Worker                 }
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker                 // Align the size to tiles
211*61046927SAndroid Build Coastguard Worker                 let lvl_tiling_ext_B = lvl_tiling.extent_B();
212*61046927SAndroid Build Coastguard Worker                 lvl_ext_B = lvl_ext_B.align(&lvl_tiling_ext_B);
213*61046927SAndroid Build Coastguard Worker                 assert!(
214*61046927SAndroid Build Coastguard Worker                     info.explicit_row_stride_B == 0
215*61046927SAndroid Build Coastguard Worker                         || info.explicit_row_stride_B == lvl_ext_B.width
216*61046927SAndroid Build Coastguard Worker                 );
217*61046927SAndroid Build Coastguard Worker 
218*61046927SAndroid Build Coastguard Worker                 image.levels[level as usize] = ImageLevel {
219*61046927SAndroid Build Coastguard Worker                     offset_B: layer_size_B,
220*61046927SAndroid Build Coastguard Worker                     tiling: lvl_tiling,
221*61046927SAndroid Build Coastguard Worker                     row_stride_B: lvl_ext_B.width,
222*61046927SAndroid Build Coastguard Worker                 };
223*61046927SAndroid Build Coastguard Worker 
224*61046927SAndroid Build Coastguard Worker                 layer_size_B += lvl_ext_B.size_B();
225*61046927SAndroid Build Coastguard Worker             } else {
226*61046927SAndroid Build Coastguard Worker                 // Linear images need to be 2D
227*61046927SAndroid Build Coastguard Worker                 assert!(image.dim == ImageDim::_2D);
228*61046927SAndroid Build Coastguard Worker                 // Linear images can't be arrays
229*61046927SAndroid Build Coastguard Worker                 assert!(image.extent_px.array_len == 1);
230*61046927SAndroid Build Coastguard Worker                 // NVIDIA can't do linear and mipmapping
231*61046927SAndroid Build Coastguard Worker                 assert!(image.num_levels == 1);
232*61046927SAndroid Build Coastguard Worker                 // NVIDIA can't do linear and multisampling
233*61046927SAndroid Build Coastguard Worker                 assert!(image.sample_layout == SampleLayout::_1x1);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker                 let row_stride_B = if info.explicit_row_stride_B > 0 {
236*61046927SAndroid Build Coastguard Worker                     assert!(info.modifier == DRM_FORMAT_MOD_LINEAR);
237*61046927SAndroid Build Coastguard Worker                     assert!(info.explicit_row_stride_B % 128 == 0);
238*61046927SAndroid Build Coastguard Worker                     info.explicit_row_stride_B
239*61046927SAndroid Build Coastguard Worker                 } else {
240*61046927SAndroid Build Coastguard Worker                     // Row stride needs to be aligned to 128B for render to work
241*61046927SAndroid Build Coastguard Worker                     lvl_ext_B.width.next_multiple_of(128)
242*61046927SAndroid Build Coastguard Worker                 };
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker                 image.levels[level as usize] = ImageLevel {
245*61046927SAndroid Build Coastguard Worker                     offset_B: layer_size_B,
246*61046927SAndroid Build Coastguard Worker                     tiling,
247*61046927SAndroid Build Coastguard Worker                     row_stride_B,
248*61046927SAndroid Build Coastguard Worker                 };
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker                 layer_size_B +=
251*61046927SAndroid Build Coastguard Worker                     u64::from(row_stride_B) * u64::from(lvl_ext_B.height);
252*61046927SAndroid Build Coastguard Worker             }
253*61046927SAndroid Build Coastguard Worker         }
254*61046927SAndroid Build Coastguard Worker 
255*61046927SAndroid Build Coastguard Worker         // We use the tiling for level 0 instead of the tiling selected above
256*61046927SAndroid Build Coastguard Worker         // because, in the case of sparse residency with small images, level 0 may
257*61046927SAndroid Build Coastguard Worker         // have a smaller tiling than what we tried to use. However, the level 0
258*61046927SAndroid Build Coastguard Worker         // tiling is the one we program in the hardware so that's the one we need
259*61046927SAndroid Build Coastguard Worker         // to use for array stride calculations and the like.
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker         let lvl0_tiling_size_B = image.levels[0].tiling.size_B();
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker         // The array stride has to be aligned to the size of a level 0 tile
264*61046927SAndroid Build Coastguard Worker         image.array_stride_B =
265*61046927SAndroid Build Coastguard Worker             layer_size_B.next_multiple_of(lvl0_tiling_size_B.into());
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker         image.size_B =
268*61046927SAndroid Build Coastguard Worker             image.array_stride_B * u64::from(image.extent_px.array_len);
269*61046927SAndroid Build Coastguard Worker         image.align_B = lvl0_tiling_size_B;
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker         // If the client requested sparse residency, we need a 64K alignment
272*61046927SAndroid Build Coastguard Worker         // or else sparse binding may fail.  This is true regardless of
273*61046927SAndroid Build Coastguard Worker         // whether or not we actually select a 64K tile format.
274*61046927SAndroid Build Coastguard Worker         if (info.usage & IMAGE_USAGE_SPARSE_RESIDENCY_BIT) != 0 {
275*61046927SAndroid Build Coastguard Worker             image.align_B = std::cmp::max(image.align_B, 1 << 16);
276*61046927SAndroid Build Coastguard Worker         }
277*61046927SAndroid Build Coastguard Worker 
278*61046927SAndroid Build Coastguard Worker         if image.levels[0].tiling.is_tiled {
279*61046927SAndroid Build Coastguard Worker             image.pte_kind = Self::choose_pte_kind(
280*61046927SAndroid Build Coastguard Worker                 dev,
281*61046927SAndroid Build Coastguard Worker                 info.format,
282*61046927SAndroid Build Coastguard Worker                 info.samples,
283*61046927SAndroid Build Coastguard Worker                 image.compressed,
284*61046927SAndroid Build Coastguard Worker             );
285*61046927SAndroid Build Coastguard Worker 
286*61046927SAndroid Build Coastguard Worker             if info.modifier != DRM_FORMAT_MOD_INVALID {
287*61046927SAndroid Build Coastguard Worker                 let bl_mod =
288*61046927SAndroid Build Coastguard Worker                     BlockLinearModifier::try_from(info.modifier).unwrap();
289*61046927SAndroid Build Coastguard Worker                 assert!(bl_mod.pte_kind() == image.pte_kind);
290*61046927SAndroid Build Coastguard Worker             }
291*61046927SAndroid Build Coastguard Worker         }
292*61046927SAndroid Build Coastguard Worker 
293*61046927SAndroid Build Coastguard Worker         if image.levels[0].tiling.is_tiled {
294*61046927SAndroid Build Coastguard Worker             image.tile_mode = u16::from(image.levels[0].tiling.y_log2) << 4
295*61046927SAndroid Build Coastguard Worker                 | u16::from(image.levels[0].tiling.z_log2) << 8;
296*61046927SAndroid Build Coastguard Worker 
297*61046927SAndroid Build Coastguard Worker             image.align_B = std::cmp::max(image.align_B, 4096);
298*61046927SAndroid Build Coastguard Worker             if image.pte_kind >= 0xb && image.pte_kind <= 0xe {
299*61046927SAndroid Build Coastguard Worker                 image.align_B = std::cmp::max(image.align_B, 1 << 16);
300*61046927SAndroid Build Coastguard Worker             }
301*61046927SAndroid Build Coastguard Worker         } else {
302*61046927SAndroid Build Coastguard Worker             // Linear images need to be aligned to 128B for render to work
303*61046927SAndroid Build Coastguard Worker             image.align_B = std::cmp::max(image.align_B, 128);
304*61046927SAndroid Build Coastguard Worker         }
305*61046927SAndroid Build Coastguard Worker 
306*61046927SAndroid Build Coastguard Worker         image.size_B = image.size_B.next_multiple_of(image.align_B.into());
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker         image
309*61046927SAndroid Build Coastguard Worker     }
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker     /// The size in bytes of an extent at a given level.
level_extent_B(&self, level: u32) -> Extent4D<units::Bytes>312*61046927SAndroid Build Coastguard Worker     fn level_extent_B(&self, level: u32) -> Extent4D<units::Bytes> {
313*61046927SAndroid Build Coastguard Worker         self.level_extent_px(level)
314*61046927SAndroid Build Coastguard Worker             .to_B(self.format, self.sample_layout)
315*61046927SAndroid Build Coastguard Worker     }
316*61046927SAndroid Build Coastguard Worker 
317*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_extent_px( &self, level: u32, ) -> Extent4D<units::Pixels>318*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_extent_px(
319*61046927SAndroid Build Coastguard Worker         &self,
320*61046927SAndroid Build Coastguard Worker         level: u32,
321*61046927SAndroid Build Coastguard Worker     ) -> Extent4D<units::Pixels> {
322*61046927SAndroid Build Coastguard Worker         self.level_extent_px(level)
323*61046927SAndroid Build Coastguard Worker     }
324*61046927SAndroid Build Coastguard Worker 
level_extent_px(&self, level: u32) -> Extent4D<units::Pixels>325*61046927SAndroid Build Coastguard Worker     pub fn level_extent_px(&self, level: u32) -> Extent4D<units::Pixels> {
326*61046927SAndroid Build Coastguard Worker         assert!(level == 0 || self.sample_layout == SampleLayout::_1x1);
327*61046927SAndroid Build Coastguard Worker         self.extent_px.minify(level)
328*61046927SAndroid Build Coastguard Worker     }
329*61046927SAndroid Build Coastguard Worker 
330*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_layer_offset_B( &self, level: u32, layer: u32, ) -> u64331*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_layer_offset_B(
332*61046927SAndroid Build Coastguard Worker         &self,
333*61046927SAndroid Build Coastguard Worker         level: u32,
334*61046927SAndroid Build Coastguard Worker         layer: u32,
335*61046927SAndroid Build Coastguard Worker     ) -> u64 {
336*61046927SAndroid Build Coastguard Worker         self.level_layer_offset_B(level, layer)
337*61046927SAndroid Build Coastguard Worker     }
338*61046927SAndroid Build Coastguard Worker 
level_layer_offset_B(&self, level: u32, layer: u32) -> u64339*61046927SAndroid Build Coastguard Worker     pub fn level_layer_offset_B(&self, level: u32, layer: u32) -> u64 {
340*61046927SAndroid Build Coastguard Worker         assert!(level < self.num_levels);
341*61046927SAndroid Build Coastguard Worker         assert!(layer < self.extent_px.array_len);
342*61046927SAndroid Build Coastguard Worker         self.levels[level as usize].offset_B
343*61046927SAndroid Build Coastguard Worker             + u64::from(layer) * self.array_stride_B
344*61046927SAndroid Build Coastguard Worker     }
345*61046927SAndroid Build Coastguard Worker 
346*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_mip_tail_offset_B(&self) -> u64347*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_mip_tail_offset_B(&self) -> u64 {
348*61046927SAndroid Build Coastguard Worker         self.mip_tail_offset_B()
349*61046927SAndroid Build Coastguard Worker     }
350*61046927SAndroid Build Coastguard Worker 
mip_tail_offset_B(&self) -> u64351*61046927SAndroid Build Coastguard Worker     pub fn mip_tail_offset_B(&self) -> u64 {
352*61046927SAndroid Build Coastguard Worker         assert!(self.mip_tail_first_lod > 0);
353*61046927SAndroid Build Coastguard Worker         self.levels[self.mip_tail_first_lod as usize].offset_B
354*61046927SAndroid Build Coastguard Worker     }
355*61046927SAndroid Build Coastguard Worker 
356*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_mip_tail_size_B(&self) -> u32357*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_mip_tail_size_B(&self) -> u32 {
358*61046927SAndroid Build Coastguard Worker         self.mip_tail_size_B()
359*61046927SAndroid Build Coastguard Worker     }
360*61046927SAndroid Build Coastguard Worker 
mip_tail_size_B(&self) -> u32361*61046927SAndroid Build Coastguard Worker     pub fn mip_tail_size_B(&self) -> u32 {
362*61046927SAndroid Build Coastguard Worker         (self.array_stride_B - self.mip_tail_offset_B())
363*61046927SAndroid Build Coastguard Worker             .try_into()
364*61046927SAndroid Build Coastguard Worker             .unwrap()
365*61046927SAndroid Build Coastguard Worker     }
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_extent_sa( &self, level: u32, ) -> Extent4D<units::Samples>368*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_extent_sa(
369*61046927SAndroid Build Coastguard Worker         &self,
370*61046927SAndroid Build Coastguard Worker         level: u32,
371*61046927SAndroid Build Coastguard Worker     ) -> Extent4D<units::Samples> {
372*61046927SAndroid Build Coastguard Worker         self.level_extent_sa(level)
373*61046927SAndroid Build Coastguard Worker     }
374*61046927SAndroid Build Coastguard Worker 
level_extent_sa(&self, level: u32) -> Extent4D<units::Samples>375*61046927SAndroid Build Coastguard Worker     pub fn level_extent_sa(&self, level: u32) -> Extent4D<units::Samples> {
376*61046927SAndroid Build Coastguard Worker         self.level_extent_px(level).to_sa(self.sample_layout)
377*61046927SAndroid Build Coastguard Worker     }
378*61046927SAndroid Build Coastguard Worker 
379*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_size_B(&self, level: u32) -> u64380*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_size_B(&self, level: u32) -> u64 {
381*61046927SAndroid Build Coastguard Worker         self.level_size_B(level)
382*61046927SAndroid Build Coastguard Worker     }
383*61046927SAndroid Build Coastguard Worker 
level_size_B(&self, level: u32) -> u64384*61046927SAndroid Build Coastguard Worker     pub fn level_size_B(&self, level: u32) -> u64 {
385*61046927SAndroid Build Coastguard Worker         assert!(level < self.num_levels);
386*61046927SAndroid Build Coastguard Worker         let lvl_ext_B = self.level_extent_B(level);
387*61046927SAndroid Build Coastguard Worker         let level = &self.levels[level as usize];
388*61046927SAndroid Build Coastguard Worker 
389*61046927SAndroid Build Coastguard Worker         if level.tiling.is_tiled {
390*61046927SAndroid Build Coastguard Worker             let lvl_tiling_ext_B = level.tiling.extent_B();
391*61046927SAndroid Build Coastguard Worker             let mut lvl_ext_B = lvl_ext_B.align(&lvl_tiling_ext_B);
392*61046927SAndroid Build Coastguard Worker 
393*61046927SAndroid Build Coastguard Worker             let array_len = lvl_ext_B.array_len;
394*61046927SAndroid Build Coastguard Worker             lvl_ext_B.array_len = 1;
395*61046927SAndroid Build Coastguard Worker 
396*61046927SAndroid Build Coastguard Worker             self.array_stride_B * u64::from(array_len - 1) + lvl_ext_B.size_B()
397*61046927SAndroid Build Coastguard Worker         } else {
398*61046927SAndroid Build Coastguard Worker             assert!(lvl_ext_B.depth == 1);
399*61046927SAndroid Build Coastguard Worker             assert!(lvl_ext_B.array_len == 1);
400*61046927SAndroid Build Coastguard Worker             u64::from(level.row_stride_B) * u64::from(lvl_ext_B.height - 1)
401*61046927SAndroid Build Coastguard Worker                 + u64::from(lvl_ext_B.width)
402*61046927SAndroid Build Coastguard Worker         }
403*61046927SAndroid Build Coastguard Worker     }
404*61046927SAndroid Build Coastguard Worker 
405*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_depth_stride_B(&self, level: u32) -> u64406*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_depth_stride_B(&self, level: u32) -> u64 {
407*61046927SAndroid Build Coastguard Worker         self.level_depth_stride_B(level)
408*61046927SAndroid Build Coastguard Worker     }
409*61046927SAndroid Build Coastguard Worker 
level_depth_stride_B(&self, level: u32) -> u64410*61046927SAndroid Build Coastguard Worker     pub fn level_depth_stride_B(&self, level: u32) -> u64 {
411*61046927SAndroid Build Coastguard Worker         assert!(level < self.num_levels);
412*61046927SAndroid Build Coastguard Worker 
413*61046927SAndroid Build Coastguard Worker         let lvl_ext_B = self.level_extent_B(level);
414*61046927SAndroid Build Coastguard Worker         let level = &self.levels[level as usize];
415*61046927SAndroid Build Coastguard Worker         let lvl_tiling_ext_B = level.tiling.extent_B();
416*61046927SAndroid Build Coastguard Worker         let lvl_ext_B = lvl_ext_B.align(&lvl_tiling_ext_B);
417*61046927SAndroid Build Coastguard Worker 
418*61046927SAndroid Build Coastguard Worker         (lvl_ext_B.width * lvl_ext_B.height).into()
419*61046927SAndroid Build Coastguard Worker     }
420*61046927SAndroid Build Coastguard Worker 
421*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_for_level( &self, level: u32, offset_in_bytes_out: &mut u64, ) -> Self422*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_for_level(
423*61046927SAndroid Build Coastguard Worker         &self,
424*61046927SAndroid Build Coastguard Worker         level: u32,
425*61046927SAndroid Build Coastguard Worker         offset_in_bytes_out: &mut u64,
426*61046927SAndroid Build Coastguard Worker     ) -> Self {
427*61046927SAndroid Build Coastguard Worker         self.image_for_level(level, offset_in_bytes_out)
428*61046927SAndroid Build Coastguard Worker     }
429*61046927SAndroid Build Coastguard Worker 
image_for_level( &self, level: u32, offset_in_bytes_out: &mut u64, ) -> Self430*61046927SAndroid Build Coastguard Worker     pub fn image_for_level(
431*61046927SAndroid Build Coastguard Worker         &self,
432*61046927SAndroid Build Coastguard Worker         level: u32,
433*61046927SAndroid Build Coastguard Worker         offset_in_bytes_out: &mut u64,
434*61046927SAndroid Build Coastguard Worker     ) -> Self {
435*61046927SAndroid Build Coastguard Worker         assert!(level < self.num_levels);
436*61046927SAndroid Build Coastguard Worker         let lvl_extent_px = self.level_extent_px(level);
437*61046927SAndroid Build Coastguard Worker         let lvl = self.levels[level as usize];
438*61046927SAndroid Build Coastguard Worker         let align_B = lvl.tiling.size_B();
439*61046927SAndroid Build Coastguard Worker 
440*61046927SAndroid Build Coastguard Worker         let mut size_B = self.size_B - lvl.offset_B;
441*61046927SAndroid Build Coastguard Worker         if (level + 1) < self.num_levels {
442*61046927SAndroid Build Coastguard Worker             // This assumes levels are sequential, tightly packed and that each
443*61046927SAndroid Build Coastguard Worker             // level has a higher alignment than the next one. All of this is
444*61046927SAndroid Build Coastguard Worker             // currently true.
445*61046927SAndroid Build Coastguard Worker             let next_lvl_offset_in_bytes =
446*61046927SAndroid Build Coastguard Worker                 self.levels[level as usize + 1].offset_B;
447*61046927SAndroid Build Coastguard Worker             assert!(next_lvl_offset_in_bytes > lvl.offset_B);
448*61046927SAndroid Build Coastguard Worker             size_B -= next_lvl_offset_in_bytes - lvl.offset_B;
449*61046927SAndroid Build Coastguard Worker         }
450*61046927SAndroid Build Coastguard Worker 
451*61046927SAndroid Build Coastguard Worker         let mut levels: [ImageLevel; MAX_LEVELS as usize] = Default::default();
452*61046927SAndroid Build Coastguard Worker         levels[0] = lvl;
453*61046927SAndroid Build Coastguard Worker 
454*61046927SAndroid Build Coastguard Worker         *offset_in_bytes_out = lvl.offset_B;
455*61046927SAndroid Build Coastguard Worker         levels[0].offset_B = 0;
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker         Self {
458*61046927SAndroid Build Coastguard Worker             extent_px: lvl_extent_px,
459*61046927SAndroid Build Coastguard Worker             num_levels: 1,
460*61046927SAndroid Build Coastguard Worker             levels,
461*61046927SAndroid Build Coastguard Worker             align_B,
462*61046927SAndroid Build Coastguard Worker             size_B,
463*61046927SAndroid Build Coastguard Worker             mip_tail_first_lod: if level < self.mip_tail_first_lod {
464*61046927SAndroid Build Coastguard Worker                 1
465*61046927SAndroid Build Coastguard Worker             } else {
466*61046927SAndroid Build Coastguard Worker                 0
467*61046927SAndroid Build Coastguard Worker             },
468*61046927SAndroid Build Coastguard Worker             ..*self
469*61046927SAndroid Build Coastguard Worker         }
470*61046927SAndroid Build Coastguard Worker     }
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_as_uncompressed( &self, level: u32, offset_in_bytes_out: &mut u64, ) -> Self473*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_as_uncompressed(
474*61046927SAndroid Build Coastguard Worker         &self,
475*61046927SAndroid Build Coastguard Worker         level: u32,
476*61046927SAndroid Build Coastguard Worker         offset_in_bytes_out: &mut u64,
477*61046927SAndroid Build Coastguard Worker     ) -> Self {
478*61046927SAndroid Build Coastguard Worker         self.level_as_uncompressed(level, offset_in_bytes_out)
479*61046927SAndroid Build Coastguard Worker     }
480*61046927SAndroid Build Coastguard Worker 
level_as_uncompressed( &self, level: u32, offset_in_bytes_out: &mut u64, ) -> Self481*61046927SAndroid Build Coastguard Worker     pub fn level_as_uncompressed(
482*61046927SAndroid Build Coastguard Worker         &self,
483*61046927SAndroid Build Coastguard Worker         level: u32,
484*61046927SAndroid Build Coastguard Worker         offset_in_bytes_out: &mut u64,
485*61046927SAndroid Build Coastguard Worker     ) -> Self {
486*61046927SAndroid Build Coastguard Worker         assert!(self.sample_layout == SampleLayout::_1x1);
487*61046927SAndroid Build Coastguard Worker 
488*61046927SAndroid Build Coastguard Worker         // Format is arbitrary. Pick one that has the right number of bits.
489*61046927SAndroid Build Coastguard Worker         let uc_format = match self.format.el_size_B() {
490*61046927SAndroid Build Coastguard Worker             4 => PIPE_FORMAT_R32_UINT,
491*61046927SAndroid Build Coastguard Worker             8 => PIPE_FORMAT_R32G32_UINT,
492*61046927SAndroid Build Coastguard Worker             16 => PIPE_FORMAT_R32G32B32A32_UINT,
493*61046927SAndroid Build Coastguard Worker             _ => panic!("No compressed PIPE_FORMAT with this size"),
494*61046927SAndroid Build Coastguard Worker         };
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker         let lvl_image = self.image_for_level(level, offset_in_bytes_out);
497*61046927SAndroid Build Coastguard Worker         let mut image_out = lvl_image.clone();
498*61046927SAndroid Build Coastguard Worker 
499*61046927SAndroid Build Coastguard Worker         image_out.format = uc_format.try_into().unwrap();
500*61046927SAndroid Build Coastguard Worker         image_out.extent_px = lvl_image
501*61046927SAndroid Build Coastguard Worker             .extent_px
502*61046927SAndroid Build Coastguard Worker             .to_el(lvl_image.format, lvl_image.sample_layout)
503*61046927SAndroid Build Coastguard Worker             .cast_units();
504*61046927SAndroid Build Coastguard Worker 
505*61046927SAndroid Build Coastguard Worker         image_out
506*61046927SAndroid Build Coastguard Worker     }
507*61046927SAndroid Build Coastguard Worker 
508*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_3d_level_as_2d_array( &self, level: u32, offset_in_bytes_out: &mut u64, ) -> Self509*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_3d_level_as_2d_array(
510*61046927SAndroid Build Coastguard Worker         &self,
511*61046927SAndroid Build Coastguard Worker         level: u32,
512*61046927SAndroid Build Coastguard Worker         offset_in_bytes_out: &mut u64,
513*61046927SAndroid Build Coastguard Worker     ) -> Self {
514*61046927SAndroid Build Coastguard Worker         self._3d_level_as_2d_array(level, offset_in_bytes_out)
515*61046927SAndroid Build Coastguard Worker     }
516*61046927SAndroid Build Coastguard Worker 
_3d_level_as_2d_array( &self, level: u32, offset_in_bytes_out: &mut u64, ) -> Self517*61046927SAndroid Build Coastguard Worker     pub fn _3d_level_as_2d_array(
518*61046927SAndroid Build Coastguard Worker         &self,
519*61046927SAndroid Build Coastguard Worker         level: u32,
520*61046927SAndroid Build Coastguard Worker         offset_in_bytes_out: &mut u64,
521*61046927SAndroid Build Coastguard Worker     ) -> Self {
522*61046927SAndroid Build Coastguard Worker         assert!(self.dim == ImageDim::_3D);
523*61046927SAndroid Build Coastguard Worker         assert!(self.extent_px.array_len == 1);
524*61046927SAndroid Build Coastguard Worker         assert!(self.sample_layout == SampleLayout::_1x1);
525*61046927SAndroid Build Coastguard Worker 
526*61046927SAndroid Build Coastguard Worker         let mut image_2d_out = self.image_for_level(level, offset_in_bytes_out);
527*61046927SAndroid Build Coastguard Worker         let lvl0 = &image_2d_out.levels[0];
528*61046927SAndroid Build Coastguard Worker 
529*61046927SAndroid Build Coastguard Worker         assert!(image_2d_out.num_levels == 1);
530*61046927SAndroid Build Coastguard Worker         assert!(!lvl0.tiling.is_tiled || lvl0.tiling.z_log2 == 0);
531*61046927SAndroid Build Coastguard Worker 
532*61046927SAndroid Build Coastguard Worker         let lvl_tiling_ext_B = lvl0.tiling.extent_B();
533*61046927SAndroid Build Coastguard Worker         let lvl_ext_B = image_2d_out.level_extent_B(0);
534*61046927SAndroid Build Coastguard Worker         let lvl_ext_B = lvl_ext_B.align(&lvl_tiling_ext_B);
535*61046927SAndroid Build Coastguard Worker         let z_stride = u64::from(lvl_ext_B.width * lvl_ext_B.height);
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker         image_2d_out.dim = ImageDim::_2D;
538*61046927SAndroid Build Coastguard Worker         image_2d_out.extent_px.array_len = image_2d_out.extent_px.depth;
539*61046927SAndroid Build Coastguard Worker         image_2d_out.extent_px.depth = 1;
540*61046927SAndroid Build Coastguard Worker         image_2d_out.array_stride_B = z_stride;
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker         image_2d_out
543*61046927SAndroid Build Coastguard Worker     }
544*61046927SAndroid Build Coastguard Worker 
choose_pte_kind( dev: &nil_rs_bindings::nv_device_info, format: Format, samples: u32, compressed: bool, ) -> u8545*61046927SAndroid Build Coastguard Worker     pub fn choose_pte_kind(
546*61046927SAndroid Build Coastguard Worker         dev: &nil_rs_bindings::nv_device_info,
547*61046927SAndroid Build Coastguard Worker         format: Format,
548*61046927SAndroid Build Coastguard Worker         samples: u32,
549*61046927SAndroid Build Coastguard Worker         compressed: bool,
550*61046927SAndroid Build Coastguard Worker     ) -> u8 {
551*61046927SAndroid Build Coastguard Worker         if dev.cls_eng3d >= clc597::TURING_A {
552*61046927SAndroid Build Coastguard Worker             Self::tu102_choose_pte_kind(format, compressed)
553*61046927SAndroid Build Coastguard Worker         } else if dev.cls_eng3d >= cl9097::FERMI_A {
554*61046927SAndroid Build Coastguard Worker             Self::nvc0_choose_pte_kind(format, samples, compressed)
555*61046927SAndroid Build Coastguard Worker         } else {
556*61046927SAndroid Build Coastguard Worker             panic!("Unsupported 3d engine class")
557*61046927SAndroid Build Coastguard Worker         }
558*61046927SAndroid Build Coastguard Worker     }
559*61046927SAndroid Build Coastguard Worker 
tu102_choose_pte_kind(format: Format, compressed: bool) -> u8560*61046927SAndroid Build Coastguard Worker     fn tu102_choose_pte_kind(format: Format, compressed: bool) -> u8 {
561*61046927SAndroid Build Coastguard Worker         use nvidia_headers::hwref::tu102::mmu::*;
562*61046927SAndroid Build Coastguard Worker         match pipe_format::from(format) {
563*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_Z16_UNORM => {
564*61046927SAndroid Build Coastguard Worker                 if compressed {
565*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z16_COMPRESSIBLE_DISABLE_PLC
566*61046927SAndroid Build Coastguard Worker                 } else {
567*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z16
568*61046927SAndroid Build Coastguard Worker                 }
569*61046927SAndroid Build Coastguard Worker             }
570*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_X8Z24_UNORM
571*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_S8X24_UINT
572*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_S8_UINT_Z24_UNORM => {
573*61046927SAndroid Build Coastguard Worker                 if compressed {
574*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z24S8_COMPRESSIBLE_DISABLE_PLC
575*61046927SAndroid Build Coastguard Worker                 } else {
576*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z24S8
577*61046927SAndroid Build Coastguard Worker                 }
578*61046927SAndroid Build Coastguard Worker             }
579*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_X24S8_UINT
580*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_Z24X8_UNORM
581*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_Z24_UNORM_S8_UINT => {
582*61046927SAndroid Build Coastguard Worker                 if compressed {
583*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_S8Z24_COMPRESSIBLE_DISABLE_PLC
584*61046927SAndroid Build Coastguard Worker                 } else {
585*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_S8Z24
586*61046927SAndroid Build Coastguard Worker                 }
587*61046927SAndroid Build Coastguard Worker             }
588*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_X32_S8X24_UINT | PIPE_FORMAT_Z32_FLOAT_S8X24_UINT => {
589*61046927SAndroid Build Coastguard Worker                 if compressed {
590*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_ZF32_X24S8_COMPRESSIBLE_DISABLE_PLC
591*61046927SAndroid Build Coastguard Worker                 } else {
592*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_ZF32_X24S8
593*61046927SAndroid Build Coastguard Worker                 }
594*61046927SAndroid Build Coastguard Worker             }
595*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_Z32_FLOAT => NV_MMU_PTE_KIND_GENERIC_MEMORY,
596*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_S8_UINT => {
597*61046927SAndroid Build Coastguard Worker                 if compressed {
598*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_S8_COMPRESSIBLE_DISABLE_PLC
599*61046927SAndroid Build Coastguard Worker                 } else {
600*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_S8
601*61046927SAndroid Build Coastguard Worker                 }
602*61046927SAndroid Build Coastguard Worker             }
603*61046927SAndroid Build Coastguard Worker             _ => NV_MMU_PTE_KIND_GENERIC_MEMORY,
604*61046927SAndroid Build Coastguard Worker         }
605*61046927SAndroid Build Coastguard Worker         .try_into()
606*61046927SAndroid Build Coastguard Worker         .unwrap()
607*61046927SAndroid Build Coastguard Worker     }
608*61046927SAndroid Build Coastguard Worker 
nvc0_choose_pte_kind( format: Format, samples: u32, compressed: bool, ) -> u8609*61046927SAndroid Build Coastguard Worker     fn nvc0_choose_pte_kind(
610*61046927SAndroid Build Coastguard Worker         format: Format,
611*61046927SAndroid Build Coastguard Worker         samples: u32,
612*61046927SAndroid Build Coastguard Worker         compressed: bool,
613*61046927SAndroid Build Coastguard Worker     ) -> u8 {
614*61046927SAndroid Build Coastguard Worker         use nvidia_headers::hwref::gp100::mmu::*;
615*61046927SAndroid Build Coastguard Worker         let ms = samples.ilog2();
616*61046927SAndroid Build Coastguard Worker         match pipe_format::from(format) {
617*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_Z16_UNORM => {
618*61046927SAndroid Build Coastguard Worker                 if compressed {
619*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z16_2C + ms
620*61046927SAndroid Build Coastguard Worker                 } else {
621*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z16
622*61046927SAndroid Build Coastguard Worker                 }
623*61046927SAndroid Build Coastguard Worker             }
624*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_X8Z24_UNORM
625*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_S8X24_UINT
626*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_S8_UINT_Z24_UNORM => {
627*61046927SAndroid Build Coastguard Worker                 if compressed {
628*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z24S8_2CZ + ms
629*61046927SAndroid Build Coastguard Worker                 } else {
630*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_Z24S8
631*61046927SAndroid Build Coastguard Worker                 }
632*61046927SAndroid Build Coastguard Worker             }
633*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_X24S8_UINT
634*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_Z24X8_UNORM
635*61046927SAndroid Build Coastguard Worker             | PIPE_FORMAT_Z24_UNORM_S8_UINT => {
636*61046927SAndroid Build Coastguard Worker                 if compressed {
637*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_S8Z24_2CZ + ms
638*61046927SAndroid Build Coastguard Worker                 } else {
639*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_S8Z24
640*61046927SAndroid Build Coastguard Worker                 }
641*61046927SAndroid Build Coastguard Worker             }
642*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_Z32_FLOAT => {
643*61046927SAndroid Build Coastguard Worker                 if compressed {
644*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_ZF32_2CZ + ms
645*61046927SAndroid Build Coastguard Worker                 } else {
646*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_ZF32
647*61046927SAndroid Build Coastguard Worker                 }
648*61046927SAndroid Build Coastguard Worker             }
649*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_X32_S8X24_UINT | PIPE_FORMAT_Z32_FLOAT_S8X24_UINT => {
650*61046927SAndroid Build Coastguard Worker                 if compressed {
651*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_ZF32_X24S8_2CSZV + ms
652*61046927SAndroid Build Coastguard Worker                 } else {
653*61046927SAndroid Build Coastguard Worker                     NV_MMU_PTE_KIND_ZF32_X24S8
654*61046927SAndroid Build Coastguard Worker                 }
655*61046927SAndroid Build Coastguard Worker             }
656*61046927SAndroid Build Coastguard Worker             PIPE_FORMAT_S8_UINT => NV_MMU_PTE_KIND_S8,
657*61046927SAndroid Build Coastguard Worker             _ => {
658*61046927SAndroid Build Coastguard Worker                 let blocksize_bits = format.el_size_B() * 8;
659*61046927SAndroid Build Coastguard Worker                 match blocksize_bits {
660*61046927SAndroid Build Coastguard Worker                     128 => {
661*61046927SAndroid Build Coastguard Worker                         if compressed {
662*61046927SAndroid Build Coastguard Worker                             match samples {
663*61046927SAndroid Build Coastguard Worker                                 1 => NV_MMU_PTE_KIND_C128_2C,
664*61046927SAndroid Build Coastguard Worker                                 2 => NV_MMU_PTE_KIND_C128_MS2_2C,
665*61046927SAndroid Build Coastguard Worker                                 4 => NV_MMU_PTE_KIND_C128_MS4_2C,
666*61046927SAndroid Build Coastguard Worker                                 8 | 16 => NV_MMU_PTE_KIND_C128_MS8_MS16_2C,
667*61046927SAndroid Build Coastguard Worker                                 _ => panic!("Unsupported sample count"),
668*61046927SAndroid Build Coastguard Worker                             }
669*61046927SAndroid Build Coastguard Worker                         } else {
670*61046927SAndroid Build Coastguard Worker                             NV_MMU_PTE_KIND_GENERIC_16BX2
671*61046927SAndroid Build Coastguard Worker                         }
672*61046927SAndroid Build Coastguard Worker                     }
673*61046927SAndroid Build Coastguard Worker                     64 => {
674*61046927SAndroid Build Coastguard Worker                         if compressed {
675*61046927SAndroid Build Coastguard Worker                             match samples {
676*61046927SAndroid Build Coastguard Worker                                 1 => NV_MMU_PTE_KIND_C64_2C,
677*61046927SAndroid Build Coastguard Worker                                 2 => NV_MMU_PTE_KIND_C64_MS2_2C,
678*61046927SAndroid Build Coastguard Worker                                 4 => NV_MMU_PTE_KIND_C64_MS4_2C,
679*61046927SAndroid Build Coastguard Worker                                 8 | 16 => NV_MMU_PTE_KIND_C64_MS8_MS16_2C,
680*61046927SAndroid Build Coastguard Worker                                 _ => panic!("Unsupported sample count"),
681*61046927SAndroid Build Coastguard Worker                             }
682*61046927SAndroid Build Coastguard Worker                         } else {
683*61046927SAndroid Build Coastguard Worker                             NV_MMU_PTE_KIND_GENERIC_16BX2
684*61046927SAndroid Build Coastguard Worker                         }
685*61046927SAndroid Build Coastguard Worker                     }
686*61046927SAndroid Build Coastguard Worker                     32 => {
687*61046927SAndroid Build Coastguard Worker                         if compressed {
688*61046927SAndroid Build Coastguard Worker                             match samples {
689*61046927SAndroid Build Coastguard Worker                                 1 => NV_MMU_PTE_KIND_C32_2C,
690*61046927SAndroid Build Coastguard Worker                                 2 => NV_MMU_PTE_KIND_C32_MS2_2C,
691*61046927SAndroid Build Coastguard Worker                                 4 => NV_MMU_PTE_KIND_C32_MS4_2C,
692*61046927SAndroid Build Coastguard Worker                                 8 | 16 => NV_MMU_PTE_KIND_C32_MS8_MS16_2C,
693*61046927SAndroid Build Coastguard Worker                                 _ => panic!("Unsupported sample count"),
694*61046927SAndroid Build Coastguard Worker                             }
695*61046927SAndroid Build Coastguard Worker                         } else {
696*61046927SAndroid Build Coastguard Worker                             NV_MMU_PTE_KIND_GENERIC_16BX2
697*61046927SAndroid Build Coastguard Worker                         }
698*61046927SAndroid Build Coastguard Worker                     }
699*61046927SAndroid Build Coastguard Worker                     16 | 8 => NV_MMU_PTE_KIND_GENERIC_16BX2,
700*61046927SAndroid Build Coastguard Worker                     _ => NV_MMU_PTE_KIND_PITCH,
701*61046927SAndroid Build Coastguard Worker                 }
702*61046927SAndroid Build Coastguard Worker             }
703*61046927SAndroid Build Coastguard Worker         }
704*61046927SAndroid Build Coastguard Worker         .try_into()
705*61046927SAndroid Build Coastguard Worker         .unwrap()
706*61046927SAndroid Build Coastguard Worker     }
707*61046927SAndroid Build Coastguard Worker 
708*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_msaa_image_as_sa(&self) -> Self709*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_msaa_image_as_sa(&self) -> Self {
710*61046927SAndroid Build Coastguard Worker         self.msaa_as_samples()
711*61046927SAndroid Build Coastguard Worker     }
712*61046927SAndroid Build Coastguard Worker 
713*61046927SAndroid Build Coastguard Worker     /// For a multisampled image, returns an image of samples
714*61046927SAndroid Build Coastguard Worker     ///
715*61046927SAndroid Build Coastguard Worker     /// The resulting image is supersampled with each pixel in the original
716*61046927SAndroid Build Coastguard Worker     /// consuming some number pixels in the supersampled images according to the
717*61046927SAndroid Build Coastguard Worker     /// original image's sample layout
msaa_as_samples(&self) -> Self718*61046927SAndroid Build Coastguard Worker     pub fn msaa_as_samples(&self) -> Self {
719*61046927SAndroid Build Coastguard Worker         assert!(self.dim == ImageDim::_2D);
720*61046927SAndroid Build Coastguard Worker         assert!(self.num_levels == 1);
721*61046927SAndroid Build Coastguard Worker 
722*61046927SAndroid Build Coastguard Worker         let extent_sa = self.extent_px.to_sa(self.sample_layout);
723*61046927SAndroid Build Coastguard Worker         let mut out = self.clone();
724*61046927SAndroid Build Coastguard Worker         out.extent_px = extent_sa.cast_units();
725*61046927SAndroid Build Coastguard Worker         out.sample_layout = SampleLayout::_1x1;
726*61046927SAndroid Build Coastguard Worker         out
727*61046927SAndroid Build Coastguard Worker     }
728*61046927SAndroid Build Coastguard Worker 
729*61046927SAndroid Build Coastguard Worker     #[no_mangle]
nil_image_level_z_offset_B( &self, level: u32, z: u32, ) -> u64730*61046927SAndroid Build Coastguard Worker     pub extern "C" fn nil_image_level_z_offset_B(
731*61046927SAndroid Build Coastguard Worker         &self,
732*61046927SAndroid Build Coastguard Worker         level: u32,
733*61046927SAndroid Build Coastguard Worker         z: u32,
734*61046927SAndroid Build Coastguard Worker     ) -> u64 {
735*61046927SAndroid Build Coastguard Worker         self.level_z_offset_B(level, z)
736*61046927SAndroid Build Coastguard Worker     }
737*61046927SAndroid Build Coastguard Worker 
level_z_offset_B(&self, level: u32, z: u32) -> u64738*61046927SAndroid Build Coastguard Worker     pub fn level_z_offset_B(&self, level: u32, z: u32) -> u64 {
739*61046927SAndroid Build Coastguard Worker         assert!(level < self.num_levels);
740*61046927SAndroid Build Coastguard Worker         let lvl_extent_px = self.level_extent_px(level);
741*61046927SAndroid Build Coastguard Worker         assert!(z < lvl_extent_px.depth);
742*61046927SAndroid Build Coastguard Worker 
743*61046927SAndroid Build Coastguard Worker         let lvl_tiling = &self.levels[level as usize].tiling;
744*61046927SAndroid Build Coastguard Worker         let z_tl = z >> lvl_tiling.z_log2;
745*61046927SAndroid Build Coastguard Worker         let z_gob = z & ((1 << lvl_tiling.z_log2) - 1);
746*61046927SAndroid Build Coastguard Worker 
747*61046927SAndroid Build Coastguard Worker         let lvl_extent_tl =
748*61046927SAndroid Build Coastguard Worker             lvl_extent_px.to_tl(lvl_tiling, self.format, self.sample_layout);
749*61046927SAndroid Build Coastguard Worker         let offset_B = u64::from(
750*61046927SAndroid Build Coastguard Worker             lvl_extent_tl.width
751*61046927SAndroid Build Coastguard Worker                 * lvl_extent_tl.height
752*61046927SAndroid Build Coastguard Worker                 * z_tl
753*61046927SAndroid Build Coastguard Worker                 * lvl_tiling.size_B(),
754*61046927SAndroid Build Coastguard Worker         );
755*61046927SAndroid Build Coastguard Worker 
756*61046927SAndroid Build Coastguard Worker         let tiling_extent_B = lvl_tiling.extent_B();
757*61046927SAndroid Build Coastguard Worker         let offset_B = offset_B
758*61046927SAndroid Build Coastguard Worker             + u64::from(tiling_extent_B.width * tiling_extent_B.height * z_gob);
759*61046927SAndroid Build Coastguard Worker         offset_B
760*61046927SAndroid Build Coastguard Worker     }
761*61046927SAndroid Build Coastguard Worker }
762*61046927SAndroid Build Coastguard Worker 
763*61046927SAndroid Build Coastguard Worker #[allow(dead_code)]
764*61046927SAndroid Build Coastguard Worker #[derive(Clone, Debug, Copy, PartialEq)]
765*61046927SAndroid Build Coastguard Worker #[repr(u8)]
766*61046927SAndroid Build Coastguard Worker pub enum ViewType {
767*61046927SAndroid Build Coastguard Worker     _1D,
768*61046927SAndroid Build Coastguard Worker     _2D,
769*61046927SAndroid Build Coastguard Worker     _3D,
770*61046927SAndroid Build Coastguard Worker     _3DSliced,
771*61046927SAndroid Build Coastguard Worker     Cube,
772*61046927SAndroid Build Coastguard Worker     _1DArray,
773*61046927SAndroid Build Coastguard Worker     _2DArray,
774*61046927SAndroid Build Coastguard Worker     CubeArray,
775*61046927SAndroid Build Coastguard Worker }
776*61046927SAndroid Build Coastguard Worker 
777*61046927SAndroid Build Coastguard Worker #[repr(C)]
778*61046927SAndroid Build Coastguard Worker #[derive(Debug, Clone, PartialEq)]
779*61046927SAndroid Build Coastguard Worker pub struct View {
780*61046927SAndroid Build Coastguard Worker     pub view_type: ViewType,
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker     /// The format to use in the view
783*61046927SAndroid Build Coastguard Worker     ///
784*61046927SAndroid Build Coastguard Worker     /// This may differ from the format of the actual isl_surf but must have the
785*61046927SAndroid Build Coastguard Worker     /// same block size.
786*61046927SAndroid Build Coastguard Worker     pub format: Format,
787*61046927SAndroid Build Coastguard Worker 
788*61046927SAndroid Build Coastguard Worker     pub base_level: u32,
789*61046927SAndroid Build Coastguard Worker     pub num_levels: u32,
790*61046927SAndroid Build Coastguard Worker 
791*61046927SAndroid Build Coastguard Worker     /// Base array layer
792*61046927SAndroid Build Coastguard Worker     ///
793*61046927SAndroid Build Coastguard Worker     /// For cube maps, both base_array_layer and array_len should be specified in
794*61046927SAndroid Build Coastguard Worker     /// terms of 2-D layers and must be a multiple of 6.
795*61046927SAndroid Build Coastguard Worker     pub base_array_layer: u32,
796*61046927SAndroid Build Coastguard Worker 
797*61046927SAndroid Build Coastguard Worker     /// Array Length
798*61046927SAndroid Build Coastguard Worker     ///
799*61046927SAndroid Build Coastguard Worker     /// Indicates the number of array elements starting at  Base Array Layer.
800*61046927SAndroid Build Coastguard Worker     pub array_len: u32,
801*61046927SAndroid Build Coastguard Worker 
802*61046927SAndroid Build Coastguard Worker     pub swizzle: [nil_rs_bindings::pipe_swizzle; 4],
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker     // VK_EXT_image_view_min_lod
805*61046927SAndroid Build Coastguard Worker     pub min_lod_clamp: f32,
806*61046927SAndroid Build Coastguard Worker }
807