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 | 6ab13f2d0cb345795f761181a06777ade61ff09c (patch) | |
tree | 42007acef9846d5e79f1bf418a96647f34b530d1 /stockton-render/src/draw/context.rs | |
parent | ccf0074b08ce835cf22e7d46153d1cb3f3d06d32 (diff) |
refactor(all): separate rendering from framework
stockton-passes is mostly just a stand-in until this is
properly separated
Diffstat (limited to 'stockton-render/src/draw/context.rs')
-rw-r--r-- | stockton-render/src/draw/context.rs | 266 |
1 files changed, 0 insertions, 266 deletions
diff --git a/stockton-render/src/draw/context.rs b/stockton-render/src/draw/context.rs deleted file mode 100644 index 65dcff6..0000000 --- a/stockton-render/src/draw/context.rs +++ /dev/null @@ -1,266 +0,0 @@ -//! Deals with all the Vulkan/HAL details. -//! This relies on draw passes for the actual drawing logic. - -use std::{ - mem::ManuallyDrop, - ptr::read, - sync::{Arc, RwLock}, -}; - -use anyhow::{Context, Result}; -use hal::pool::CommandPoolCreateFlags; -use log::debug; - -use winit::window::Window; - -use super::{ - draw_passes::{DrawPass, IntoDrawPass}, - queue_negotiator::{DrawQueue, QueueNegotiator}, - target::{SwapchainProperties, TargetChain}, -}; -use crate::{ - error::{EnvironmentError, LockPoisoned}, - types::*, -}; - -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<DP> { - // Parents for most of these things - /// Vulkan Instance - instance: ManuallyDrop<back::Instance>, - - /// Device we're using - device: Arc<RwLock<DeviceT>>, - - /// Adapter we're using - adapter: Adapter, - - /// Swapchain and stuff - pub(crate) target_chain: ManuallyDrop<TargetChain>, - - // Command pool and buffers - /// The command pool used for our buffers - cmd_pool: ManuallyDrop<CommandPoolT>, - - /// The queue to use for drawing - queue: Arc<RwLock<QueueT>>, - - /// Deals with drawing logic, and holds any data required for drawing. - draw_pass: ManuallyDrop<DP>, - - pub(crate) pixels_per_point: f32, -} - -impl<DP: DrawPass> RenderingContext<DP> { - /// Create a new RenderingContext for the given window. - pub fn new<IDP: IntoDrawPass<DP>>( - window: &Window, - session: &Session, - idp: IDP, - ) -> Result<Self> { - // Create surface - let (instance, surface, mut adapters) = unsafe { - let instance = - back::Instance::create("stockton", 1).context("Error creating vulkan instance")?; - let surface = instance - .create_surface(window) - .context("Error creating surface")?; - let adapters = instance.enumerate_adapters(); - - (instance, surface, adapters) - }; - - // TODO: Properly figure out which adapter to use - let adapter = adapters.remove(0); - - // Queue Negotiator - let mut queue_families_specs = Vec::new(); - let (mut queue_negotiator, surface) = { - let dq: DrawQueue = DrawQueue { surface }; - - let mut qn = QueueNegotiator::new(); - - // Draw Queue - qn.find(&adapter, &dq) - .context("Couldn't find draw queue family")?; - queue_families_specs.push( - qn.family_spec::<DrawQueue>(&adapter.queue_families, 1) - .context("Couldn't find draw queue family")?, - ); - - // Auxiliary queues for DP - queue_families_specs.extend( - IDP::find_aux_queues(&adapter, &mut qn) - .context("Level pass couldn't populate queue negotiator")?, - ); - - (qn, dq.surface) - }; - - // Device & Queue groups - let (device_lock, queue_groups) = { - // TODO: This sucks, but hal is restrictive on how we can pass this specific argument. - let queue_families_specs_real: Vec<_> = queue_families_specs - .iter() - .map(|(qf, ns)| (*qf, ns.as_slice())) - .collect(); - - let gpu = unsafe { - adapter - .physical_device - .open(queue_families_specs_real.as_slice(), hal::Features::empty()) - .context("Error opening logical device")? - }; - - (Arc::new(RwLock::new(gpu.device)), gpu.queue_groups) - }; - - queue_negotiator.set_queue_groups(queue_groups); - - // Figure out what our swapchain will look like - let swapchain_properties = SwapchainProperties::find_best(&adapter, &surface) - .context("Error getting properties for swapchain")?; - - // Draw pass - let dp = idp - .init( - session, - &adapter, - device_lock.clone(), - &mut queue_negotiator, - &swapchain_properties, - ) - .context("Error initialising draw pass")?; - - // Lock device - let mut device = device_lock - .write() - .map_err(|_| LockPoisoned::Device) - .context("Error getting device lock")?; - - debug!("Detected swapchain properties: {:?}", swapchain_properties); - - // Command pool - let mut cmd_pool = unsafe { - device.create_command_pool( - queue_negotiator - .family::<DrawQueue>() - .ok_or(EnvironmentError::NoSuitableFamilies)?, - CommandPoolCreateFlags::RESET_INDIVIDUAL, - ) - } - .context("Error creating draw command pool")?; - - // Swapchain and associated resources - let target_chain = TargetChain::new( - &mut device, - &adapter, - surface, - &mut cmd_pool, - swapchain_properties, - ) - .context("Error creating target chain")?; - - // Unlock device - drop(device); - - Ok(RenderingContext { - instance: ManuallyDrop::new(instance), - - device: device_lock, - adapter, - - queue: queue_negotiator - .get_queue::<DrawQueue>() - .ok_or(EnvironmentError::NoQueues) - .context("Error getting draw queue")?, - - draw_pass: ManuallyDrop::new(dp), - target_chain: ManuallyDrop::new(target_chain), - cmd_pool: ManuallyDrop::new(cmd_pool), - - // pixels_per_point: window.scale_factor() as f32, - pixels_per_point: window.scale_factor() as f32, - }) - } - - /// If this function fails the whole context is probably dead - /// # Safety - /// The context must not be used while this is being called - pub unsafe fn handle_surface_change(&mut self) -> Result<()> { - let mut device = self - .device - .write() - .map_err(|_| LockPoisoned::Device) - .context("Error getting device lock")?; - - device - .wait_idle() - .context("Error waiting for device to become idle")?; - - let surface = ManuallyDrop::into_inner(read(&self.target_chain)) - .deactivate_with_recyling(&mut device, &mut self.cmd_pool); - - let properties = SwapchainProperties::find_best(&self.adapter, &surface) - .context("Error finding best swapchain properties")?; - - // TODO: Notify draw passes - - self.target_chain = ManuallyDrop::new( - TargetChain::new( - &mut device, - &self.adapter, - surface, - &mut self.cmd_pool, - properties, - ) - .context("Error creating target chain")?, - ); - Ok(()) - } - - /// Draw onto the next frame of the swapchain - pub fn draw_next_frame(&mut self, session: &Session) -> Result<()> { - let mut device = self - .device - .write() - .map_err(|_| LockPoisoned::Device) - .context("Error getting device lock")?; - let mut queue = self - .queue - .write() - .map_err(|_| LockPoisoned::Queue) - .context("Error getting draw queue lock")?; - - // Level draw pass - self.target_chain - .do_draw_with(&mut device, &mut queue, &mut *self.draw_pass, session) - .context("Error preparing next target")?; - - Ok(()) - } -} - -impl<DP> core::ops::Drop for RenderingContext<DP> { - fn drop(&mut self) { - { - self.device.write().unwrap().wait_idle().unwrap(); - } - - unsafe { - let mut device = self.device.write().unwrap(); - - ManuallyDrop::into_inner(read(&self.target_chain)).deactivate( - &mut self.instance, - &mut device, - &mut self.cmd_pool, - ); - - device.destroy_command_pool(ManuallyDrop::into_inner(read(&self.cmd_pool))); - } - } -} |