aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/texture
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:21 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:21 +0100
commit82d3355a7e265f84f7ef229c3e7841b485f2b43f (patch)
treebb02250d42759916596573cd22f10f3e249adc9c /stockton-render/src/draw/texture
parentbb1fb24290654394cd0a32c3a6b3d98e5131088d (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.rs17
-rw-r--r--stockton-render/src/draw/texture/image.rs26
-rw-r--r--stockton-render/src/draw/texture/loader.rs26
-rw-r--r--stockton-render/src/draw/texture/mod.rs2
-rw-r--r--stockton-render/src/draw/texture/resolver.rs20
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