diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:21 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:21 +0100 |
commit | 82d3355a7e265f84f7ef229c3e7841b485f2b43f (patch) | |
tree | bb02250d42759916596573cd22f10f3e249adc9c /stockton-render/src/draw/texture | |
parent | bb1fb24290654394cd0a32c3a6b3d98e5131088d (diff) |
refactor(render): docs/comments and error handling for missing textures
Diffstat (limited to 'stockton-render/src/draw/texture')
-rw-r--r-- | stockton-render/src/draw/texture/chunk.rs | 17 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/image.rs | 26 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/loader.rs | 26 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/mod.rs | 2 | ||||
-rw-r--r-- | stockton-render/src/draw/texture/resolver.rs | 20 |
5 files changed, 65 insertions, 26 deletions
diff --git a/stockton-render/src/draw/texture/chunk.rs b/stockton-render/src/draw/texture/chunk.rs index 9356274..22541a5 100644 --- a/stockton-render/src/draw/texture/chunk.rs +++ b/stockton-render/src/draw/texture/chunk.rs @@ -44,6 +44,8 @@ pub struct TextureChunk { } impl TextureChunk { + /// Create a new texture chunk and load in the textures specified by `range` from `file` using `resolver` + /// Can error if the descriptor pool is too small or if a texture isn't found pub fn new<T: HasTextures, R: TextureResolver>(device: &mut Device, adapter: &mut Adapter, command_queue: &mut CommandQueue, @@ -53,6 +55,7 @@ impl TextureChunk { file: &T, range: Range<u32>, resolver: &mut R) -> Result<TextureChunk, error::CreationError> { + // let descriptor_set = unsafe { pool.allocate_set(&layout).map_err(|e| { println!("{:?}", e); @@ -71,10 +74,16 @@ impl TextureChunk { for tex_idx in range { debug!("Loading tex {}", local_idx + 1); let tex = file.get_texture(tex_idx); - let img = resolver.resolve(tex); - store.put_texture(img, local_idx, - device, adapter, - command_queue, command_pool).unwrap(); + if let Some(img) = resolver.resolve(tex) { + store.put_texture(img, local_idx, + device, adapter, + command_queue, command_pool).unwrap(); + } else { + // Texture not found. For now, tear everything down. + store.deactivate(device); + + return Err(error::CreationError::BadDataError); + } local_idx += 1; } diff --git a/stockton-render/src/draw/texture/image.rs b/stockton-render/src/draw/texture/image.rs index fec84a2..583c2d9 100644 --- a/stockton-render/src/draw/texture/image.rs +++ b/stockton-render/src/draw/texture/image.rs @@ -13,12 +13,15 @@ // You should have received a copy of the GNU General Public License along // with this program. If not, see <http://www.gnu.org/licenses/>. -use core::ptr::copy_nonoverlapping; -use std::iter::once; -use core::mem::size_of; +use core::{ + ptr::copy_nonoverlapping, + mem::{size_of, ManuallyDrop} +}; +use std::{ + iter::once, + convert::TryInto +}; use image::RgbaImage; -use draw::buffer::create_buffer; -use core::mem::ManuallyDrop; use hal::{ MemoryTypeId, buffer::Usage as BufUsage, @@ -28,18 +31,25 @@ use hal::{ memory::{Properties as MemProperties, Dependencies as MemDependencies, Segment}, prelude::*, }; -use std::convert::TryInto; + use crate::types::*; +use draw::buffer::create_buffer; /// The size of each pixel in an image const PIXEL_SIZE: usize = size_of::<image::Rgba<u8>>(); - /// Holds an image that's loaded into GPU memory and can be sampled from pub struct LoadedImage { + /// The GPU Image handle image: ManuallyDrop<Image>, + + /// The full view of the image pub image_view: ManuallyDrop<ImageView>, + + /// A sampler for the image pub sampler: ManuallyDrop<Sampler>, + + /// The memory backing the image memory: ManuallyDrop<Memory> } @@ -52,7 +62,7 @@ impl LoadedImage { let initial_row_size = PIXEL_SIZE * (img.width() as usize); let limits = adapter.physical_device.limits(); let row_alignment_mask = limits.optimal_buffer_copy_pitch_alignment as u32 - 1; - + let row_size = ((initial_row_size as u32 + row_alignment_mask) & !row_alignment_mask) as usize; debug_assert!(row_size as usize >= initial_row_size); diff --git a/stockton-render/src/draw/texture/loader.rs b/stockton-render/src/draw/texture/loader.rs index b3aa3ae..483fb7d 100644 --- a/stockton-render/src/draw/texture/loader.rs +++ b/stockton-render/src/draw/texture/loader.rs @@ -34,7 +34,7 @@ use crate::types::*; /// Stores all loaded textures in GPU memory. /// When rendering, the descriptor sets are bound to the buffer /// The descriptor set layout should have the same count of textures as this does. -/// Note that it's possible not all descriptors are actually initialised images +/// All descriptors will be properly initialised images. pub struct TextureStore { descriptor_pool: ManuallyDrop<DescriptorPool>, pub(crate) descriptor_set_layout: ManuallyDrop<DescriptorSetLayout>, @@ -42,11 +42,12 @@ pub struct TextureStore { } impl TextureStore { + /// Create a new texture store for the given file, loading all textures from it. pub fn new<T: HasTextures>(device: &mut Device, adapter: &mut Adapter, command_queue: &mut CommandQueue, command_pool: &mut CommandPool, file: &T) -> Result<TextureStore, error::CreationError> { - // Figure out how many textures in this file + // Figure out how many textures in this file / how many chunks needed let size = file.textures_iter().count(); let num_chunks = { let mut x = size / CHUNK_SIZE; @@ -57,6 +58,7 @@ impl TextureStore { }; let rounded_size = num_chunks * CHUNK_SIZE; + // Descriptor pool, where we get our sets from let mut descriptor_pool = unsafe { use hal::pso::{DescriptorRangeDesc, DescriptorType, DescriptorPoolCreateFlags, ImageDescriptorType}; @@ -83,7 +85,7 @@ impl TextureStore { })? }; - // Descriptor set layout + // Layout of our descriptor sets let mut descriptor_set_layout = unsafe { use hal::pso::{DescriptorSetLayoutBinding, DescriptorType, ShaderStageFlags, ImageDescriptorType}; @@ -112,11 +114,11 @@ impl TextureStore { ) }.map_err(|_| error::CreationError::OutOfMemoryError)?; - // Set up all our chunks - debug!("Starting to load textures..."); - + // TODO: Proper way to set up resolver let mut resolver = BasicFSResolver::new(Path::new(".")); + // Create texture chunks + debug!("Starting to load textures..."); let mut chunks = Vec::with_capacity(num_chunks); for i in 0..num_chunks { let range = { @@ -128,7 +130,14 @@ impl TextureStore { }; debug!("Chunk {} / {} covering {:?}", i + 1, num_chunks, range); - chunks.push(TextureChunk::new(device, adapter, command_queue, command_pool, &mut descriptor_pool, &mut descriptor_set_layout, file, range, &mut resolver)?); + chunks.push( + TextureChunk::new( + device, adapter, command_queue, + command_pool, &mut descriptor_pool, + &mut descriptor_set_layout, file, + range, &mut resolver + )? + ); } debug!("All textures loaded."); @@ -140,6 +149,7 @@ impl TextureStore { }) } + /// Call this before dropping pub fn deactivate(mut self, device: &mut Device) -> () { unsafe { use core::ptr::read; @@ -155,10 +165,12 @@ impl TextureStore { } } + /// Get number of chunks being used pub fn get_n_chunks(&self) -> usize { self.chunks.len() } + /// Get the descriptor set for a given chunk pub fn get_chunk_descriptor_set<'a>(&'a self, idx: usize) -> &'a DescriptorSet { &self.chunks[idx].descriptor_set } diff --git a/stockton-render/src/draw/texture/mod.rs b/stockton-render/src/draw/texture/mod.rs index 896e1d2..9951eeb 100644 --- a/stockton-render/src/draw/texture/mod.rs +++ b/stockton-render/src/draw/texture/mod.rs @@ -13,6 +13,8 @@ // You should have received a copy of the GNU General Public License along // with this program. If not, see <http://www.gnu.org/licenses/>. +//! Everything related to loading textures into GPU memory + mod resolver; mod image; mod chunk; diff --git a/stockton-render/src/draw/texture/resolver.rs b/stockton-render/src/draw/texture/resolver.rs index 66bce9e..5867171 100644 --- a/stockton-render/src/draw/texture/resolver.rs +++ b/stockton-render/src/draw/texture/resolver.rs @@ -26,9 +26,11 @@ use std::path::Path; /// An object that can be used to resolve a texture from a BSP File pub trait TextureResolver { - fn resolve(&mut self, texture: &Texture) -> RgbaImage; + /// Get the given texture, or None if it's corrupt/not there. + fn resolve(&mut self, texture: &Texture) -> Option<RgbaImage>; } +/// A basic filesystem resolver which expects no file extension and guesses the image format pub struct BasicFSResolver<'a> { path: &'a Path } @@ -42,13 +44,17 @@ impl<'a> BasicFSResolver<'a> { } impl<'a> TextureResolver for BasicFSResolver<'a> { - fn resolve(&mut self, tex: &Texture) -> RgbaImage { + fn resolve(&mut self, tex: &Texture) -> Option<RgbaImage> { let path = self.path.join(&tex.name); - println!("Loading texture from {:?}", path); - Reader::open(path).unwrap() - .with_guessed_format().unwrap() - .decode().unwrap() - .into_rgba() + if let Ok(file) = Reader::open(path) { + if let Ok(guessed) = file.with_guessed_format() { + if let Ok(decoded) = guessed.decode() { + return Some(decoded.into_rgba()); + } + } + } + + None } }
\ No newline at end of file |