diff options
Diffstat (limited to 'stockton-render/src/draw/texture/load.rs')
-rw-r--r-- | stockton-render/src/draw/texture/load.rs | 338 |
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, |