diff --git a/src/nouveau/nil/image.rs b/src/nouveau/nil/image.rs index 0e0b8a0d6fe..d1f4757547b 100644 --- a/src/nouveau/nil/image.rs +++ b/src/nouveau/nil/image.rs @@ -193,6 +193,12 @@ impl Image { let mut layer_size_B = 0; for level in 0..info.levels { let mut lvl_ext_B = image.level_extent_B(level); + + // NVIDIA images are layed out as an array of 1/2/3D images, each of + // which may have multiple miplevels. For the purposes of computing + // the size of a miplevel, we don't care about arrays. + lvl_ext_B.array_len = 1; + if tiling.is_tiled { let lvl_tiling = tiling.clamp(lvl_ext_B); @@ -214,32 +220,36 @@ impl Image { tiling: lvl_tiling, row_stride_B: lvl_ext_B.width, }; + + layer_size_B += lvl_ext_B.size_B(); } else { // Linear images need to be 2D assert!(image.dim == ImageDim::_2D); + // Linear images can't be arrays + assert!(image.extent_px.array_len == 1); // NVIDIA can't do linear and mipmapping assert!(image.num_levels == 1); // NVIDIA can't do linear and multisampling assert!(image.sample_layout == SampleLayout::_1x1); - let row_stride = if info.explicit_row_stride_B > 0 { + let row_stride_B = if info.explicit_row_stride_B > 0 { assert!(info.modifier == DRM_FORMAT_MOD_LINEAR); assert!(info.explicit_row_stride_B % 128 == 0); info.explicit_row_stride_B } else { + // Row stride needs to be aligned to 128B for render to work lvl_ext_B.width.next_multiple_of(128) }; image.levels[level as usize] = ImageLevel { offset_B: layer_size_B, tiling, - // Row stride needs to be aligned to 128B for render to work - row_stride_B: row_stride, + row_stride_B, }; - assert!(lvl_ext_B.depth == 1); + layer_size_B += + u64::from(row_stride_B) * u64::from(lvl_ext_B.height); } - layer_size_B += image.level_size_B(level); } // We use the tiling for level 0 instead of the tiling selected above