use std::{convert::TryInto, io::Read}; use vulkano::{format::Format, sampler::{Filter, SamplerAddressMode}}; use super::{Texture, VulkanRenderer}; pub fn upload_texture_from_file(path: &str, renderer: &mut VulkanRenderer) -> Result> { // Load file let mut tex_file = std::fs::File::open(path)?; let mut tex_bytes: Vec = vec![]; tex_file.read_to_end(&mut tex_bytes)?; // Parse DDS let tex_height = u32::from_ne_bytes(tex_bytes[12..16].try_into()?); let tex_width = u32::from_ne_bytes(tex_bytes[16..20].try_into()?); let tex_byte_count = u32::from_ne_bytes(tex_bytes[20..24].try_into()?); let pixel_format_flags = u32::from_ne_bytes(tex_bytes[80..84].try_into()?); let pixel_format_name: [u8; 4] = tex_bytes[84..88].try_into()?; let is_dxt1 = pixel_format_name == [0x44, 0x58, 0x54, 0x31]; // [D,X,T,1] let is_dx10 = pixel_format_name == [0x44, 0x58, 0x31, 0x30]; // [D,X,1,0] assert!(pixel_format_flags == 0x00000004); assert!(is_dxt1 || is_dx10); println!("Texture width: {}, height: {}, bytes: {}", tex_width, tex_height, tex_byte_count); let texture = if is_dxt1 { renderer.upload_texture(&tex_bytes[128..], tex_width, tex_height, Format::BC1_RGB_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone()) } else if is_dx10 { let dxgi_type = u32::from_ne_bytes(tex_bytes[128..132].try_into()?); assert!(dxgi_type == 83); // BC5 Unorm Typeless renderer.upload_texture(&tex_bytes[128+20..], tex_width, tex_height, Format::BC5_UNORM_BLOCK, Filter::Linear, SamplerAddressMode::Repeat, renderer.device.clone()) } else { panic!("Unknown texture type!"); }; Ok(texture) } pub fn get_block_size(format: Format) -> Option { match format { Format::BC1_RGB_UNORM_BLOCK => Some(8), Format::BC5_UNORM_BLOCK => Some(16), _ => None } }