refactor(vulkan-ffi): extract swapchain probe module
This commit is contained in:
@@ -33,6 +33,7 @@ mod runtime;
|
|||||||
mod smoke;
|
mod smoke;
|
||||||
mod smoke_types;
|
mod smoke_types;
|
||||||
mod surface;
|
mod surface;
|
||||||
|
mod swapchain;
|
||||||
mod swapchain_resources;
|
mod swapchain_resources;
|
||||||
mod validation;
|
mod validation;
|
||||||
|
|
||||||
@@ -50,11 +51,9 @@ use self::resources::{
|
|||||||
VulkanFrameSync,
|
VulkanFrameSync,
|
||||||
};
|
};
|
||||||
pub use self::runtime::{
|
pub use self::runtime::{
|
||||||
create_vulkan_logical_device_probe, create_vulkan_swapchain_probe,
|
create_vulkan_logical_device_probe, probe_vulkan_runtime_capabilities,
|
||||||
create_vulkan_swapchain_probe_for_extent, probe_vulkan_runtime_capabilities,
|
|
||||||
VulkanLogicalDeviceError, VulkanLogicalDeviceProbe, VulkanLogicalDeviceReport,
|
VulkanLogicalDeviceError, VulkanLogicalDeviceProbe, VulkanLogicalDeviceReport,
|
||||||
VulkanRuntimeCapabilityError, VulkanRuntimeCapabilityProbe, VulkanSwapchainProbe,
|
VulkanRuntimeCapabilityError, VulkanRuntimeCapabilityProbe,
|
||||||
VulkanSwapchainProbeError, VulkanSwapchainReport,
|
|
||||||
};
|
};
|
||||||
pub use self::smoke_types::{
|
pub use self::smoke_types::{
|
||||||
VulkanSmokeFrameOutcome, VulkanSmokeRenderer, VulkanSmokeRendererCreateInfo,
|
VulkanSmokeFrameOutcome, VulkanSmokeRenderer, VulkanSmokeRendererCreateInfo,
|
||||||
@@ -66,6 +65,10 @@ pub use self::surface::{
|
|||||||
create_vulkan_surface_probe, plan_vulkan_surface, render_surface_plan_json, VulkanSurfaceError,
|
create_vulkan_surface_probe, plan_vulkan_surface, render_surface_plan_json, VulkanSurfaceError,
|
||||||
VulkanSurfacePlan, VulkanSurfaceProbe,
|
VulkanSurfacePlan, VulkanSurfaceProbe,
|
||||||
};
|
};
|
||||||
|
pub use self::swapchain::{
|
||||||
|
create_vulkan_swapchain_probe, create_vulkan_swapchain_probe_for_extent, VulkanSwapchainProbe,
|
||||||
|
VulkanSwapchainProbeError, VulkanSwapchainReport,
|
||||||
|
};
|
||||||
use self::swapchain_resources::{
|
use self::swapchain_resources::{
|
||||||
create_swapchain_resources, destroy_swapchain_resources, VulkanSwapchainResources,
|
create_swapchain_resources, destroy_swapchain_resources, VulkanSwapchainResources,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use ash::{khr::swapchain, vk};
|
use ash::vk;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
|
|
||||||
use super::{VulkanInstanceProbe, VulkanSurfaceProbe};
|
use super::{VulkanInstanceProbe, VulkanSurfaceProbe};
|
||||||
use crate::policy::{
|
use crate::policy::{
|
||||||
compare_reports, plan_vulkan_swapchain, select_composite_alpha, validate_device,
|
compare_reports, plan_vulkan_swapchain, validate_device, VulkanCapabilityError,
|
||||||
VulkanCapabilityError, VulkanCapabilityReport, VulkanDeviceType, VulkanPhysicalDeviceRecord,
|
VulkanCapabilityReport, VulkanDeviceType, VulkanPhysicalDeviceRecord, VulkanQueueFamily,
|
||||||
VulkanQueueFamily, VulkanSurfaceFormat, VulkanSwapchainError, VulkanSwapchainPlan,
|
VulkanSurfaceFormat, VulkanSwapchainError, VulkanSwapchainPlan, VulkanSwapchainRequest,
|
||||||
VulkanSwapchainRequest, VulkanSwapchainSurfaceCapabilities,
|
VulkanSwapchainSurfaceCapabilities,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Live Vulkan device/surface capability probe.
|
/// Live Vulkan device/surface capability probe.
|
||||||
@@ -86,46 +86,6 @@ pub struct VulkanLogicalDeviceReport {
|
|||||||
pub enabled_extensions: Vec<String>,
|
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.
|
/// Live Vulkan device/surface capability probe error.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum VulkanRuntimeCapabilityError {
|
pub enum VulkanRuntimeCapabilityError {
|
||||||
@@ -254,50 +214,6 @@ impl std::fmt::Display for VulkanLogicalDeviceError {
|
|||||||
|
|
||||||
impl std::error::Error 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.
|
/// Probes live Vulkan device, queue, surface and swapchain capabilities.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # 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 {
|
struct SelectedLiveDevice {
|
||||||
physical_device: vk::PhysicalDevice,
|
physical_device: vk::PhysicalDevice,
|
||||||
runtime: VulkanRuntimeCapabilityProbe,
|
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 {
|
if graphics == present {
|
||||||
vec![graphics]
|
vec![graphics]
|
||||||
} else {
|
} else {
|
||||||
@@ -697,7 +492,7 @@ fn live_device_extensions(
|
|||||||
Ok(extensions)
|
Ok(extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn live_surface_formats(
|
pub(super) fn live_surface_formats(
|
||||||
surface: &VulkanSurfaceProbe,
|
surface: &VulkanSurfaceProbe,
|
||||||
device: vk::PhysicalDevice,
|
device: vk::PhysicalDevice,
|
||||||
name: &str,
|
name: &str,
|
||||||
@@ -723,7 +518,7 @@ fn live_surface_formats(
|
|||||||
.collect())
|
.collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn live_present_modes(
|
pub(super) fn live_present_modes(
|
||||||
surface: &VulkanSurfaceProbe,
|
surface: &VulkanSurfaceProbe,
|
||||||
device: vk::PhysicalDevice,
|
device: vk::PhysicalDevice,
|
||||||
name: &str,
|
name: &str,
|
||||||
@@ -743,7 +538,7 @@ fn live_present_modes(
|
|||||||
Ok(modes.into_iter().map(vk::PresentModeKHR::as_raw).collect())
|
Ok(modes.into_iter().map(vk::PresentModeKHR::as_raw).collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn live_surface_capabilities(
|
pub(super) fn live_surface_capabilities(
|
||||||
surface: &VulkanSurfaceProbe,
|
surface: &VulkanSurfaceProbe,
|
||||||
device: vk::PhysicalDevice,
|
device: vk::PhysicalDevice,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
|||||||
@@ -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),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1245,6 +1245,7 @@ const AUDITED_UNSAFE_SOURCE_FILES: &[&str] = &[
|
|||||||
"adapters/fparkan-render-vulkan/src/ffi/resources.rs",
|
"adapters/fparkan-render-vulkan/src/ffi/resources.rs",
|
||||||
"adapters/fparkan-render-vulkan/src/ffi/runtime.rs",
|
"adapters/fparkan-render-vulkan/src/ffi/runtime.rs",
|
||||||
"adapters/fparkan-render-vulkan/src/ffi/smoke.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/swapchain_resources.rs",
|
||||||
"adapters/fparkan-render-vulkan/src/ffi/surface.rs",
|
"adapters/fparkan-render-vulkan/src/ffi/surface.rs",
|
||||||
"adapters/fparkan-render-vulkan/src/ffi/validation.rs",
|
"adapters/fparkan-render-vulkan/src/ffi/validation.rs",
|
||||||
|
|||||||
Reference in New Issue
Block a user