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