aboutsummaryrefslogtreecommitdiff
path: root/stockton-skeleton/src/texture/load.rs
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:24 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:24 +0100
commitb86e97f67a07368877bd18501aebcbe80cf93118 (patch)
tree97b72b4339da6400b481170eab11fd89ab5dfa80 /stockton-skeleton/src/texture/load.rs
parente1cc0e9a9d191bcd3a634be46fd3555d430b07a8 (diff)
feat(skeleton): add memory pools
added stock memory pools behind a feature gate refactored buffers to use them and to have better APIs. moved some util code out of builders::pipeline updated stockton-render for the changes deactivation is a WIP breaks UI drawing, fix WIP
Diffstat (limited to 'stockton-skeleton/src/texture/load.rs')
-rw-r--r--stockton-skeleton/src/texture/load.rs223
1 files changed, 88 insertions, 135 deletions
diff --git a/stockton-skeleton/src/texture/load.rs b/stockton-skeleton/src/texture/load.rs
index 1f33ad5..6cb4f4d 100644
--- a/stockton-skeleton/src/texture/load.rs
+++ b/stockton-skeleton/src/texture/load.rs
@@ -1,31 +1,31 @@
-use super::{
- block::LoadedImage, block::TexturesBlock, repo::BLOCK_SIZE, resolver::TextureResolver,
- staging_buffer::StagingBuffer, LoadableImage, PIXEL_SIZE,
+use std::sync::{Arc, RwLock};
+
+use super::{block::TexturesBlock, repo::BLOCK_SIZE, resolver::TextureResolver, LoadableImage};
+use crate::{
+ buffers::{
+ image::{ImageSpec, SampledImage, COLOR_RESOURCES},
+ staging::StagingBuffer,
+ },
+ error::LockPoisoned,
+ mem::{Block, MappableBlock, MemoryPool},
+ types::*,
};
-use crate::types::*;
use anyhow::{Context, Result};
use arrayvec::ArrayVec;
use hal::{
- format::{Aspects, Format, Swizzle},
+ format::{Aspects, Format},
image::{
- Filter, SamplerDesc, SubresourceLayers, SubresourceRange, Usage as ImgUsage, ViewKind,
- WrapMode,
+ Filter, SamplerDesc, SubresourceLayers, SubresourceRange, Usage as ImgUsage, WrapMode,
},
- memory::SparseFlags,
- MemoryTypeId,
};
-use rendy_memory::{Allocator, Block};
-use std::mem::ManuallyDrop;
use thiserror::Error;
-#[derive(Error, Debug)]
-pub enum TextureLoadError {
- #[error("No available resources")]
- NoResources,
-}
-
+/// The format used by the texture repo
+// TODO: This should be customisable.
pub const FORMAT: Format = Format::Rgba8Srgb;
+
+/// The resources used by each texture. ie one colour aspect
pub const RESOURCES: SubresourceRange = SubresourceRange {
aspects: Aspects::COLOR,
level_start: 0,
@@ -33,159 +33,112 @@ pub const RESOURCES: SubresourceRange = SubresourceRange {
layer_start: 0,
layer_count: Some(1),
};
+
+/// The layers used by each texture. ie one colour layer
pub const LAYERS: SubresourceLayers = SubresourceLayers {
aspects: Aspects::COLOR,
level: 0,
layers: 0..1,
};
+/// Configuration required to load a texture
pub struct TextureLoadConfig<R: TextureResolver> {
+ /// The resolver to use
pub resolver: R,
+
+ /// How to sample the image
pub filter: Filter,
+
+ /// How to deal with texture coordinates outside the image.
pub wrap_mode: WrapMode,
}
-pub struct QueuedLoad<B: Block<back::Backend>> {
+/// A texture load that has been queued, and is finished when the fence triggers.
+pub struct QueuedLoad<TP: MemoryPool, SP: MemoryPool> {
pub fence: FenceT,
pub buf: CommandBufferT,
- pub block: TexturesBlock<B>,
- pub staging_bufs: ArrayVec<[StagingBuffer; BLOCK_SIZE]>,
+ pub block: TexturesBlock<TP>,
+ pub staging_bufs: ArrayVec<[StagingBuffer<SP>; BLOCK_SIZE]>,
}
-impl<B: Block<back::Backend>> QueuedLoad<B> {
+impl<TP: MemoryPool, SP: MemoryPool> QueuedLoad<TP, SP> {
+ /// Break down into a tuple
pub fn dissolve(
self,
) -> (
(FenceT, CommandBufferT),
- ArrayVec<[StagingBuffer; BLOCK_SIZE]>,
- TexturesBlock<B>,
+ ArrayVec<[StagingBuffer<SP>; BLOCK_SIZE]>,
+ TexturesBlock<TP>,
) {
((self.fence, self.buf), self.staging_bufs, self.block)
}
}
-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;
-
- let row_size = ((initial_row_size as u32 + row_alignment_mask) & !row_alignment_mask) as usize;
- let total_size = (row_size * (img.height() as usize)) as u64;
- debug_assert!(row_size as usize >= initial_row_size);
-
- (row_size, total_size as usize)
-}
-
-pub fn create_image_view<T, I>(
+/// Create a SampledImage for the given LoadableImage, and load the image data into a StagingBuffer
+/// Note that this doesn't queue up transferring from the buffer to the image.
+pub unsafe fn load_image<I, R, SP, TP>(
device: &mut DeviceT,
- allocator: &mut T,
- format: Format,
- usage: ImgUsage,
- img: &I,
-) -> Result<(T::Block, ImageT)>
+ staging_allocator: &Arc<RwLock<SP>>,
+ tex_allocator: &Arc<RwLock<TP>>,
+ obcpa: u32,
+ img_data: I,
+ config: &TextureLoadConfig<R>,
+) -> Result<(StagingBuffer<SP>, SampledImage<TP>)>
where
- T: Allocator<back::Backend>,
I: LoadableImage,
+ R: TextureResolver,
+ SP: MemoryPool,
+ TP: MemoryPool,
+ SP::Block: MappableBlock,
{
- // Make the image
- let mut image_ref = unsafe {
- use hal::image::{Kind, Tiling, ViewCapabilities};
-
- device.create_image(
- Kind::D2(img.width(), img.height(), 1, 1),
- 1,
- format,
- Tiling::Optimal,
- usage,
- SparseFlags::empty(),
- ViewCapabilities::empty(),
- )
- }
- .context("Error creating image")?;
+ // Create sampled image
+ let sampled_image = {
+ let mut tex_allocator = tex_allocator
+ .write()
+ .map_err(|_| LockPoisoned::MemoryPool)?;
+
+ SampledImage::from_device_allocator(
+ device,
+ &mut *tex_allocator,
+ obcpa as u32,
+ &ImageSpec {
+ width: img_data.width(),
+ height: img_data.height(),
+ format: FORMAT,
+ usage: ImgUsage::TRANSFER_DST | ImgUsage::SAMPLED,
+ resources: COLOR_RESOURCES,
+ },
+ &SamplerDesc::new(config.filter, config.wrap_mode),
+ )?
+ };
- // Allocate memory
- let (block, _) = unsafe {
- let requirements = device.get_image_requirements(&image_ref);
-
- allocator.alloc(device, requirements.size, requirements.alignment)
- }
- .context("Error allocating memory")?;
-
- unsafe {
- device
- .bind_image_memory(block.memory(), block.range().start, &mut image_ref)
- .context("Error binding memory to image")?;
- }
+ // Create staging buffer
+ let total_size = sampled_image.bound_image().mem().size();
- Ok((block, image_ref))
-}
+ let mut staging_buffer = {
+ let mut staging_allocator = staging_allocator
+ .write()
+ .map_err(|_| LockPoisoned::MemoryPool)?;
-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);
-
- // Create staging buffer
- let mut staging_buffer = StagingBuffer::new(
- device,
- staging_allocator,
- total_size as u64,
- staging_memory_type,
- )
- .context("Error creating staging buffer")?;
+ StagingBuffer::from_device_pool(device, &mut *staging_allocator, total_size as u64)
+ .context("Error creating staging buffer")?
+ };
// Write to staging buffer
let mapped_memory = staging_buffer
- .map_memory(device)
+ .map(device, 0..total_size)
.context("Error mapping staged memory")?;
- img_data.copy_into(mapped_memory, row_size);
-
- staging_buffer.unmap_memory(device);
-
- // Create image
- let (img_mem, img) = create_image_view(
- device,
- tex_allocator,
- FORMAT,
- ImgUsage::SAMPLED | ImgUsage::TRANSFER_DST,
- &img_data,
- )
- .context("Error creating image")?;
-
- // Create image view
- let img_view = device
- .create_image_view(
- &img,
- ViewKind::D2,
- FORMAT,
- Swizzle::NO,
- ImgUsage::SAMPLED | ImgUsage::TRANSFER_DST,
- RESOURCES,
- )
- .context("Error creating image view")?;
-
- // Create sampler
- let sampler = device
- .create_sampler(&SamplerDesc::new(config.filter, config.wrap_mode))
- .context("Error creating sampler")?;
-
- Ok((
- staging_buffer,
- LoadedImage {
- mem: ManuallyDrop::new(img_mem),
- img: ManuallyDrop::new(img),
- img_view: ManuallyDrop::new(img_view),
- sampler: ManuallyDrop::new(sampler),
- row_size,
- height: img_data.height(),
- width: img_data.width(),
- },
- ))
+ img_data.copy_into(mapped_memory, sampled_image.row_size() as usize);
+
+ staging_buffer.unmap(device)?;
+
+ Ok((staging_buffer, sampled_image))
+}
+
+/// Errors that can be encountered when loading a texture.
+#[derive(Error, Debug)]
+pub enum TextureLoadError {
+ #[error("No available resources")]
+ NoResources,
}