Build the linear-depth Hi-Z pyramid as `HIZ_MIP_COUNT` separate single-mip textures. One multi-mip texture is cheaper on paper but Metal's per-subresource state tracking trips when wgpu writes one mip and samples another in the same encoder — the bloom chain has the same issue and uses this same layout.
(
device: &wgpu::Device,
width: u32,
height: u32,
)
| 701 | /// writes one mip and samples another in the same encoder — the |
| 702 | /// bloom chain has the same issue and uses this same layout. |
| 703 | pub(super) fn create_linear_depth_hiz_chain( |
| 704 | device: &wgpu::Device, |
| 705 | width: u32, |
| 706 | height: u32, |
| 707 | ) -> (Vec<wgpu::Texture>, Vec<wgpu::TextureView>) { |
| 708 | let mut textures = Vec::with_capacity(HIZ_MIP_COUNT as usize); |
| 709 | let mut views = Vec::with_capacity(HIZ_MIP_COUNT as usize); |
| 710 | for i in 0..HIZ_MIP_COUNT { |
| 711 | let w = ((width / 2) >> i).max(1); |
| 712 | let h = ((height / 2) >> i).max(1); |
| 713 | let tex = device.create_texture(&wgpu::TextureDescriptor { |
| 714 | label: Some("linear_depth_hiz_mip"), |
| 715 | size: wgpu::Extent3d { width: w, height: h, depth_or_array_layers: 1 }, |
| 716 | mip_level_count: 1, |
| 717 | sample_count: 1, |
| 718 | dimension: wgpu::TextureDimension::D2, |
| 719 | format: HIZ_FORMAT, |
| 720 | usage: wgpu::TextureUsages::STORAGE_BINDING |
| 721 | | wgpu::TextureUsages::TEXTURE_BINDING, |
| 722 | view_formats: &[], |
| 723 | }); |
| 724 | let view = tex.create_view(&wgpu::TextureViewDescriptor::default()); |
| 725 | textures.push(tex); |
| 726 | views.push(view); |
| 727 | } |
| 728 | (textures, views) |
| 729 | } |
| 730 | |
| 731 | /// Create the bloom mip-chain texture + per-mip render views + a |
| 732 | /// full-chain view for sampling. Mip 0 starts at surface/2 size and |