aboutsummaryrefslogtreecommitdiff
path: root/stockton-skeleton/src/target.rs
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-25 17:44:24 +0100
committertcmal <me@aria.rip>2024-08-25 17:44:24 +0100
commit59b5e4463d6eec0de27d6da6c85f8c719674e966 (patch)
treed1833c4702410df6f976d95ba5c9169b03125b35 /stockton-skeleton/src/target.rs
parent6b8395152b8e0c7ddd714e195e4e92d464b8147c (diff)
refactor(skeleton): clean up targetchain
Diffstat (limited to 'stockton-skeleton/src/target.rs')
-rw-r--r--stockton-skeleton/src/target.rs228
1 files changed, 36 insertions, 192 deletions
diff --git a/stockton-skeleton/src/target.rs b/stockton-skeleton/src/target.rs
index c3a212e..647aa96 100644
--- a/stockton-skeleton/src/target.rs
+++ b/stockton-skeleton/src/target.rs
@@ -1,4 +1,12 @@
//! Resources needed for drawing on the screen, including sync objects
+//! You likely won't need to interact with this directly
+
+use crate::{
+ context::ContextProperties,
+ draw_passes::{DrawPass, Singular},
+ types::*,
+};
+use stockton_types::Session;
use std::{
borrow::Borrow,
@@ -8,177 +16,53 @@ use std::{
use hal::{
command::CommandBufferFlags,
- format::{ChannelType, Format, ImageFeature},
- image::{Extent, FramebufferAttachment, Usage as ImgUsage, ViewCapabilities},
- pso::Viewport,
- window::{CompositeAlphaMode, Extent2D, PresentMode, SwapchainConfig},
+ image::Usage as ImgUsage,
+ window::{Extent2D, SwapchainConfig},
};
-use super::draw_passes::DrawPass;
-use crate::{draw_passes::Singular, error::EnvironmentError, types::*};
use anyhow::{Context, Result};
-use stockton_types::Session;
-
-#[derive(Debug, Clone)]
-pub struct SwapchainProperties {
- pub format: Format,
- pub depth_format: Format,
- pub present_mode: PresentMode,
- pub composite_alpha_mode: CompositeAlphaMode,
- pub viewport: Viewport,
- pub extent: Extent,
- pub image_count: u32,
-}
-
-impl SwapchainProperties {
- pub fn find_best(
- adapter: &Adapter,
- surface: &SurfaceT,
- ) -> Result<SwapchainProperties, EnvironmentError> {
- let caps = surface.capabilities(&adapter.physical_device);
- let formats = surface.supported_formats(&adapter.physical_device);
-
- // Find which settings we'll actually use based on preset preferences
- let format = match formats {
- Some(formats) => formats
- .iter()
- .find(|format| format.base_format().1 == ChannelType::Srgb)
- .copied()
- .ok_or(EnvironmentError::ColorFormat),
- None => Ok(Format::Rgba8Srgb),
- }?;
-
- let depth_format = *[
- Format::D32SfloatS8Uint,
- Format::D24UnormS8Uint,
- Format::D32Sfloat,
- ]
- .iter()
- .find(|format| {
- format.is_depth()
- && adapter
- .physical_device
- .format_properties(Some(**format))
- .optimal_tiling
- .contains(ImageFeature::DEPTH_STENCIL_ATTACHMENT)
- })
- .ok_or(EnvironmentError::DepthFormat)?;
-
- let present_mode = [
- PresentMode::MAILBOX,
- PresentMode::FIFO,
- PresentMode::RELAXED,
- PresentMode::IMMEDIATE,
- ]
- .iter()
- .cloned()
- .find(|pm| caps.present_modes.contains(*pm))
- .ok_or(EnvironmentError::PresentMode)?;
-
- let composite_alpha_mode = [
- CompositeAlphaMode::OPAQUE,
- CompositeAlphaMode::INHERIT,
- CompositeAlphaMode::PREMULTIPLIED,
- CompositeAlphaMode::POSTMULTIPLIED,
- ]
- .iter()
- .cloned()
- .find(|ca| caps.composite_alpha_modes.contains(*ca))
- .ok_or(EnvironmentError::CompositeAlphaMode)?;
-
- let extent = caps.extents.end().to_extent(); // Size
- let viewport = Viewport {
- rect: extent.rect(),
- depth: 0.0..1.0,
- };
-
- Ok(SwapchainProperties {
- format,
- depth_format,
- present_mode,
- composite_alpha_mode,
- extent,
- viewport,
- image_count: if present_mode == PresentMode::MAILBOX {
- ((*caps.image_count.end()) - 1).min((*caps.image_count.start()).max(3))
- } else {
- ((*caps.image_count.end()) - 1).min((*caps.image_count.start()).max(2))
- },
- })
- }
-
- pub fn framebuffer_attachment(&self) -> FramebufferAttachment {
- FramebufferAttachment {
- usage: ImgUsage::COLOR_ATTACHMENT,
- format: self.format,
- view_caps: ViewCapabilities::empty(),
- }
- }
-}
+/// Holds our swapchain and other resources for drawing each frame
pub struct TargetChain {
/// Surface we're targeting
surface: ManuallyDrop<SurfaceT>,
- properties: SwapchainProperties,
-
- /// Resources tied to each target frame in the swapchain
- targets: Box<[TargetResources]>,
-
- /// Sync objects used in drawing
- /// These are seperated from the targets because we don't necessarily always match up indexes
- sync_objects: Box<[SyncObjects]>,
- /// The last set of sync objects used
- last_syncs: usize,
+ /// Command buffers and sync objects used when drawing
+ resources: Box<[(CommandBufferT, SyncObjects)]>,
/// Last image index of the swapchain drawn to
- last_image: u32,
+ last_resources: usize,
}
impl TargetChain {
pub fn new(
device: &mut DeviceT,
- adapter: &Adapter,
mut surface: SurfaceT,
cmd_pool: &mut CommandPoolT,
- properties: SwapchainProperties,
+ properties: &ContextProperties,
) -> Result<TargetChain> {
- let caps = surface.capabilities(&adapter.physical_device);
-
- // Number of frames to pre-render
- let image_count = if properties.present_mode == PresentMode::MAILBOX {
- ((*caps.image_count.end()) - 1).min((*caps.image_count.start()).max(3))
- } else {
- ((*caps.image_count.end()) - 1).min((*caps.image_count.start()).max(2))
- };
-
- // Swap config
+ // Create swapchain
let swap_config = SwapchainConfig {
present_mode: properties.present_mode,
composite_alpha_mode: properties.composite_alpha_mode,
- format: properties.format,
+ format: properties.color_format,
extent: Extent2D {
width: properties.extent.width,
height: properties.extent.height,
},
- image_count,
+ image_count: properties.image_count,
image_layers: 1,
image_usage: ImgUsage::COLOR_ATTACHMENT,
};
- let _fat = swap_config.framebuffer_attachment();
- let mut targets: Vec<TargetResources> =
- Vec::with_capacity(swap_config.image_count as usize);
- let mut sync_objects: Vec<SyncObjects> =
- Vec::with_capacity(swap_config.image_count as usize);
+ // Create command buffers and sync objects
+ let mut resources = Vec::with_capacity(swap_config.image_count as usize);
for _ in 0..swap_config.image_count {
- targets.push(
- TargetResources::new(device, cmd_pool, &properties)
- .context("Error creating target resources")?,
- );
-
- sync_objects.push(SyncObjects::new(device).context("Error creating sync objects")?);
+ resources.push((
+ unsafe { cmd_pool.allocate_one(hal::command::Level::Primary) },
+ SyncObjects::new(device).context("Error creating sync objects")?,
+ ));
}
// Configure Swapchain
@@ -190,11 +74,8 @@ impl TargetChain {
Ok(TargetChain {
surface: ManuallyDrop::new(surface),
- targets: targets.into_boxed_slice(),
- sync_objects: sync_objects.into_boxed_slice(),
- properties,
- last_syncs: (image_count - 1) as usize, // This means the next one to be used is index 0
- last_image: 0,
+ resources: resources.into_boxed_slice(),
+ last_resources: (properties.image_count - 1) as usize, // This means the next one to be used is index 0
})
}
@@ -218,12 +99,10 @@ impl TargetChain {
) -> SurfaceT {
use core::ptr::read;
unsafe {
- for i in 0..self.targets.len() {
- read(&self.targets[i]).deactivate(device, cmd_pool);
- }
-
- for i in 0..self.sync_objects.len() {
- read(&self.sync_objects[i]).deactivate(device);
+ for i in 0..self.resources.len() {
+ let (cmd_buf, syncs) = read(&self.resources[i]);
+ cmd_pool.free(once(cmd_buf));
+ syncs.deactivate(device);
}
self.surface.unconfigure_swapchain(device);
@@ -239,11 +118,9 @@ impl TargetChain {
dp: &mut DP,
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;
+ self.last_resources = (self.last_resources + 1) % self.resources.len();
- let syncs = &mut self.sync_objects[self.last_syncs];
- let target = &mut self.targets[self.last_image as usize];
+ let (cmd_buffer, syncs) = &mut self.resources[self.last_resources];
// Get the image
let (img, _) = unsafe {
@@ -264,18 +141,18 @@ impl TargetChain {
// Record commands
unsafe {
- target.cmd_buffer.begin_primary(CommandBufferFlags::empty());
+ cmd_buffer.begin_primary(CommandBufferFlags::empty());
- dp.queue_draw(session, img.borrow(), &mut target.cmd_buffer)
+ dp.queue_draw(session, img.borrow(), cmd_buffer)
.context("Error in draw pass")?;
- target.cmd_buffer.finish();
+ cmd_buffer.finish();
}
// Submit it
unsafe {
command_queue.submit(
- once(&*target.cmd_buffer),
+ once(&*cmd_buffer),
empty(),
once(&*syncs.render_complete),
Some(&mut syncs.present_complete),
@@ -287,39 +164,6 @@ impl TargetChain {
Ok(())
}
-
- /// Get a reference to the target chain's properties.
- pub fn properties(&self) -> &SwapchainProperties {
- &self.properties
- }
-}
-
-/// Resources for a single target frame, including sync objects
-pub struct TargetResources {
- /// Command buffer to use when drawing
- pub cmd_buffer: ManuallyDrop<CommandBufferT>,
-}
-
-impl TargetResources {
- pub fn new(
- _device: &mut DeviceT,
- cmd_pool: &mut CommandPoolT,
- _properties: &SwapchainProperties,
- ) -> Result<TargetResources> {
- // Command Buffer
- let cmd_buffer = unsafe { cmd_pool.allocate_one(hal::command::Level::Primary) };
-
- Ok(TargetResources {
- cmd_buffer: ManuallyDrop::new(cmd_buffer),
- })
- }
-
- pub fn deactivate(self, _device: &mut DeviceT, cmd_pool: &mut CommandPoolT) {
- use core::ptr::read;
- unsafe {
- cmd_pool.free(once(ManuallyDrop::into_inner(read(&self.cmd_buffer))));
- }
- }
}
pub struct SyncObjects {