aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/texture/image.rs
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
commit2f112ab34ac1458b038598f4d7ef6638df463dc6 (patch)
treec0100341b31276297fc9d2992797c5ca18cd2d99 /stockton-render/src/draw/texture/image.rs
parent27760ec1ca7a93877b2b015a0a2e9db87de4204c (diff)
feat(render): depth buffer and refactors
Diffstat (limited to 'stockton-render/src/draw/texture/image.rs')
-rw-r--r--stockton-render/src/draw/texture/image.rs216
1 files changed, 139 insertions, 77 deletions
diff --git a/stockton-render/src/draw/texture/image.rs b/stockton-render/src/draw/texture/image.rs
index 583c2d9..530628a 100644
--- a/stockton-render/src/draw/texture/image.rs
+++ b/stockton-render/src/draw/texture/image.rs
@@ -26,7 +26,7 @@ use hal::{
MemoryTypeId,
buffer::Usage as BufUsage,
format::{Format, Swizzle, Aspects},
- image::{ViewKind, SubresourceRange},
+ image::{ViewKind, SubresourceRange, Usage as ImgUsage},
queue::Submission,
memory::{Properties as MemProperties, Dependencies as MemDependencies, Segment},
prelude::*,
@@ -46,28 +46,91 @@ pub struct LoadedImage {
/// 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>
}
+pub fn create_image_view(device: &mut Device, adapter: &Adapter, format: Format, usage: ImgUsage, width: usize, height: usize) -> Result<(Memory, Image), &'static str> {
+ // Round up the size to align properly
+ let initial_row_size = PIXEL_SIZE * width;
+ 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);
+
+ // Make the image
+ let mut image_ref = unsafe {
+ use hal::image::{Kind, Tiling, ViewCapabilities};
+
+ device.create_image(
+ Kind::D2(width as u32, height as u32, 1, 1),
+ 1,
+ format,
+ Tiling::Optimal,
+ usage,
+ ViewCapabilities::empty()
+ )
+ }.map_err(|_| "Couldn't create image")?;
+
+ // Allocate memory
+ let memory = unsafe {
+ let requirements = device.get_image_requirements(&image_ref);
+
+ let memory_type_id = adapter.physical_device
+ .memory_properties().memory_types
+ .iter().enumerate()
+ .find(|&(id, memory_type)| {
+ requirements.type_mask & (1 << id) != 0 && memory_type.properties.contains(MemProperties::DEVICE_LOCAL)
+ })
+ .map(|(id, _)| MemoryTypeId(id))
+ .ok_or("Couldn't find a memory type for image memory")?;
+
+ let memory = device
+ .allocate_memory(memory_type_id, requirements.size)
+ .map_err(|_| "Couldn't allocate image memory")?;
+
+ device.bind_image_memory(&memory, 0, &mut image_ref)
+ .map_err(|_| "Couldn't bind memory to image")?;
+
+ Ok(memory)
+ }?;
+
+ Ok((memory, image_ref))
+
+}
+
impl LoadedImage {
- /// Load the given image into a new buffer
- pub fn load(img: RgbaImage, device: &mut Device, adapter: &Adapter,
- command_queue: &mut CommandQueue,
- command_pool: &mut CommandPool) -> Result<LoadedImage, &'static str> {
- // Round up the size to align properly
- let initial_row_size = PIXEL_SIZE * (img.width() as usize);
+ pub fn new(device: &mut Device, adapter: &Adapter, format: Format, usage: ImgUsage, resources: SubresourceRange, width: usize, height: usize) -> Result<LoadedImage, &'static str> {
+ let (memory, image_ref) = create_image_view(device, adapter, format, usage, width, height)?;
+
+ // Create ImageView and sampler
+ let image_view = unsafe { device.create_image_view(
+ &image_ref,
+ ViewKind::D2,
+ format,
+ Swizzle::NO,
+ resources,
+ )}.map_err(|_| "Couldn't create the image view!")?;
+
+ Ok(LoadedImage {
+ image: ManuallyDrop::new(image_ref),
+ image_view: ManuallyDrop::new(image_view),
+ memory: ManuallyDrop::new(memory)
+ })
+ }
+
+ /// Load the given image
+ pub fn load(&mut self, img: RgbaImage, device: &mut Device, adapter: &Adapter, command_queue: &mut CommandQueue,
+ command_pool: &mut CommandPool) -> Result<(), &'static str> {
+ 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;
+ let total_size = (row_size * (img.height() as usize)) as u64;
debug_assert!(row_size as usize >= initial_row_size);
- let total_size = (row_size * img.height() as usize) as u64;
-
// Make a staging buffer
let (staging_buffer, staging_memory) = create_buffer(device, adapter, BufUsage::TRANSFER_SRC, MemProperties::CPU_VISIBLE, total_size)
.map_err(|_| "Couldn't create staging buffer")?;
@@ -86,43 +149,6 @@ impl LoadedImage {
device.unmap_memory(&staging_memory);
}
- // Make the image
- let mut image_ref = unsafe {
- use hal::image::{Kind, Tiling, Usage, ViewCapabilities};
-
- device.create_image(
- Kind::D2(img.width(), img.height(), 1, 1),
- 1,
- Format::Rgba8Srgb,
- Tiling::Optimal,
- Usage::TRANSFER_DST | Usage::SAMPLED,
- ViewCapabilities::empty()
- )
- }.map_err(|_| "Couldn't create image")?;
-
- // Allocate memory
- let memory = unsafe {
- let requirements = device.get_image_requirements(&image_ref);
-
- let memory_type_id = adapter.physical_device
- .memory_properties().memory_types
- .iter().enumerate()
- .find(|&(id, memory_type)| {
- requirements.type_mask & (1 << id) != 0 && memory_type.properties.contains(MemProperties::DEVICE_LOCAL)
- })
- .map(|(id, _)| MemoryTypeId(id))
- .ok_or("Couldn't find a memory type for image memory")?;
-
- let memory = device
- .allocate_memory(memory_type_id, requirements.size)
- .map_err(|_| "Couldn't allocate image memory")?;
-
- device.bind_image_memory(&memory, 0, &mut image_ref)
- .map_err(|_| "Couldn't bind memory to image")?;
-
- Ok(memory)
- }?;
-
// Copy from staging to image memory
let buf = unsafe {
use hal::command::{CommandBufferFlags, BufferImageCopy};
@@ -141,7 +167,7 @@ impl LoadedImage {
Access::TRANSFER_WRITE,
Layout::TransferDstOptimal,
),
- target: &image_ref,
+ target: &(*self.image),
families: None,
range: SubresourceRange {
aspects: Aspects::COLOR,
@@ -156,7 +182,7 @@ impl LoadedImage {
);
// Copy from buffer to image
- buf.copy_buffer_to_image(&staging_buffer, &image_ref,
+ buf.copy_buffer_to_image(&staging_buffer, &(*self.image),
Layout::TransferDstOptimal, &[
BufferImageCopy {
buffer_offset: 0,
@@ -187,7 +213,7 @@ impl LoadedImage {
Access::SHADER_READ,
Layout::ShaderReadOnlyOptimal,
),
- target: &image_ref,
+ target: &(*self.image),
families: None,
range: SubresourceRange {
aspects: Aspects::COLOR,
@@ -229,18 +255,49 @@ impl LoadedImage {
device.destroy_buffer(staging_buffer);
}
- // Create ImageView and sampler
- let image_view = unsafe { device.create_image_view(
- &image_ref,
- ViewKind::D2,
- Format::Rgba8Srgb,
- Swizzle::NO,
- SubresourceRange {
- aspects: Aspects::COLOR,
- levels: 0..1,
- layers: 0..1,
- },
- )}.map_err(|_| "Couldn't create the image view!")?;
+ Ok(())
+ }
+
+ /// Load the given image into a new buffer
+ pub fn load_into_new(img: RgbaImage, device: &mut Device, adapter: &Adapter,
+ command_queue: &mut CommandQueue,
+ command_pool: &mut CommandPool, format: Format, usage: ImgUsage) -> Result<LoadedImage, &'static str> {
+ let mut loaded_image = Self::new(device, adapter, format, usage | ImgUsage::TRANSFER_DST, SubresourceRange {
+ aspects: Aspects::COLOR,
+ levels: 0..1,
+ layers: 0..1,
+ }, img.width() as usize, img.height() as usize)?;
+ loaded_image.load(img, device, adapter, command_queue, command_pool)?;
+
+ Ok(loaded_image)
+ }
+
+ /// Properly frees/destroys all the objects in this struct
+ /// Dropping without doing this is a bad idea
+ pub fn deactivate(self, device: &Device) -> () {
+ unsafe {
+ use core::ptr::read;
+
+ device.destroy_image_view(ManuallyDrop::into_inner(read(&self.image_view)));
+ device.destroy_image(ManuallyDrop::into_inner(read(&self.image)));
+ device.free_memory(ManuallyDrop::into_inner(read(&self.memory)));
+ }
+ }
+}
+
+
+pub struct SampledImage {
+ pub image: ManuallyDrop<LoadedImage>,
+ pub sampler: ManuallyDrop<Sampler>
+}
+
+impl SampledImage {
+ pub fn new(device: &mut Device, adapter: &Adapter, format: Format, usage: ImgUsage, width: usize, height: usize) -> Result<SampledImage, &'static str> {
+ let image = LoadedImage::new(device, adapter, format, usage | ImgUsage::SAMPLED, SubresourceRange {
+ aspects: Aspects::COLOR,
+ levels: 0..1,
+ layers: 0..1,
+ }, width, height)?;
let sampler = unsafe {
use hal::image::{SamplerDesc, Filter, WrapMode};
@@ -251,24 +308,29 @@ impl LoadedImage {
))
}.map_err(|_| "Couldn't create the sampler!")?;
- Ok(LoadedImage {
- image: ManuallyDrop::new(image_ref),
- image_view: ManuallyDrop::new(image_view),
- sampler: ManuallyDrop::new(sampler),
- memory: ManuallyDrop::new(memory)
+ Ok(SampledImage {
+ image: ManuallyDrop::new(image),
+ sampler: ManuallyDrop::new(sampler)
})
}
- /// Properly frees/destroys all the objects in this struct
- /// Dropping without doing this is a bad idea
- pub fn deactivate(self, device: &Device) -> () {
+ pub fn load_into_new(img: RgbaImage, device: &mut Device, adapter: &Adapter,
+ command_queue: &mut CommandQueue,
+ command_pool: &mut CommandPool, format: Format, usage: ImgUsage) -> Result<SampledImage, &'static str> {
+ let mut sampled_image = SampledImage::new(device, adapter, format, usage | ImgUsage::TRANSFER_DST, img.width() as usize, img.height() as usize)?;
+ sampled_image.image.load(img, device, adapter, command_queue, command_pool)?;
+
+ Ok(sampled_image)
+
+ }
+
+ pub fn deactivate(self, device: &mut Device) -> () {
unsafe {
use core::ptr::read;
device.destroy_sampler(ManuallyDrop::into_inner(read(&self.sampler)));
- device.destroy_image_view(ManuallyDrop::into_inner(read(&self.image_view)));
- device.destroy_image(ManuallyDrop::into_inner(read(&self.image)));
- device.free_memory(ManuallyDrop::into_inner(read(&self.memory)));
+
+ ManuallyDrop::into_inner(read(&self.image)).deactivate(device);
}
}
-} \ No newline at end of file
+}