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