texture.rs (3701B)
1 pub fn make_1x1_rgba8( 2 device: &wgpu::Device, 3 queue: &wgpu::Queue, 4 format: wgpu::TextureFormat, 5 rgba: [u8; 4], 6 label: &str, 7 ) -> wgpu::TextureView { 8 let extent = wgpu::Extent3d { 9 width: 1, 10 height: 1, 11 depth_or_array_layers: 1, 12 }; 13 let tex = device.create_texture(&wgpu::TextureDescriptor { 14 label: Some(label), 15 size: extent, 16 mip_level_count: 1, 17 sample_count: 1, 18 dimension: wgpu::TextureDimension::D2, 19 format, 20 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, 21 view_formats: &[], 22 }); 23 24 queue.write_texture( 25 wgpu::TexelCopyTextureInfo { 26 texture: &tex, 27 mip_level: 0, 28 origin: wgpu::Origin3d::ZERO, 29 aspect: wgpu::TextureAspect::All, 30 }, 31 &rgba, 32 wgpu::TexelCopyBufferLayout { 33 offset: 0, 34 bytes_per_row: Some(4), 35 rows_per_image: Some(1), 36 }, 37 extent, 38 ); 39 40 tex.create_view(&wgpu::TextureViewDescriptor::default()) 41 } 42 43 pub fn texture_layout_entry(binding: u32) -> wgpu::BindGroupLayoutEntry { 44 wgpu::BindGroupLayoutEntry { 45 binding, 46 visibility: wgpu::ShaderStages::FRAGMENT, 47 ty: wgpu::BindingType::Texture { 48 multisampled: false, 49 view_dimension: wgpu::TextureViewDimension::D2, 50 sample_type: wgpu::TextureSampleType::Float { filterable: true }, 51 }, 52 count: None, 53 } 54 } 55 56 /// Robust texture upload helper (handles row padding) 57 /// "queue.write_texture is annoying once width*4 isn't 256-aligned. This helper always works" 58 pub fn upload_rgba8_texture_2d( 59 device: &wgpu::Device, 60 queue: &wgpu::Queue, 61 width: u32, 62 height: u32, 63 rgba: &[u8], 64 format: wgpu::TextureFormat, 65 label: &str, 66 ) -> wgpu::TextureView { 67 assert_eq!(rgba.len(), (width * height * 4) as usize); 68 assert!(!rgba.is_empty()); 69 70 let extent = wgpu::Extent3d { 71 width, 72 height, 73 depth_or_array_layers: 1, 74 }; 75 let texture = device.create_texture(&wgpu::TextureDescriptor { 76 label: Some(label), 77 size: extent, 78 mip_level_count: 1, 79 sample_count: 1, 80 dimension: wgpu::TextureDimension::D2, 81 format, 82 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST, 83 view_formats: &[], 84 }); 85 86 let bytes_per_pixel = 4usize; 87 let unpadded_bytes_per_row = width as usize * bytes_per_pixel; 88 let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as usize; // 256 89 90 // CEIL division to next multiple of 256 91 let padded_bytes_per_row = unpadded_bytes_per_row.div_ceil(align) * align; 92 93 assert!(padded_bytes_per_row >= unpadded_bytes_per_row); 94 assert!(padded_bytes_per_row.is_multiple_of(align)); 95 96 let mut padded = vec![0u8; padded_bytes_per_row * height as usize]; 97 for y in 0..height as usize { 98 let src = &rgba[y * unpadded_bytes_per_row..(y + 1) * unpadded_bytes_per_row]; 99 let dst = &mut padded 100 [y * padded_bytes_per_row..y * padded_bytes_per_row + unpadded_bytes_per_row]; 101 dst.copy_from_slice(src); 102 } 103 104 queue.write_texture( 105 wgpu::TexelCopyTextureInfo { 106 texture: &texture, 107 mip_level: 0, 108 origin: wgpu::Origin3d::ZERO, 109 aspect: wgpu::TextureAspect::All, 110 }, 111 &padded, 112 wgpu::TexelCopyBufferLayout { 113 offset: 0, 114 bytes_per_row: Some(padded_bytes_per_row as u32), 115 rows_per_image: Some(height), 116 }, 117 extent, 118 ); 119 120 texture.create_view(&wgpu::TextureViewDescriptor::default()) 121 }