aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/texture
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:23 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:23 +0100
commitc9fb3ae28fe491bc55243fb80d8c6be93f37ad99 (patch)
treec8d6519479d3b17f5bd657495c4d7fe2d2830a1a /stockton-render/src/draw/texture
parentc52a05e6d3977efce6bd4479aa312dc90e0452e5 (diff)
feat(render): ui working
Diffstat (limited to 'stockton-render/src/draw/texture')
-rw-r--r--stockton-render/src/draw/texture/load.rs21
-rw-r--r--stockton-render/src/draw/texture/loader.rs48
-rw-r--r--stockton-render/src/draw/texture/mod.rs1
-rw-r--r--stockton-render/src/draw/texture/repo.rs16
-rw-r--r--stockton-render/src/draw/texture/resolver.rs36
5 files changed, 57 insertions, 65 deletions
diff --git a/stockton-render/src/draw/texture/load.rs b/stockton-render/src/draw/texture/load.rs
index eea820a..e278fa2 100644
--- a/stockton-render/src/draw/texture/load.rs
+++ b/stockton-render/src/draw/texture/load.rs
@@ -1,9 +1,8 @@
use super::{
- block::LoadedImage, block::TexturesBlock, loader::TextureLoader, repo::BLOCK_SIZE,
- resolver::TextureResolver, staging_buffer::StagingBuffer, LoadableImage, PIXEL_SIZE,
+ block::LoadedImage, block::TexturesBlock, repo::BLOCK_SIZE, resolver::TextureResolver,
+ staging_buffer::StagingBuffer, LoadableImage, PIXEL_SIZE,
};
use crate::types::*;
-use stockton_levels::prelude::*;
use anyhow::{Context, Result};
use arrayvec::ArrayVec;
@@ -24,9 +23,6 @@ use thiserror::Error;
pub enum TextureLoadError {
#[error("No available resources")]
NoResources,
-
- #[error("Texture could not be resolved")]
- ResolveFailed(usize),
}
pub const FORMAT: Format = Format::Rgba8Srgb;
@@ -43,6 +39,12 @@ pub const LAYERS: SubresourceLayers = SubresourceLayers {
layers: 0..1,
};
+pub struct TextureLoadConfig<R: TextureResolver> {
+ pub resolver: R,
+ pub filter: Filter,
+ pub wrap_mode: WrapMode,
+}
+
pub struct QueuedLoad<B: Block<back::Backend>> {
pub fence: FenceT,
pub buf: CommandBufferT,
@@ -62,8 +64,6 @@ impl<B: Block<back::Backend>> QueuedLoad<B> {
}
}
-impl<'a, T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R, I> {}
-
pub fn tex_size_info<T: LoadableImage>(img: &T, obcpa: hal::buffer::Offset) -> (usize, usize) {
let initial_row_size = PIXEL_SIZE * img.width() as usize;
let row_alignment_mask = obcpa as u32 - 1;
@@ -119,13 +119,14 @@ where
Ok((block, image_ref))
}
-pub unsafe fn load_image<I: LoadableImage>(
+pub unsafe fn load_image<I: LoadableImage, R: TextureResolver>(
device: &mut DeviceT,
staging_allocator: &mut DynamicAllocator,
tex_allocator: &mut DynamicAllocator,
staging_memory_type: MemoryTypeId,
obcpa: u64,
img_data: I,
+ config: &TextureLoadConfig<R>,
) -> Result<(StagingBuffer, LoadedImage<DynamicBlock>)> {
// Calculate buffer size
let (row_size, total_size) = tex_size_info(&img_data, obcpa);
@@ -172,7 +173,7 @@ pub unsafe fn load_image<I: LoadableImage>(
// Create sampler
let sampler = device
- .create_sampler(&SamplerDesc::new(Filter::Nearest, WrapMode::Tile))
+ .create_sampler(&SamplerDesc::new(config.filter, config.wrap_mode))
.context("Error creating sampler")?;
Ok((
diff --git a/stockton-render/src/draw/texture/loader.rs b/stockton-render/src/draw/texture/loader.rs
index 3d7d32e..96b1646 100644
--- a/stockton-render/src/draw/texture/loader.rs
+++ b/stockton-render/src/draw/texture/loader.rs
@@ -2,10 +2,10 @@
use super::{
block::{LoadedImage, TexturesBlock},
- load::{load_image, QueuedLoad, TextureLoadError, LAYERS, RESOURCES},
+ load::{load_image, QueuedLoad, TextureLoadConfig, TextureLoadError, LAYERS, RESOURCES},
repo::BLOCK_SIZE,
resolver::TextureResolver,
- LoadableImage, PIXEL_SIZE,
+ PIXEL_SIZE,
};
use crate::{draw::utils::find_memory_type_id, error::LockPoisoned, types::*};
@@ -13,7 +13,6 @@ use std::{
array::IntoIter,
collections::VecDeque,
iter::{empty, once},
- marker::PhantomData,
mem::{drop, ManuallyDrop},
sync::{
mpsc::{Receiver, Sender},
@@ -38,7 +37,6 @@ use image::{Rgba, RgbaImage};
use log::*;
use rendy_descriptor::{DescriptorRanges, DescriptorSetLayoutBinding, DescriptorType};
use rendy_memory::DynamicConfig;
-use stockton_levels::prelude::HasTextures;
use thiserror::Error;
/// The number of command buffers to have in flight simultaneously.
@@ -49,7 +47,7 @@ pub type BlockRef = usize;
/// Manages the loading/unloading of textures
/// This is expected to load the textures, then send the loaded blocks back
-pub struct TextureLoader<T, R, I> {
+pub struct TextureLoader<R: TextureResolver> {
/// Blocks for which commands have been queued and are done loading once the fence is triggered.
commands_queued: ArrayVec<[QueuedLoad<DynamicBlock>; NUM_SIMULTANEOUS_CMDS]>,
@@ -82,11 +80,8 @@ pub struct TextureLoader<T, R, I> {
/// From adapter, used for determining alignment
optimal_buffer_copy_pitch_alignment: hal::buffer::Offset,
- /// The textures lump to get info from
- textures: Arc<RwLock<T>>,
-
- /// The resolver which gets image data for a given texture.
- resolver: R,
+ /// Configuration for how to find and load textures
+ config: TextureLoadConfig<R>,
/// The channel requests come in.
/// Requests should reference a texture **block**, for example textures 8..16 is block 1.
@@ -97,8 +92,6 @@ pub struct TextureLoader<T, R, I> {
/// A filler image for descriptors that aren't needed but still need to be written to
blank_image: ManuallyDrop<LoadedImage<DynamicBlock>>,
-
- _li: PhantomData<I>,
}
#[derive(Error, Debug)]
@@ -107,7 +100,7 @@ pub enum TextureLoaderError {
NoMemoryTypes,
}
-impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R, I> {
+impl<R: TextureResolver> TextureLoader<R> {
pub fn loop_until_exit(mut self) -> Result<TextureLoaderRemains> {
debug!("TextureLoader starting main loop");
let mut res = Ok(false);
@@ -196,8 +189,7 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
ds_layout: Arc<RwLock<DescriptorSetLayoutT>>,
request_channel: Receiver<LoaderRequest>,
return_channel: Sender<TexturesBlock<DynamicBlock>>,
- texs: Arc<RwLock<T>>,
- resolver: R,
+ config: TextureLoadConfig<R>,
) -> Result<Self> {
let mut device = device_lock
.write()
@@ -310,6 +302,7 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
&mut tex_allocator,
staging_memory_type,
optimal_buffer_copy_pitch_alignment,
+ &config,
)
}
.context("Error creating blank image")?;
@@ -333,10 +326,8 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
request_channel,
return_channel,
- textures: texs,
- resolver,
+ config,
blank_image: ManuallyDrop::new(blank_image),
- _li: PhantomData::default(),
})
}
@@ -347,12 +338,6 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
.map_err(|_| LockPoisoned::Device)
.context("Error getting device lock")?;
- let textures = self
- .textures
- .read()
- .map_err(|_| LockPoisoned::Map)
- .context("Error getting map lock")?;
-
// Get assets to use
let (mut fence, mut buf) = self
.buffers
@@ -407,9 +392,9 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
// For each texture in block
for tex_idx in (block_ref * BLOCK_SIZE)..(block_ref + 1) * BLOCK_SIZE {
- // Get texture and Resolve image
- let tex = textures.get_texture(tex_idx as u32);
- if tex.is_none() {
+ // Resolve texture
+ let img_data = self.config.resolver.resolve(tex_idx as u32);
+ if img_data.is_none() {
// Write a blank descriptor
device.write_descriptor_set(DescriptorSetWrite {
set: descriptor_set.raw_mut(),
@@ -430,12 +415,8 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
continue;
}
- let tex = tex.unwrap();
+ let img_data = img_data.unwrap();
- let img_data = self
- .resolver
- .resolve(tex)
- .ok_or(TextureLoadError::ResolveFailed(tex_idx))?;
let array_offset = tex_idx % BLOCK_SIZE;
let (staging_buffer, img) = load_image(
@@ -445,6 +426,7 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
self.staging_memory_type,
self.optimal_buffer_copy_pitch_alignment,
img_data,
+ &self.config,
)?;
// Write to descriptor set
@@ -555,6 +537,7 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
tex_allocator: &mut DynamicAllocator,
staging_memory_type: MemoryTypeId,
obcpa: u64,
+ config: &TextureLoadConfig<R>,
) -> Result<LoadedImage<DynamicBlock>> {
let img_data = RgbaImage::from_pixel(1, 1, Rgba([0, 0, 0, 0]));
@@ -572,6 +555,7 @@ impl<T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R
staging_memory_type,
obcpa,
img_data,
+ &config,
)?;
buf.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT);
diff --git a/stockton-render/src/draw/texture/mod.rs b/stockton-render/src/draw/texture/mod.rs
index 43c89d5..62b28c5 100644
--- a/stockton-render/src/draw/texture/mod.rs
+++ b/stockton-render/src/draw/texture/mod.rs
@@ -10,6 +10,7 @@ mod staging_buffer;
pub use self::block::TexturesBlock;
pub use self::image::LoadableImage;
+pub use self::load::TextureLoadConfig;
pub use self::loader::BlockRef;
pub use self::repo::TextureRepo;
diff --git a/stockton-render/src/draw/texture/repo.rs b/stockton-render/src/draw/texture/repo.rs
index 8191f7b..ef35610 100644
--- a/stockton-render/src/draw/texture/repo.rs
+++ b/stockton-render/src/draw/texture/repo.rs
@@ -1,10 +1,8 @@
-use stockton_levels::prelude::HasTextures;
-
use super::{
block::TexturesBlock,
+ load::TextureLoadConfig,
loader::{BlockRef, LoaderRequest, TextureLoader, TextureLoaderRemains, NUM_SIMULTANEOUS_CMDS},
resolver::TextureResolver,
- LoadableImage,
};
use crate::error::LockPoisoned;
use crate::types::*;
@@ -49,17 +47,12 @@ impl<'a> TextureRepo<'a> {
family.queue_type().supports_transfer() && family.max_queues() >= NUM_SIMULTANEOUS_CMDS
}
- pub fn new<
- T: 'static + HasTextures + Send + Sync,
- R: 'static + TextureResolver<I> + Send + Sync,
- I: 'static + LoadableImage + Send,
- >(
+ pub fn new<R: 'static + TextureResolver + Send + Sync>(
device_lock: Arc<RwLock<DeviceT>>,
family: QueueFamilyId,
queue: Arc<RwLock<QueueT>>,
adapter: &Adapter,
- texs_lock: Arc<RwLock<T>>,
- resolver: R,
+ config: TextureLoadConfig<R>,
) -> Result<Self> {
// Create Channels
let (req_send, req_recv) = channel();
@@ -112,8 +105,7 @@ impl<'a> TextureRepo<'a> {
ds_lock.clone(),
req_recv,
resp_send,
- texs_lock,
- resolver,
+ config,
)?;
std::thread::spawn(move || loader.loop_until_exit())
diff --git a/stockton-render/src/draw/texture/resolver.rs b/stockton-render/src/draw/texture/resolver.rs
index 20efa00..1ecb7a0 100644
--- a/stockton-render/src/draw/texture/resolver.rs
+++ b/stockton-render/src/draw/texture/resolver.rs
@@ -1,33 +1,47 @@
//! Resolves a texture in a BSP File to an image
use crate::draw::texture::image::LoadableImage;
-use stockton_levels::traits::textures::Texture;
+use stockton_levels::prelude::HasTextures;
-use std::path::Path;
+use std::{
+ mem::drop,
+ path::Path,
+ sync::{Arc, RwLock},
+};
use image::{io::Reader, RgbaImage};
/// An object that can be used to resolve a texture from a BSP File
-pub trait TextureResolver<T: LoadableImage> {
+pub trait TextureResolver {
+ type Image: LoadableImage;
+
/// Get the given texture, or None if it's corrupt/not there.
- fn resolve(&mut self, texture: &Texture) -> Option<T>;
+ fn resolve(&mut self, texture_id: u32) -> Option<Self::Image>;
}
-/// A basic filesystem resolver which expects no file extension and guesses the image format
-pub struct BasicFsResolver<'a> {
+/// A basic filesystem resolver which gets the texture name from any HasTextures Object.
+pub struct FsResolver<'a, T: HasTextures> {
path: &'a Path,
+ map_lock: Arc<RwLock<T>>,
}
-impl<'a> BasicFsResolver<'a> {
- pub fn new(path: &'a Path) -> BasicFsResolver<'a> {
- BasicFsResolver { path }
+impl<'a, T: HasTextures> FsResolver<'a, T> {
+ pub fn new(path: &'a Path, map_lock: Arc<RwLock<T>>) -> Self {
+ FsResolver { path, map_lock }
}
}
-impl<'a> TextureResolver<RgbaImage> for BasicFsResolver<'a> {
- fn resolve(&mut self, tex: &Texture) -> Option<RgbaImage> {
+impl<'a, T: HasTextures> TextureResolver for FsResolver<'a, T> {
+ type Image = RgbaImage;
+
+ fn resolve(&mut self, tex: u32) -> Option<Self::Image> {
+ let map = self.map_lock.read().unwrap();
+ let tex = map.get_texture(tex)?;
let path = self.path.join(&tex.name);
+ drop(tex);
+ drop(map);
+
if let Ok(file) = Reader::open(path) {
if let Ok(guessed) = file.with_guessed_format() {
if let Ok(decoded) = guessed.decode() {