aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi.rs11
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/runtime.rs223
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/swapchain.rs220
-rw-r--r--xtask/src/main.rs1
4 files changed, 237 insertions, 218 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi.rs b/adapters/fparkan-render-vulkan/src/ffi.rs
index 8b5312e..a2daef7 100644
--- a/adapters/fparkan-render-vulkan/src/ffi.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi.rs
@@ -33,6 +33,7 @@ mod runtime;
mod smoke;
mod smoke_types;
mod surface;
+mod swapchain;
mod swapchain_resources;
mod validation;
@@ -50,11 +51,9 @@ use self::resources::{
VulkanFrameSync,
};
pub use self::runtime::{
- create_vulkan_logical_device_probe, create_vulkan_swapchain_probe,
- create_vulkan_swapchain_probe_for_extent, probe_vulkan_runtime_capabilities,
+ create_vulkan_logical_device_probe, probe_vulkan_runtime_capabilities,
VulkanLogicalDeviceError, VulkanLogicalDeviceProbe, VulkanLogicalDeviceReport,
- VulkanRuntimeCapabilityError, VulkanRuntimeCapabilityProbe, VulkanSwapchainProbe,
- VulkanSwapchainProbeError, VulkanSwapchainReport,
+ VulkanRuntimeCapabilityError, VulkanRuntimeCapabilityProbe,
};
pub use self::smoke_types::{
VulkanSmokeFrameOutcome, VulkanSmokeRenderer, VulkanSmokeRendererCreateInfo,
@@ -66,6 +65,10 @@ pub use self::surface::{
create_vulkan_surface_probe, plan_vulkan_surface, render_surface_plan_json, VulkanSurfaceError,
VulkanSurfacePlan, VulkanSurfaceProbe,
};
+pub use self::swapchain::{
+ create_vulkan_swapchain_probe, create_vulkan_swapchain_probe_for_extent, VulkanSwapchainProbe,
+ VulkanSwapchainProbeError, VulkanSwapchainReport,
+};
use self::swapchain_resources::{
create_swapchain_resources, destroy_swapchain_resources, VulkanSwapchainResources,
};
diff --git a/adapters/fparkan-render-vulkan/src/ffi/runtime.rs b/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
index 56d4041..b1c98df 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
@@ -1,14 +1,14 @@
#![allow(unsafe_code)]
-use ash::{khr::swapchain, vk};
+use ash::vk;
use std::ffi::{CStr, CString};
use super::{VulkanInstanceProbe, VulkanSurfaceProbe};
use crate::policy::{
- compare_reports, plan_vulkan_swapchain, select_composite_alpha, validate_device,
- VulkanCapabilityError, VulkanCapabilityReport, VulkanDeviceType, VulkanPhysicalDeviceRecord,
- VulkanQueueFamily, VulkanSurfaceFormat, VulkanSwapchainError, VulkanSwapchainPlan,
- VulkanSwapchainRequest, VulkanSwapchainSurfaceCapabilities,
+ compare_reports, plan_vulkan_swapchain, validate_device, VulkanCapabilityError,
+ VulkanCapabilityReport, VulkanDeviceType, VulkanPhysicalDeviceRecord, VulkanQueueFamily,
+ VulkanSurfaceFormat, VulkanSwapchainError, VulkanSwapchainPlan, VulkanSwapchainRequest,
+ VulkanSwapchainSurfaceCapabilities,
};
/// Live Vulkan device/surface capability probe.
@@ -86,46 +86,6 @@ pub struct VulkanLogicalDeviceReport {
pub enabled_extensions: Vec<String>,
}
-/// Created Vulkan swapchain probe.
-pub struct VulkanSwapchainProbe {
- loader: swapchain::Device,
- swapchain: vk::SwapchainKHR,
- /// Deterministic swapchain creation report.
- pub report: VulkanSwapchainReport,
-}
-
-impl Drop for VulkanSwapchainProbe {
- fn drop(&mut self) {
- // SAFETY: The swapchain was created by this probe and is destroyed once during drop.
- unsafe { self.loader.destroy_swapchain(self.swapchain, None) };
- }
-}
-
-impl VulkanSwapchainProbe {
- /// Returns the live swapchain handle.
- #[must_use]
- pub fn swapchain(&self) -> vk::SwapchainKHR {
- self.swapchain
- }
-
- /// Returns the swapchain extension loader for this live swapchain.
- #[must_use]
- pub fn loader(&self) -> &swapchain::Device {
- &self.loader
- }
-}
-
-/// Runtime swapchain creation report.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct VulkanSwapchainReport {
- /// Report schema version.
- pub schema: u32,
- /// Deterministic swapchain policy used for creation.
- pub plan: VulkanSwapchainPlan,
- /// Number of images returned by `vkGetSwapchainImagesKHR`.
- pub image_count: u32,
-}
-
/// Live Vulkan device/surface capability probe error.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VulkanRuntimeCapabilityError {
@@ -254,50 +214,6 @@ impl std::fmt::Display for VulkanLogicalDeviceError {
impl std::error::Error for VulkanLogicalDeviceError {}
-/// Vulkan swapchain creation error.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum VulkanSwapchainProbeError {
- /// Live runtime capability probing failed before swapchain creation.
- Runtime(VulkanRuntimeCapabilityError),
- /// Deterministic swapchain planning failed before create.
- Plan(VulkanSwapchainError),
- /// Surface capability query failed.
- SurfaceCapabilitiesFailed {
- /// Vulkan result.
- result: vk::Result,
- },
- /// Swapchain creation failed.
- CreateFailed {
- /// Vulkan result.
- result: vk::Result,
- },
- /// Swapchain image query failed.
- ImagesFailed {
- /// Vulkan result.
- result: vk::Result,
- },
-}
-
-impl std::fmt::Display for VulkanSwapchainProbeError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::Runtime(error) => write!(f, "{error}"),
- Self::Plan(error) => write!(f, "{error}"),
- Self::SurfaceCapabilitiesFailed { result } => {
- write!(f, "Vulkan surface capabilities query failed: {result:?}")
- }
- Self::CreateFailed { result } => {
- write!(f, "Vulkan swapchain creation failed: {result:?}")
- }
- Self::ImagesFailed { result } => {
- write!(f, "Vulkan swapchain image query failed: {result:?}")
- }
- }
- }
-}
-
-impl std::error::Error for VulkanSwapchainProbeError {}
-
/// Probes live Vulkan device, queue, surface and swapchain capabilities.
///
/// # Errors
@@ -377,127 +293,6 @@ pub fn create_vulkan_logical_device_probe(
})
}
-/// Creates a Vulkan swapchain for the live logical device and surface.
-///
-/// # Errors
-///
-/// Returns [`VulkanSwapchainProbeError`] when live surface capability queries,
-/// swapchain creation, or swapchain image enumeration fails.
-pub fn create_vulkan_swapchain_probe(
- instance: &VulkanInstanceProbe,
- surface: &VulkanSurfaceProbe,
- device: &VulkanLogicalDeviceProbe,
-) -> Result<VulkanSwapchainProbe, VulkanSwapchainProbeError> {
- create_vulkan_swapchain_probe_for_extent(
- instance,
- surface,
- device,
- device.runtime.swapchain.extent,
- vk::SwapchainKHR::null(),
- )
-}
-
-/// Creates a Vulkan swapchain for the live logical device and surface at a specific extent.
-///
-/// # Errors
-///
-/// Returns [`VulkanSwapchainProbeError`] when live surface capability queries,
-/// swapchain creation, or swapchain image enumeration fails.
-pub fn create_vulkan_swapchain_probe_for_extent(
- instance: &VulkanInstanceProbe,
- surface: &VulkanSurfaceProbe,
- device: &VulkanLogicalDeviceProbe,
- drawable_extent: (u32, u32),
- old_swapchain: vk::SwapchainKHR,
-) -> Result<VulkanSwapchainProbe, VulkanSwapchainProbeError> {
- let raw_capabilities = {
- // SAFETY: The physical device and surface are live query inputs and no handles are retained.
- unsafe {
- surface
- .loader
- .get_physical_device_surface_capabilities(device.physical_device(), surface.surface)
- }
- }
- .map_err(|error| VulkanSwapchainProbeError::SurfaceCapabilitiesFailed { result: error })?;
- let surface_formats = live_surface_formats(
- surface,
- device.physical_device(),
- &device.report.device_name,
- )
- .map_err(VulkanSwapchainProbeError::Runtime)?;
- let present_modes = live_present_modes(
- surface,
- device.physical_device(),
- &device.report.device_name,
- )
- .map_err(VulkanSwapchainProbeError::Runtime)?;
- let capabilities = live_surface_capabilities(
- surface,
- device.physical_device(),
- &device.report.device_name,
- )
- .map_err(VulkanSwapchainProbeError::Runtime)?;
- let plan = plan_vulkan_swapchain(&VulkanSwapchainRequest {
- drawable_extent,
- formats: surface_formats,
- present_modes,
- capabilities,
- preferred_present_mode: vk::PresentModeKHR::MAILBOX.as_raw(),
- })
- .map_err(VulkanSwapchainProbeError::Plan)?;
- let queue_family_indices = unique_queue_families(
- device.runtime.capability.graphics_queue_family,
- device.runtime.capability.present_queue_family,
- );
- let sharing_mode = if queue_family_indices.len() > 1 {
- vk::SharingMode::CONCURRENT
- } else {
- vk::SharingMode::EXCLUSIVE
- };
- let create_info = vk::SwapchainCreateInfoKHR::default()
- .surface(surface.surface)
- .min_image_count(plan.image_count)
- .image_format(vk::Format::from_raw(plan.format.format))
- .image_color_space(vk::ColorSpaceKHR::from_raw(plan.format.color_space))
- .image_extent(vk::Extent2D {
- width: plan.extent.0,
- height: plan.extent.1,
- })
- .image_array_layers(1)
- .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
- .image_sharing_mode(sharing_mode)
- .queue_family_indices(&queue_family_indices)
- .pre_transform(raw_capabilities.current_transform)
- .composite_alpha(select_composite_alpha(
- raw_capabilities.supported_composite_alpha,
- ))
- .present_mode(vk::PresentModeKHR::from_raw(plan.present_mode))
- .old_swapchain(old_swapchain)
- .clipped(true);
- let loader = swapchain::Device::new(&instance.instance, device.device());
- // SAFETY: The create info references live instance/device/surface handles for this call.
- let swapchain = unsafe { loader.create_swapchain(&create_info, None) }
- .map_err(|error| VulkanSwapchainProbeError::CreateFailed { result: error })?;
- // SAFETY: The swapchain was created above and the returned image handles are owned by it.
- let images = match unsafe { loader.get_swapchain_images(swapchain) } {
- Ok(images) => images,
- Err(error) => {
- // SAFETY: The swapchain was created above on this loader/device pair and is destroyed on setup failure.
- unsafe { loader.destroy_swapchain(swapchain, None) };
- return Err(VulkanSwapchainProbeError::ImagesFailed { result: error });
- }
- };
- Ok(VulkanSwapchainProbe {
- loader,
- swapchain,
- report: VulkanSwapchainReport {
- schema: 1,
- plan,
- image_count: images.len().try_into().unwrap_or(u32::MAX),
- },
- })
-}
-
struct SelectedLiveDevice {
physical_device: vk::PhysicalDevice,
runtime: VulkanRuntimeCapabilityProbe,
@@ -636,7 +431,7 @@ fn live_device_candidate(
})
}
-fn unique_queue_families(graphics: u32, present: u32) -> Vec<u32> {
+pub(super) fn unique_queue_families(graphics: u32, present: u32) -> Vec<u32> {
if graphics == present {
vec![graphics]
} else {
@@ -697,7 +492,7 @@ fn live_device_extensions(
Ok(extensions)
}
-fn live_surface_formats(
+pub(super) fn live_surface_formats(
surface: &VulkanSurfaceProbe,
device: vk::PhysicalDevice,
name: &str,
@@ -723,7 +518,7 @@ fn live_surface_formats(
.collect())
}
-fn live_present_modes(
+pub(super) fn live_present_modes(
surface: &VulkanSurfaceProbe,
device: vk::PhysicalDevice,
name: &str,
@@ -743,7 +538,7 @@ fn live_present_modes(
Ok(modes.into_iter().map(vk::PresentModeKHR::as_raw).collect())
}
-fn live_surface_capabilities(
+pub(super) fn live_surface_capabilities(
surface: &VulkanSurfaceProbe,
device: vk::PhysicalDevice,
name: &str,
diff --git a/adapters/fparkan-render-vulkan/src/ffi/swapchain.rs b/adapters/fparkan-render-vulkan/src/ffi/swapchain.rs
new file mode 100644
index 0000000..adfca60
--- /dev/null
+++ b/adapters/fparkan-render-vulkan/src/ffi/swapchain.rs
@@ -0,0 +1,220 @@
+#![allow(unsafe_code)]
+
+use ash::{khr::swapchain, vk};
+
+use super::{
+ runtime::{
+ live_present_modes, live_surface_capabilities, live_surface_formats, unique_queue_families,
+ },
+ VulkanInstanceProbe, VulkanLogicalDeviceProbe, VulkanRuntimeCapabilityError,
+ VulkanSurfaceProbe,
+};
+use crate::policy::{
+ plan_vulkan_swapchain, select_composite_alpha, VulkanSwapchainError, VulkanSwapchainPlan,
+ VulkanSwapchainRequest,
+};
+
+/// Created Vulkan swapchain probe.
+pub struct VulkanSwapchainProbe {
+ loader: swapchain::Device,
+ swapchain: vk::SwapchainKHR,
+ /// Deterministic swapchain creation report.
+ pub report: VulkanSwapchainReport,
+}
+
+impl Drop for VulkanSwapchainProbe {
+ fn drop(&mut self) {
+ // SAFETY: The swapchain was created by this probe and is destroyed once during drop.
+ unsafe { self.loader.destroy_swapchain(self.swapchain, None) };
+ }
+}
+
+impl VulkanSwapchainProbe {
+ /// Returns the live swapchain handle.
+ #[must_use]
+ pub fn swapchain(&self) -> vk::SwapchainKHR {
+ self.swapchain
+ }
+
+ /// Returns the swapchain extension loader for this live swapchain.
+ #[must_use]
+ pub fn loader(&self) -> &swapchain::Device {
+ &self.loader
+ }
+}
+
+/// Runtime swapchain creation report.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VulkanSwapchainReport {
+ /// Report schema version.
+ pub schema: u32,
+ /// Deterministic swapchain policy used for creation.
+ pub plan: VulkanSwapchainPlan,
+ /// Number of images returned by `vkGetSwapchainImagesKHR`.
+ pub image_count: u32,
+}
+
+/// Vulkan swapchain creation error.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum VulkanSwapchainProbeError {
+ /// Live runtime capability probing failed before swapchain creation.
+ Runtime(VulkanRuntimeCapabilityError),
+ /// Deterministic swapchain planning failed before create.
+ Plan(VulkanSwapchainError),
+ /// Surface capability query failed.
+ SurfaceCapabilitiesFailed {
+ /// Vulkan result.
+ result: vk::Result,
+ },
+ /// Swapchain creation failed.
+ CreateFailed {
+ /// Vulkan result.
+ result: vk::Result,
+ },
+ /// Swapchain image query failed.
+ ImagesFailed {
+ /// Vulkan result.
+ result: vk::Result,
+ },
+}
+
+impl std::fmt::Display for VulkanSwapchainProbeError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::Runtime(error) => write!(f, "{error}"),
+ Self::Plan(error) => write!(f, "{error}"),
+ Self::SurfaceCapabilitiesFailed { result } => {
+ write!(f, "Vulkan surface capabilities query failed: {result:?}")
+ }
+ Self::CreateFailed { result } => {
+ write!(f, "Vulkan swapchain creation failed: {result:?}")
+ }
+ Self::ImagesFailed { result } => {
+ write!(f, "Vulkan swapchain image query failed: {result:?}")
+ }
+ }
+ }
+}
+
+impl std::error::Error for VulkanSwapchainProbeError {}
+
+/// Creates a Vulkan swapchain for the live logical device and surface.
+///
+/// # Errors
+///
+/// Returns [`VulkanSwapchainProbeError`] when live surface capability queries,
+/// swapchain creation, or swapchain image enumeration fails.
+pub fn create_vulkan_swapchain_probe(
+ instance: &VulkanInstanceProbe,
+ surface: &VulkanSurfaceProbe,
+ device: &VulkanLogicalDeviceProbe,
+) -> Result<VulkanSwapchainProbe, VulkanSwapchainProbeError> {
+ create_vulkan_swapchain_probe_for_extent(
+ instance,
+ surface,
+ device,
+ device.runtime.swapchain.extent,
+ vk::SwapchainKHR::null(),
+ )
+}
+
+/// Creates a Vulkan swapchain for the live logical device and surface at a specific extent.
+///
+/// # Errors
+///
+/// Returns [`VulkanSwapchainProbeError`] when live surface capability queries,
+/// swapchain creation, or swapchain image enumeration fails.
+pub fn create_vulkan_swapchain_probe_for_extent(
+ instance: &VulkanInstanceProbe,
+ surface: &VulkanSurfaceProbe,
+ device: &VulkanLogicalDeviceProbe,
+ drawable_extent: (u32, u32),
+ old_swapchain: vk::SwapchainKHR,
+) -> Result<VulkanSwapchainProbe, VulkanSwapchainProbeError> {
+ let raw_capabilities = {
+ // SAFETY: The physical device and surface are live query inputs and no handles are retained.
+ unsafe {
+ surface
+ .loader
+ .get_physical_device_surface_capabilities(device.physical_device(), surface.surface)
+ }
+ }
+ .map_err(|error| VulkanSwapchainProbeError::SurfaceCapabilitiesFailed { result: error })?;
+ let surface_formats = live_surface_formats(
+ surface,
+ device.physical_device(),
+ &device.report.device_name,
+ )
+ .map_err(VulkanSwapchainProbeError::Runtime)?;
+ let present_modes = live_present_modes(
+ surface,
+ device.physical_device(),
+ &device.report.device_name,
+ )
+ .map_err(VulkanSwapchainProbeError::Runtime)?;
+ let capabilities = live_surface_capabilities(
+ surface,
+ device.physical_device(),
+ &device.report.device_name,
+ )
+ .map_err(VulkanSwapchainProbeError::Runtime)?;
+ let plan = plan_vulkan_swapchain(&VulkanSwapchainRequest {
+ drawable_extent,
+ formats: surface_formats,
+ present_modes,
+ capabilities,
+ preferred_present_mode: vk::PresentModeKHR::MAILBOX.as_raw(),
+ })
+ .map_err(VulkanSwapchainProbeError::Plan)?;
+ let queue_family_indices = unique_queue_families(
+ device.runtime.capability.graphics_queue_family,
+ device.runtime.capability.present_queue_family,
+ );
+ let sharing_mode = if queue_family_indices.len() > 1 {
+ vk::SharingMode::CONCURRENT
+ } else {
+ vk::SharingMode::EXCLUSIVE
+ };
+ let create_info = vk::SwapchainCreateInfoKHR::default()
+ .surface(surface.surface)
+ .min_image_count(plan.image_count)
+ .image_format(vk::Format::from_raw(plan.format.format))
+ .image_color_space(vk::ColorSpaceKHR::from_raw(plan.format.color_space))
+ .image_extent(vk::Extent2D {
+ width: plan.extent.0,
+ height: plan.extent.1,
+ })
+ .image_array_layers(1)
+ .image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
+ .image_sharing_mode(sharing_mode)
+ .queue_family_indices(&queue_family_indices)
+ .pre_transform(raw_capabilities.current_transform)
+ .composite_alpha(select_composite_alpha(
+ raw_capabilities.supported_composite_alpha,
+ ))
+ .present_mode(vk::PresentModeKHR::from_raw(plan.present_mode))
+ .old_swapchain(old_swapchain)
+ .clipped(true);
+ let loader = swapchain::Device::new(&instance.instance, device.device());
+ // SAFETY: The create info references live instance/device/surface handles for this call.
+ let swapchain = unsafe { loader.create_swapchain(&create_info, None) }
+ .map_err(|error| VulkanSwapchainProbeError::CreateFailed { result: error })?;
+ // SAFETY: The swapchain was created above and the returned image handles are owned by it.
+ let images = match unsafe { loader.get_swapchain_images(swapchain) } {
+ Ok(images) => images,
+ Err(error) => {
+ // SAFETY: The swapchain was created above on this loader/device pair and is destroyed on setup failure.
+ unsafe { loader.destroy_swapchain(swapchain, None) };
+ return Err(VulkanSwapchainProbeError::ImagesFailed { result: error });
+ }
+ };
+ Ok(VulkanSwapchainProbe {
+ loader,
+ swapchain,
+ report: VulkanSwapchainReport {
+ schema: 1,
+ plan,
+ image_count: images.len().try_into().unwrap_or(u32::MAX),
+ },
+ })
+}
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 412934e..484e9c5 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -1245,6 +1245,7 @@ const AUDITED_UNSAFE_SOURCE_FILES: &[&str] = &[
"adapters/fparkan-render-vulkan/src/ffi/resources.rs",
"adapters/fparkan-render-vulkan/src/ffi/runtime.rs",
"adapters/fparkan-render-vulkan/src/ffi/smoke.rs",
+ "adapters/fparkan-render-vulkan/src/ffi/swapchain.rs",
"adapters/fparkan-render-vulkan/src/ffi/swapchain_resources.rs",
"adapters/fparkan-render-vulkan/src/ffi/surface.rs",
"adapters/fparkan-render-vulkan/src/ffi/validation.rs",