diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
commit | fb996488aa651cb2e7f46abc083c4318b47e77cd (patch) | |
tree | d1513d479b6069abca290e271f439cd1ef553383 /stockton-render/src/draw | |
parent | a82e16c92a026b2fbe3a40a21d7e690242e32ba6 (diff) |
wip refactor(render): more work on draw passes
Diffstat (limited to 'stockton-render/src/draw')
-rw-r--r-- | stockton-render/src/draw/buffers/dedicated_image.rs (renamed from stockton-render/src/draw/depth_buffer.rs) | 23 | ||||
-rw-r--r-- | stockton-render/src/draw/buffers/draw_buffers.rs (renamed from stockton-render/src/draw/draw_buffers.rs) | 11 | ||||
-rw-r--r-- | stockton-render/src/draw/buffers/mod.rs | 68 | ||||
-rw-r--r-- | stockton-render/src/draw/buffers/staged.rs (renamed from stockton-render/src/draw/buffer.rs) | 63 | ||||
-rw-r--r-- | stockton-render/src/draw/camera.rs | 64 | ||||
-rw-r--r-- | stockton-render/src/draw/context.rs | 28 | ||||
-rw-r--r-- | stockton-render/src/draw/draw_passes/cons.rs | 34 | ||||
-rw-r--r-- | stockton-render/src/draw/draw_passes/level.rs | 10 | ||||
-rw-r--r-- | stockton-render/src/draw/draw_passes/mod.rs | 21 | ||||
-rw-r--r-- | stockton-render/src/draw/mod.rs | 8 | ||||
-rw-r--r-- | stockton-render/src/draw/target.rs | 13 | ||||
-rw-r--r-- | stockton-render/src/draw/ui/render.rs | 2 |
12 files changed, 170 insertions, 175 deletions
diff --git a/stockton-render/src/draw/depth_buffer.rs b/stockton-render/src/draw/buffers/dedicated_image.rs index e3306c5..38a23c9 100644 --- a/stockton-render/src/draw/depth_buffer.rs +++ b/stockton-render/src/draw/buffers/dedicated_image.rs @@ -1,21 +1,22 @@ -use crate::draw::buffer::create_buffer; -use gfx_hal::{format::Aspects, memory::Properties, MemoryTypeId}; +//! A dedicated image. Used for depth buffers. + +use super::create_buffer; +use crate::draw::texture::{LoadableImage, PIXEL_SIZE}; +use crate::types::*; + +use std::{array::IntoIter, convert::TryInto, iter::empty, mem::ManuallyDrop}; + +use anyhow::{Context, Result}; use hal::{ buffer::Usage as BufUsage, - format::{Format, Swizzle}, + format::{Aspects, Format, Swizzle}, image::{SubresourceRange, Usage, Usage as ImgUsage, ViewKind}, memory, - memory::Segment, + memory::{Properties, Segment}, + MemoryTypeId, }; -use std::{array::IntoIter, convert::TryInto, iter::empty}; - -use crate::types::*; -use anyhow::{Context, Result}; -use std::mem::ManuallyDrop; use thiserror::Error; -use super::texture::{LoadableImage, PIXEL_SIZE}; - /// Holds an image that's loaded into GPU memory dedicated only to that image, bypassing the memory allocator. pub struct DedicatedLoadedImage { /// The GPU Image handle diff --git a/stockton-render/src/draw/draw_buffers.rs b/stockton-render/src/draw/buffers/draw_buffers.rs index 2d2fce4..5baec92 100644 --- a/stockton-render/src/draw/draw_buffers.rs +++ b/stockton-render/src/draw/buffers/draw_buffers.rs @@ -1,12 +1,11 @@ -use crate::{draw::buffer::StagedBuffer, types::*}; +//! A vertex and index buffer set for drawing + +use super::StagedBuffer; +use crate::types::*; + use anyhow::{Context, Result}; use hal::buffer::Usage; use std::mem::ManuallyDrop; -use stockton_types::{Vector2, Vector3}; - -/// Represents a point of a triangle, including UV and texture information. -#[derive(Debug, Clone, Copy)] -pub struct UvPoint(pub Vector3, pub i32, pub Vector2); /// Initial size of vertex buffer. TODO: Way of overriding this pub const INITIAL_VERT_SIZE: u64 = 3 * 3000; diff --git a/stockton-render/src/draw/buffers/mod.rs b/stockton-render/src/draw/buffers/mod.rs new file mode 100644 index 0000000..5093872 --- /dev/null +++ b/stockton-render/src/draw/buffers/mod.rs @@ -0,0 +1,68 @@ +//! All sorts of buffers + +use std::ops::IndexMut; + +use crate::{error::EnvironmentError, types::*}; + +use anyhow::{Context, Result}; +use hal::{ + buffer::Usage, + memory::{Properties, SparseFlags}, + MemoryTypeId, +}; + +mod dedicated_image; +mod draw_buffers; +mod staged; + +pub use dedicated_image::DedicatedLoadedImage; +pub use draw_buffers::DrawBuffers; +pub use staged::StagedBuffer; + +/// Create a buffer of the given specifications, allocating more device memory. +// TODO: Use a different memory allocator? +pub(crate) fn create_buffer( + device: &mut DeviceT, + adapter: &Adapter, + usage: Usage, + properties: Properties, + size: u64, +) -> Result<(BufferT, MemoryT)> { + let mut buffer = unsafe { device.create_buffer(size, usage, SparseFlags::empty()) } + .context("Error creating buffer")?; + + let requirements = unsafe { device.get_buffer_requirements(&buffer) }; + 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(properties) + }) + .map(|(id, _)| MemoryTypeId(id)) + .ok_or(EnvironmentError::NoMemoryTypes)?; + + let memory = unsafe { device.allocate_memory(memory_type_id, requirements.size) } + .context("Error allocating memory")?; + + unsafe { device.bind_buffer_memory(&memory, 0, &mut buffer) } + .context("Error binding memory to buffer")?; + + Ok((buffer, memory)) +} + +/// A buffer that can be modified by the CPU +pub trait ModifiableBuffer: IndexMut<usize> { + /// Get a handle to the underlying GPU buffer + fn get_buffer(&mut self) -> &BufferT; + + /// Commit all changes to GPU memory, returning a handle to the GPU buffer + fn commit<'a>( + &'a mut self, + device: &DeviceT, + command_queue: &mut QueueT, + command_pool: &mut CommandPoolT, + ) -> Result<&'a BufferT>; +} diff --git a/stockton-render/src/draw/buffer.rs b/stockton-render/src/draw/buffers/staged.rs index 77ac38a..f92c41d 100644 --- a/stockton-render/src/draw/buffer.rs +++ b/stockton-render/src/draw/buffers/staged.rs @@ -1,7 +1,14 @@ +//! A buffer that can be written to by the CPU using staging memory + +use super::{create_buffer, ModifiableBuffer}; +use crate::{error::EnvironmentError, types::*}; + use core::mem::{size_of, ManuallyDrop}; -use std::convert::TryInto; -use std::iter::{empty, once}; -use std::ops::{Index, IndexMut}; +use std::{ + convert::TryInto, + iter::{empty, once}, + ops::{Index, IndexMut}, +}; use anyhow::{Context, Result}; use hal::{ @@ -10,56 +17,6 @@ use hal::{ MemoryTypeId, }; -use crate::{error::EnvironmentError, types::*}; - -/// Create a buffer of the given specifications, allocating more device memory. -// TODO: Use a different memory allocator? -pub(crate) fn create_buffer( - device: &mut DeviceT, - adapter: &Adapter, - usage: Usage, - properties: Properties, - size: u64, -) -> Result<(BufferT, MemoryT)> { - let mut buffer = unsafe { device.create_buffer(size, usage, SparseFlags::empty()) } - .context("Error creating buffer")?; - - let requirements = unsafe { device.get_buffer_requirements(&buffer) }; - 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(properties) - }) - .map(|(id, _)| MemoryTypeId(id)) - .ok_or(EnvironmentError::NoMemoryTypes)?; - - let memory = unsafe { device.allocate_memory(memory_type_id, requirements.size) } - .context("Error allocating memory")?; - - unsafe { device.bind_buffer_memory(&memory, 0, &mut buffer) } - .context("Error binding memory to buffer")?; - - Ok((buffer, memory)) -} - -/// A buffer that can be modified by the CPU -pub trait ModifiableBuffer: IndexMut<usize> { - /// Get a handle to the underlying GPU buffer - fn get_buffer(&mut self) -> &BufferT; - - /// Commit all changes to GPU memory, returning a handle to the GPU buffer - fn commit<'a>( - &'a mut self, - device: &DeviceT, - command_queue: &mut QueueT, - command_pool: &mut CommandPoolT, - ) -> Result<&'a BufferT>; -} - /// A GPU buffer that is written to using a staging buffer pub struct StagedBuffer<'a, T: Sized> { /// CPU-visible buffer diff --git a/stockton-render/src/draw/camera.rs b/stockton-render/src/draw/camera.rs index a9d10f4..421b661 100644 --- a/stockton-render/src/draw/camera.rs +++ b/stockton-render/src/draw/camera.rs @@ -22,35 +22,35 @@ fn euler_to_direction(euler: &Vector3) -> Vector3 { ) } -#[system(for_each)] -#[filter(maybe_changed::<Transform>() | maybe_changed::<CameraSettings>())] -pub fn calc_vp_matrix<M: 'static + MinRenderFeatures>( - transform: &Transform, - settings: &CameraSettings, - #[resource] renderer: &mut Renderer<M>, -) { - let ratio = renderer.context.target_chain.properties.extent.width as f32 - / renderer.context.target_chain.properties.extent.height as f32; - // Get look direction from euler angles - let direction = euler_to_direction(&transform.rotation); - - // Converts world space to camera space - let view_matrix = look_at_lh( - &transform.position, - &(transform.position + direction), - &Vector3::new(0.0, 1.0, 0.0), - ); - - // Converts camera space to screen space - let projection_matrix = { - let mut temp = perspective_lh_zo(ratio, settings.fov, settings.near, settings.far); - - // Vulkan's co-ord system is different from OpenGLs - temp[(1, 1)] *= -1.0; - - temp - }; - - // Chain them together into a single matrix - renderer.context.vp_matrix = projection_matrix * view_matrix -} +// #[system(for_each)] +// #[filter(maybe_changed::<Transform>() | maybe_changed::<CameraSettings>())] +// pub fn calc_vp_matrix<M: 'static + MinRenderFeatures>( +// transform: &Transform, +// settings: &CameraSettings, +// #[resource] renderer: &mut Renderer<M>, +// ) { +// let ratio = renderer.context.target_chain.properties.extent.width as f32 +// / renderer.context.target_chain.properties.extent.height as f32; +// // Get look direction from euler angles +// let direction = euler_to_direction(&transform.rotation); + +// // Converts world space to camera space +// let view_matrix = look_at_lh( +// &transform.position, +// &(transform.position + direction), +// &Vector3::new(0.0, 1.0, 0.0), +// ); + +// // Converts camera space to screen space +// let projection_matrix = { +// let mut temp = perspective_lh_zo(ratio, settings.fov, settings.near, settings.far); + +// // Vulkan's co-ord system is different from OpenGLs +// temp[(1, 1)] *= -1.0; + +// temp +// }; + +// // Chain them together into a single matrix +// renderer.context.vp_matrix = projection_matrix * view_matrix +// } diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs index 2d3d92d..1a690fe 100644 --- a/stockton-render/src/draw/context.rs +++ b/stockton-render/src/draw/context.rs @@ -24,13 +24,12 @@ use crate::{ window::UiState, }; use stockton_levels::prelude::*; +use stockton_types::Session; /// Contains all the hal related stuff. /// In the end, this takes in a depth-sorted list of faces and a map file and renders them. // TODO: Settings for clear colour, buffer sizes, etc -pub struct RenderingContext<M: 'static + MinRenderFeatures, DP = LevelDrawPass<M>> { - pub map: Arc<RwLock<M>>, - +pub struct RenderingContext<DP> { // Parents for most of these things /// Vulkan Instance instance: ManuallyDrop<back::Instance>, @@ -60,19 +59,12 @@ pub struct RenderingContext<M: 'static + MinRenderFeatures, DP = LevelDrawPass<M pub(crate) pixels_per_point: f32, } -impl<M: 'static + MinRenderFeatures, DP> RenderingContext<M, DP> -where - DP: DrawPass<Input = M>, -{ - // TODO: Arbitrary drawpass input +impl<DP: DrawPass> RenderingContext<DP> { /// Create a new RenderingContext for the given window. pub fn new<ILDP: IntoDrawPass<DP>>( window: &Window, - _ui: &mut UiState, - map: M, idp: ILDP, ) -> Result<Self> { - let map = Arc::new(RwLock::new(map)); // Create surface let (instance, surface, mut adapters) = unsafe { let instance = @@ -174,7 +166,6 @@ where drop(device); Ok(RenderingContext { - map, instance: ManuallyDrop::new(instance), device: device_lock, @@ -231,8 +222,8 @@ where Ok(()) } - /// Draw all vertices in the buffer - pub fn draw_next_frame(&mut self) -> Result<()> { + /// Draw onto the next frame of the swapchain + pub fn draw_next_frame(&mut self, session: &Session) -> Result<()> { let mut device = self .device .write() @@ -241,20 +232,19 @@ where let mut queue = self .queue .write() - .map_err(|_| LockPoisoned::Map) - .context("Error getting map lock")?; - let map = self.map.read().or(Err(LockPoisoned::Map))?; + .map_err(|_| LockPoisoned::Queue) + .context("Error getting draw queue lock")?; // Level draw pass self.target_chain - .do_draw_with(&mut device, &mut queue, &*self.draw_pass, &*map) + .do_draw_with(&mut device, &mut queue, &*self.draw_pass, session) .context("Error preparing next target")?; Ok(()) } } -impl<M: 'static + MinRenderFeatures, LDP> core::ops::Drop for RenderingContext<M, LDP> { +impl<DP> core::ops::Drop for RenderingContext<DP> { fn drop(&mut self) { { self.device.write().unwrap().wait_idle().unwrap(); diff --git a/stockton-render/src/draw/draw_passes/cons.rs b/stockton-render/src/draw/draw_passes/cons.rs index 274bd76..76e2f32 100644 --- a/stockton-render/src/draw/draw_passes/cons.rs +++ b/stockton-render/src/draw/draw_passes/cons.rs @@ -1,22 +1,22 @@ //! Code for using multiple draw passes in place of just one //! Note that this can be extended to an arbitrary amount of draw passes. -use super::{DrawPass, DrawPassInput}; +use super::DrawPass; use crate::{draw::queue_negotiator::QueueNegotiator, types::*}; +use stockton_types::Session; + use anyhow::Result; /// One draw pass, then another. -struct ConsDrawPass<A: DrawPass, B: DrawPass> { +pub struct ConsDrawPass<A: DrawPass, B: DrawPass> { a: A, b: B, } impl<A: DrawPass, B: DrawPass> DrawPass for ConsDrawPass<A, B> { - type Input = ConsDrawPassInput<A::Input, B::Input>; - - fn queue_draw(&self, input: &Self::Input, cmd_buffer: &mut CommandBufferT) -> Result<()> { - self.a.queue_draw(&input.a, cmd_buffer)?; - self.b.queue_draw(&input.b, cmd_buffer)?; + fn queue_draw(&self, session: &Session, cmd_buffer: &mut CommandBufferT) -> Result<()> { + self.a.queue_draw(&session, cmd_buffer)?; + self.b.queue_draw(&session, cmd_buffer)?; Ok(()) } @@ -34,21 +34,12 @@ impl<A: DrawPass, B: DrawPass> DrawPass for ConsDrawPass<A, B> { } } -/// Input for a ConsDrawPass. -struct ConsDrawPassInput<A, B> { - pub a: A, - pub b: B, -} - -impl<A: DrawPassInput, B: DrawPassInput> DrawPassInput for ConsDrawPassInput<A, B> {} - /// A draw pass that does nothing. Can be used at the end of sequences if there's an odd number of draw passes. -struct NilDrawPass; +pub struct NilDrawPass; impl DrawPass for NilDrawPass { - type Input = NilDrawPassInput; - fn queue_draw(&self, _input: &Self::Input, _cmd_buffer: &mut CommandBufferT) -> Result<()> { + fn queue_draw(&self, _input: &Session, _cmd_buffer: &mut CommandBufferT) -> Result<()> { Ok(()) } @@ -58,9 +49,4 @@ impl DrawPass for NilDrawPass { ) -> Result<Vec<(&'a QueueFamilyT, Vec<f32>)>> { Ok(vec![]) } -} - -/// Input for a NilDrawPass. -struct NilDrawPassInput; - -impl DrawPassInput for NilDrawPassInput {} +}
\ No newline at end of file diff --git a/stockton-render/src/draw/draw_passes/level.rs b/stockton-render/src/draw/draw_passes/level.rs index afcb703..b968a1a 100644 --- a/stockton-render/src/draw/draw_passes/level.rs +++ b/stockton-render/src/draw/draw_passes/level.rs @@ -1,6 +1,6 @@ //! Minimal code for drawing any level, based on traits from stockton-levels -use super::{DrawPass, DrawPassInput, IntoDrawPass}; +use super::{DrawPass, IntoDrawPass}; use crate::{ draw::{queue_negotiator::QueueNegotiator, target::SwapchainProperties, texture::TextureRepo}, error::EnvironmentError, @@ -30,16 +30,10 @@ pub struct LevelDrawPass<M: MinRenderFeatures> { _d: PhantomData<M>, } -/// Any map can be used as draw pass input. -/// TODO: Restrict this based on the type of the renderer. -impl<T: MinRenderFeatures> DrawPassInput for T {} - impl<M: MinRenderFeatures> DrawPass for LevelDrawPass<M> { - type Input = M; - fn queue_draw( &self, - _file: &Self::Input, + _input: &Session, _cmd_buffer: &mut crate::types::CommandBufferT, ) -> anyhow::Result<()> { todo!() diff --git a/stockton-render/src/draw/draw_passes/mod.rs b/stockton-render/src/draw/draw_passes/mod.rs index 76dd8d6..566a64b 100644 --- a/stockton-render/src/draw/draw_passes/mod.rs +++ b/stockton-render/src/draw/draw_passes/mod.rs @@ -1,26 +1,23 @@ //! Traits and common draw passes. +use super::{queue_negotiator::QueueNegotiator, target::SwapchainProperties}; +use crate::types::*; +use stockton_types::Session; -mod cons; -mod level; use std::sync::{Arc, RwLock}; -pub use level::LevelDrawPass; - -use super::{queue_negotiator::QueueNegotiator, target::SwapchainProperties}; -use crate::types::*; use anyhow::Result; -/// Type can be used as input to a draw pass. This requires it being available from only the resources at draw time. -pub trait DrawPassInput {} +mod cons; +mod level; + +pub use level::LevelDrawPass; +pub use cons::{ConsDrawPass, NilDrawPass}; /// One of several 'passes' that draw on each frame. pub trait DrawPass { - /// Extra input required for this draw pass. - type Input: DrawPassInput; - /// Queue any necessary draw commands to cmd_buffer /// This should assume the command buffer isn't in the middle of a renderpass, and should leave it as such. - fn queue_draw(&self, input: &Self::Input, cmd_buffer: &mut CommandBufferT) -> Result<()>; + fn queue_draw(&self, session: &Session, cmd_buffer: &mut CommandBufferT) -> Result<()>; /// This function should ask the queue negotatior to find families for any auxilary operations this draw pass needs to perform /// For example, .find(&TexLoadQueue) diff --git a/stockton-render/src/draw/mod.rs b/stockton-render/src/draw/mod.rs index 5e1d2cd..411e835 100644 --- a/stockton-render/src/draw/mod.rs +++ b/stockton-render/src/draw/mod.rs @@ -2,17 +2,15 @@ pub mod target; -mod buffer; +mod buffers; mod camera; mod context; -mod depth_buffer; -mod draw_buffers; pub mod draw_passes; mod queue_negotiator; mod texture; mod ui; mod utils; -pub use self::camera::calc_vp_matrix_system; pub use self::context::RenderingContext; -pub use self::draw_buffers::UvPoint; + +pub use self::draw_passes::*; diff --git a/stockton-render/src/draw/target.rs b/stockton-render/src/draw/target.rs index 754bad3..c46feb5 100644 --- a/stockton-render/src/draw/target.rs +++ b/stockton-render/src/draw/target.rs @@ -6,15 +6,17 @@ use std::{ }; use hal::{ + command::CommandBufferFlags, format::{ChannelType, Format, ImageFeature}, image::{Extent, Usage as ImgUsage}, pso::Viewport, window::{CompositeAlphaMode, Extent2D, PresentMode, SwapchainConfig}, }; -use super::{depth_buffer::DedicatedLoadedImage, draw_passes::DrawPass}; +use super::{buffers::DedicatedLoadedImage, draw_passes::DrawPass}; use crate::{error::EnvironmentError, types::*}; use anyhow::{Context, Result}; +use stockton_types::Session; #[derive(Debug, Clone)] pub struct SwapchainProperties { @@ -249,7 +251,7 @@ impl TargetChain { device: &mut DeviceT, command_queue: &mut QueueT, dp: &DP, - dpi: &DP::Input, + session: &Session, ) -> Result<()> { self.last_syncs = (self.last_syncs + 1) % self.sync_objects.len(); self.last_image = (self.last_image + 1) % self.targets.len() as u32; @@ -275,9 +277,12 @@ impl TargetChain { }; // Record commands - dp.queue_draw(dpi, &mut target.cmd_buffer) - .context("Error in draw pass")?; unsafe { + target.cmd_buffer.begin_primary(CommandBufferFlags::empty()); + + dp.queue_draw(session, &mut target.cmd_buffer) + .context("Error in draw pass")?; + target.cmd_buffer.finish(); } diff --git a/stockton-render/src/draw/ui/render.rs b/stockton-render/src/draw/ui/render.rs index a3e0f04..009a1b7 100644 --- a/stockton-render/src/draw/ui/render.rs +++ b/stockton-render/src/draw/ui/render.rs @@ -2,7 +2,7 @@ use crate::draw::texture::TextureRepo; use hal::pso::{Rect, ShaderStageFlags}; use super::UiPoint; -use crate::draw::draw_buffers::DrawBuffers; +use crate::draw::buffers::DrawBuffers; use crate::types::*; use crate::UiState; use anyhow::{anyhow, Result}; |