aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/texture/load.rs
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
commit399ae8ba45f40a54ec68026f77ca3c7c709ab62f (patch)
tree0ca721f8baf1cdf612c27822cd106343cad26155 /stockton-render/src/draw/texture/load.rs
parentd7d0f0277c437004ed476393542da39c84c5cf9f (diff)
refactor(render): move functions from load into loader
Diffstat (limited to 'stockton-render/src/draw/texture/load.rs')
-rw-r--r--stockton-render/src/draw/texture/load.rs338
1 files changed, 11 insertions, 327 deletions
diff --git a/stockton-render/src/draw/texture/load.rs b/stockton-render/src/draw/texture/load.rs
index be1aa27..eea820a 100644
--- a/stockton-render/src/draw/texture/load.rs
+++ b/stockton-render/src/draw/texture/load.rs
@@ -2,31 +2,22 @@ use super::{
block::LoadedImage, block::TexturesBlock, loader::TextureLoader, repo::BLOCK_SIZE,
resolver::TextureResolver, staging_buffer::StagingBuffer, LoadableImage, PIXEL_SIZE,
};
-use crate::{error::LockPoisoned, types::*};
+use crate::types::*;
use stockton_levels::prelude::*;
use anyhow::{Context, Result};
use arrayvec::ArrayVec;
use hal::{
- command::{BufferImageCopy, CommandBufferFlags},
format::{Aspects, Format, Swizzle},
image::{
- Access, Extent, Filter, Layout, Offset, SamplerDesc, SubresourceLayers, SubresourceRange,
- Usage as ImgUsage, ViewKind, WrapMode,
+ Filter, SamplerDesc, SubresourceLayers, SubresourceRange, Usage as ImgUsage, ViewKind,
+ WrapMode,
},
- memory::{Barrier, Dependencies, SparseFlags},
- pso::{Descriptor, DescriptorSetWrite, ImageDescriptorType, PipelineStage, ShaderStageFlags},
+ memory::SparseFlags,
MemoryTypeId,
};
-use image::{Rgba, RgbaImage};
-use rendy_descriptor::{DescriptorRanges, DescriptorSetLayoutBinding, DescriptorType};
use rendy_memory::{Allocator, Block};
-use std::{
- array::IntoIter,
- iter::{empty, once},
- mem::ManuallyDrop,
- sync::{Arc, RwLock},
-};
+use std::mem::ManuallyDrop;
use thiserror::Error;
#[derive(Error, Debug)]
@@ -38,15 +29,15 @@ pub enum TextureLoadError {
ResolveFailed(usize),
}
-const FORMAT: Format = Format::Rgba8Srgb;
-const RESOURCES: SubresourceRange = SubresourceRange {
+pub const FORMAT: Format = Format::Rgba8Srgb;
+pub const RESOURCES: SubresourceRange = SubresourceRange {
aspects: Aspects::COLOR,
level_start: 0,
level_count: Some(1),
layer_start: 0,
layer_count: Some(1),
};
-const LAYERS: SubresourceLayers = SubresourceLayers {
+pub const LAYERS: SubresourceLayers = SubresourceLayers {
aspects: Aspects::COLOR,
level: 0,
layers: 0..1,
@@ -71,314 +62,7 @@ impl<B: Block<back::Backend>> QueuedLoad<B> {
}
}
-impl<'a, T: HasTextures, R: TextureResolver<I>, I: LoadableImage> TextureLoader<T, R, I> {
- pub(crate) unsafe fn attempt_queue_load(
- &mut self,
- block_ref: usize,
- ) -> Result<QueuedLoad<DynamicBlock>> {
- let mut device = self
- .device
- .write()
- .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
- .pop_front()
- .ok_or(TextureLoadError::NoResources)
- .context("Error getting resources to use")?;
-
- // Create descriptor set
- let mut descriptor_set = {
- let mut v: ArrayVec<[RDescriptorSet; 1]> = ArrayVec::new();
- self.descriptor_allocator
- .allocate(
- &device,
- &*self.ds_layout.read().unwrap(),
- DescriptorRanges::from_bindings(&[
- DescriptorSetLayoutBinding {
- binding: 0,
- ty: DescriptorType::Image {
- ty: ImageDescriptorType::Sampled {
- with_sampler: false,
- },
- },
- count: BLOCK_SIZE,
- stage_flags: ShaderStageFlags::FRAGMENT,
- immutable_samplers: false,
- },
- DescriptorSetLayoutBinding {
- binding: 1,
- ty: DescriptorType::Sampler,
- count: BLOCK_SIZE,
- stage_flags: ShaderStageFlags::FRAGMENT,
- immutable_samplers: false,
- },
- ]),
- 1,
- &mut v,
- )
- .context("Error creating descriptor set")?;
-
- v.pop().unwrap()
- };
-
- // Get a command buffer
- buf.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT);
-
- let mut imgs: ArrayVec<[_; BLOCK_SIZE]> = ArrayVec::new();
- let mut staging_bufs: ArrayVec<[_; BLOCK_SIZE]> = ArrayVec::new();
-
- // 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() {
- // Write a blank descriptor
- device.write_descriptor_set(DescriptorSetWrite {
- set: descriptor_set.raw_mut(),
- binding: 0,
- array_offset: tex_idx % BLOCK_SIZE,
- descriptors: once(Descriptor::Image(
- &*self.blank_image.img_view,
- Layout::ShaderReadOnlyOptimal,
- )),
- });
- device.write_descriptor_set(DescriptorSetWrite {
- set: descriptor_set.raw_mut(),
- binding: 1,
- array_offset: tex_idx % BLOCK_SIZE,
- descriptors: once(Descriptor::Sampler(&*self.blank_image.sampler)),
- });
-
- continue;
- }
-
- let tex = tex.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(
- &mut device,
- &mut self.staging_allocator,
- &mut self.tex_allocator,
- self.staging_memory_type,
- self.optimal_buffer_copy_pitch_alignment,
- img_data,
- )?;
-
- // Write to descriptor set
- {
- device.write_descriptor_set(DescriptorSetWrite {
- set: descriptor_set.raw_mut(),
- binding: 0,
- array_offset,
- descriptors: once(Descriptor::Image(
- &*img.img_view,
- Layout::ShaderReadOnlyOptimal,
- )),
- });
- device.write_descriptor_set(DescriptorSetWrite {
- set: descriptor_set.raw_mut(),
- binding: 1,
- array_offset,
- descriptors: once(Descriptor::Sampler(&*img.sampler)),
- });
- }
-
- imgs.push(img);
-
- staging_bufs.push(staging_buffer);
- }
-
- // Add start pipeline barrier
- buf.pipeline_barrier(
- PipelineStage::TOP_OF_PIPE..PipelineStage::TRANSFER,
- Dependencies::empty(),
- imgs.iter().map(|li| Barrier::Image {
- states: (Access::empty(), Layout::Undefined)
- ..(Access::TRANSFER_WRITE, Layout::TransferDstOptimal),
- target: &*li.img,
- families: None,
- range: SubresourceRange {
- aspects: Aspects::COLOR,
- level_start: 0,
- level_count: None,
- layer_start: 0,
- layer_count: None,
- },
- }),
- );
-
- // Record copy commands
- for (li, sb) in imgs.iter().zip(staging_bufs.iter()) {
- buf.copy_buffer_to_image(
- &*sb.buf,
- &*li.img,
- Layout::TransferDstOptimal,
- once(BufferImageCopy {
- buffer_offset: 0,
- buffer_width: (li.row_size / super::PIXEL_SIZE) as u32,
- buffer_height: li.height,
- image_layers: SubresourceLayers {
- aspects: Aspects::COLOR,
- level: 0,
- layers: 0..1,
- },
- image_offset: Offset { x: 0, y: 0, z: 0 },
- image_extent: gfx_hal::image::Extent {
- width: li.width,
- height: li.height,
- depth: 1,
- },
- }),
- );
- }
- buf.pipeline_barrier(
- PipelineStage::TRANSFER..PipelineStage::BOTTOM_OF_PIPE,
- Dependencies::empty(),
- imgs.iter().map(|li| Barrier::Image {
- states: (Access::TRANSFER_WRITE, Layout::TransferDstOptimal)
- ..(Access::empty(), Layout::ShaderReadOnlyOptimal),
- target: &*li.img,
- families: None,
- range: RESOURCES,
- }),
- );
-
- buf.finish();
-
- // Submit command buffer
- {
- let mut queue = self.queue.write().map_err(|_| LockPoisoned::Queue)?;
-
- queue.submit(IntoIter::new([&buf]), empty(), empty(), Some(&mut fence));
- }
-
- Ok(QueuedLoad {
- staging_bufs,
- fence,
- buf,
- block: TexturesBlock {
- id: block_ref,
- imgs,
- descriptor_set: ManuallyDrop::new(descriptor_set),
- },
- })
- }
-
- pub(crate) unsafe fn get_blank_image(
- device: &mut DeviceT,
- buf: &mut CommandBufferT,
- queue_lock: &Arc<RwLock<QueueT>>,
- staging_allocator: &mut DynamicAllocator,
- tex_allocator: &mut DynamicAllocator,
- staging_memory_type: MemoryTypeId,
- obcpa: u64,
- ) -> Result<LoadedImage<DynamicBlock>> {
- let img_data = RgbaImage::from_pixel(1, 1, Rgba([0, 0, 0, 0]));
-
- let height = img_data.height();
- let width = img_data.width();
- let row_alignment_mask = obcpa as u32 - 1;
- let initial_row_size = PIXEL_SIZE * img_data.width() as usize;
- let row_size =
- ((initial_row_size as u32 + row_alignment_mask) & !row_alignment_mask) as usize;
-
- let (staging_buffer, img) = load_image(
- device,
- staging_allocator,
- tex_allocator,
- staging_memory_type,
- obcpa,
- img_data,
- )?;
-
- buf.begin_primary(CommandBufferFlags::ONE_TIME_SUBMIT);
-
- buf.pipeline_barrier(
- PipelineStage::TOP_OF_PIPE..PipelineStage::TRANSFER,
- Dependencies::empty(),
- once(Barrier::Image {
- states: (Access::empty(), Layout::Undefined)
- ..(Access::TRANSFER_WRITE, Layout::TransferDstOptimal),
- target: &*img.img,
- families: None,
- range: SubresourceRange {
- aspects: Aspects::COLOR,
- level_start: 0,
- level_count: None,
- layer_start: 0,
- layer_count: None,
- },
- }),
- );
- buf.copy_buffer_to_image(
- &*staging_buffer.buf,
- &*img.img,
- Layout::TransferDstOptimal,
- once(BufferImageCopy {
- buffer_offset: 0,
- buffer_width: (row_size / super::PIXEL_SIZE) as u32,
- buffer_height: height,
- image_layers: LAYERS,
- image_offset: Offset { x: 0, y: 0, z: 0 },
- image_extent: Extent {
- width: width,
- height: height,
- depth: 1,
- },
- }),
- );
-
- buf.pipeline_barrier(
- PipelineStage::TRANSFER..PipelineStage::BOTTOM_OF_PIPE,
- Dependencies::empty(),
- once(Barrier::Image {
- states: (Access::TRANSFER_WRITE, Layout::TransferDstOptimal)
- ..(Access::empty(), Layout::ShaderReadOnlyOptimal),
- target: &*img.img,
- families: None,
- range: RESOURCES,
- }),
- );
- buf.finish();
-
- let mut fence = device.create_fence(false).context("Error creating fence")?;
-
- {
- let mut queue = queue_lock.write().map_err(|_| LockPoisoned::Queue)?;
-
- queue.submit(
- IntoIter::new([buf as &CommandBufferT]),
- empty(),
- empty(),
- Some(&mut fence),
- );
- }
-
- device
- .wait_for_fence(&fence, std::u64::MAX)
- .context("Error waiting for copy")?;
-
- device.destroy_fence(fence);
-
- staging_buffer.deactivate(device, staging_allocator);
-
- Ok(img)
- }
-}
+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;
@@ -391,7 +75,7 @@ pub fn tex_size_info<T: LoadableImage>(img: &T, obcpa: hal::buffer::Offset) -> (
(row_size, total_size as usize)
}
-fn create_image_view<T, I>(
+pub fn create_image_view<T, I>(
device: &mut DeviceT,
allocator: &mut T,
format: Format,
@@ -435,7 +119,7 @@ where
Ok((block, image_ref))
}
-unsafe fn load_image<I: LoadableImage>(
+pub unsafe fn load_image<I: LoadableImage>(
device: &mut DeviceT,
staging_allocator: &mut DynamicAllocator,
tex_allocator: &mut DynamicAllocator,