aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/ffi/runtime.rs')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/runtime.rs405
1 files changed, 5 insertions, 400 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi/runtime.rs b/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
index b1c98df..134bf3e 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/runtime.rs
@@ -1,24 +1,13 @@
#![allow(unsafe_code)]
use ash::vk;
-use std::ffi::{CStr, CString};
+use std::ffi::CString;
-use super::{VulkanInstanceProbe, VulkanSurfaceProbe};
-use crate::policy::{
- compare_reports, plan_vulkan_swapchain, validate_device, VulkanCapabilityError,
- VulkanCapabilityReport, VulkanDeviceType, VulkanPhysicalDeviceRecord, VulkanQueueFamily,
- VulkanSurfaceFormat, VulkanSwapchainError, VulkanSwapchainPlan, VulkanSwapchainRequest,
- VulkanSwapchainSurfaceCapabilities,
+use super::capabilities::{
+ select_live_device_candidate, unique_queue_families, VulkanRuntimeCapabilityError,
+ VulkanRuntimeCapabilityProbe,
};
-
-/// Live Vulkan device/surface capability probe.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct VulkanRuntimeCapabilityProbe {
- /// Selected device/queue capability report.
- pub capability: VulkanCapabilityReport,
- /// Swapchain plan built from the selected device and live surface capabilities.
- pub swapchain: VulkanSwapchainPlan,
-}
+use super::{VulkanInstanceProbe, VulkanSurfaceProbe};
/// Created Vulkan logical device probe.
pub struct VulkanLogicalDeviceProbe {
@@ -86,95 +75,6 @@ pub struct VulkanLogicalDeviceReport {
pub enabled_extensions: Vec<String>,
}
-/// Live Vulkan device/surface capability probe error.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum VulkanRuntimeCapabilityError {
- /// Physical device enumeration failed.
- EnumerateDevicesFailed {
- /// Vulkan result.
- result: vk::Result,
- },
- /// Device extension enumeration failed.
- EnumerateDeviceExtensionsFailed {
- /// Device name or index context.
- device: String,
- /// Vulkan result.
- result: vk::Result,
- },
- /// Queue-family present support query failed.
- PresentSupportFailed {
- /// Device name.
- device: String,
- /// Queue-family index.
- queue_family: u32,
- /// Vulkan result.
- result: vk::Result,
- },
- /// Surface format query failed.
- SurfaceFormatsFailed {
- /// Device name.
- device: String,
- /// Vulkan result.
- result: vk::Result,
- },
- /// Surface capability query failed.
- SurfaceCapabilitiesFailed {
- /// Device name.
- device: String,
- /// Vulkan result.
- result: vk::Result,
- },
- /// Present mode query failed.
- PresentModesFailed {
- /// Device name.
- device: String,
- /// Vulkan result.
- result: vk::Result,
- },
- /// No device satisfied Stage 0 capability policy.
- Capability(VulkanCapabilityError),
- /// Live surface capabilities could not produce a swapchain plan.
- Swapchain(VulkanSwapchainError),
-}
-
-impl std::fmt::Display for VulkanRuntimeCapabilityError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::EnumerateDevicesFailed { result } => {
- write!(f, "Vulkan physical device enumeration failed: {result:?}")
- }
- Self::EnumerateDeviceExtensionsFailed { device, result } => write!(
- f,
- "Vulkan device {device} extension enumeration failed: {result:?}"
- ),
- Self::PresentSupportFailed {
- device,
- queue_family,
- result,
- } => write!(
- f,
- "Vulkan device {device} queue family {queue_family} present support query failed: {result:?}"
- ),
- Self::SurfaceFormatsFailed { device, result } => write!(
- f,
- "Vulkan device {device} surface format query failed: {result:?}"
- ),
- Self::SurfaceCapabilitiesFailed { device, result } => write!(
- f,
- "Vulkan device {device} surface capabilities query failed: {result:?}"
- ),
- Self::PresentModesFailed { device, result } => write!(
- f,
- "Vulkan device {device} present mode query failed: {result:?}"
- ),
- Self::Capability(error) => write!(f, "{error}"),
- Self::Swapchain(error) => write!(f, "{error}"),
- }
- }
-}
-
-impl std::error::Error for VulkanRuntimeCapabilityError {}
-
/// Vulkan logical device creation error.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum VulkanLogicalDeviceError {
@@ -214,21 +114,6 @@ impl std::fmt::Display for VulkanLogicalDeviceError {
impl std::error::Error for VulkanLogicalDeviceError {}
-/// Probes live Vulkan device, queue, surface and swapchain capabilities.
-///
-/// # Errors
-///
-/// Returns [`VulkanRuntimeCapabilityError`] when device enumeration, surface
-/// capability queries, Stage 0 device selection, or swapchain planning fails.
-pub fn probe_vulkan_runtime_capabilities(
- instance: &VulkanInstanceProbe,
- surface: &VulkanSurfaceProbe,
- drawable_extent: (u32, u32),
-) -> Result<VulkanRuntimeCapabilityProbe, VulkanRuntimeCapabilityError> {
- let selected = select_live_device_candidate(instance, surface, drawable_extent)?;
- Ok(selected.runtime)
-}
-
/// Creates a Vulkan logical device for the selected live surface-capable device.
///
/// # Errors
@@ -293,289 +178,9 @@ pub fn create_vulkan_logical_device_probe(
})
}
-struct SelectedLiveDevice {
- physical_device: vk::PhysicalDevice,
- runtime: VulkanRuntimeCapabilityProbe,
-}
-
-struct LiveDeviceCandidate {
- physical_device: vk::PhysicalDevice,
- capability: VulkanCapabilityReport,
- surface_formats: Vec<VulkanSurfaceFormat>,
- present_modes: Vec<i32>,
- surface_capabilities: VulkanSwapchainSurfaceCapabilities,
-}
-
-fn select_live_device_candidate(
- instance: &VulkanInstanceProbe,
- surface: &VulkanSurfaceProbe,
- drawable_extent: (u32, u32),
-) -> Result<SelectedLiveDevice, VulkanRuntimeCapabilityError> {
- let devices = {
- // SAFETY: The Vulkan instance is live for this query and no handles are retained.
- unsafe { instance.instance.enumerate_physical_devices() }.map_err(|error| {
- VulkanRuntimeCapabilityError::EnumerateDevicesFailed { result: error }
- })?
- };
- let mut best: Option<LiveDeviceCandidate> = None;
- let mut last_error = None;
- for (index, device) in devices.iter().copied().enumerate() {
- let candidate = match live_device_candidate(instance, surface, device, index) {
- Ok(candidate) => candidate,
- Err(err) => {
- last_error = Some(err);
- continue;
- }
- };
- match &best {
- Some(existing)
- if compare_reports(&candidate.capability, &existing.capability)
- != std::cmp::Ordering::Greater => {}
- _ => best = Some(candidate),
- }
- }
- let best = best.ok_or_else(|| {
- last_error.unwrap_or(VulkanRuntimeCapabilityError::Capability(
- VulkanCapabilityError::NoPhysicalDevice,
- ))
- })?;
- let swapchain = plan_vulkan_swapchain(&VulkanSwapchainRequest {
- drawable_extent,
- formats: best.surface_formats,
- present_modes: best.present_modes,
- capabilities: best.surface_capabilities,
- preferred_present_mode: vk::PresentModeKHR::MAILBOX.as_raw(),
- })
- .map_err(VulkanRuntimeCapabilityError::Swapchain)?;
- Ok(SelectedLiveDevice {
- physical_device: best.physical_device,
- runtime: VulkanRuntimeCapabilityProbe {
- capability: best.capability,
- swapchain,
- },
- })
-}
-
-fn live_device_candidate(
- instance: &VulkanInstanceProbe,
- surface: &VulkanSurfaceProbe,
- device: vk::PhysicalDevice,
- index: usize,
-) -> Result<LiveDeviceCandidate, VulkanRuntimeCapabilityError> {
- let properties = {
- // SAFETY: `device` was returned by this live instance and the result is copied by value.
- unsafe { instance.instance.get_physical_device_properties(device) }
- };
- let name = physical_device_name(&properties, index);
- let queue_properties = {
- // SAFETY: `device` was returned by this live instance and the result is owned by Rust.
- unsafe {
- instance
- .instance
- .get_physical_device_queue_family_properties(device)
- }
- };
- let extensions = live_device_extensions(instance, device, &name)?;
- let surface_formats = live_surface_formats(surface, device, &name)?;
- let present_modes = live_present_modes(surface, device, &name)?;
- let surface_capabilities = live_surface_capabilities(surface, device, &name)?;
- let queue_families = queue_properties
- .iter()
- .enumerate()
- .map(|(queue_index, properties)| {
- let index = u32::try_from(queue_index).unwrap_or(u32::MAX);
- let present = {
- // SAFETY: The physical device, surface and queue-family index are live query inputs.
- unsafe {
- surface.loader.get_physical_device_surface_support(
- device,
- index,
- surface.surface,
- )
- }
- }
- .map_err(|error| VulkanRuntimeCapabilityError::PresentSupportFailed {
- device: name.clone(),
- queue_family: index,
- result: error,
- })?;
- Ok(VulkanQueueFamily {
- index,
- graphics: properties.queue_flags.contains(vk::QueueFlags::GRAPHICS),
- present,
- })
- })
- .collect::<Result<Vec<_>, VulkanRuntimeCapabilityError>>()?;
- let record = VulkanPhysicalDeviceRecord {
- name,
- api_version: properties.api_version,
- device_type: match properties.device_type {
- vk::PhysicalDeviceType::DISCRETE_GPU => VulkanDeviceType::DiscreteGpu,
- vk::PhysicalDeviceType::INTEGRATED_GPU => VulkanDeviceType::IntegratedGpu,
- vk::PhysicalDeviceType::CPU => VulkanDeviceType::Cpu,
- _ => VulkanDeviceType::Other,
- },
- extensions,
- queue_families,
- surface_formats: surface_formats.clone(),
- present_modes: present_modes.clone(),
- surface_capabilities,
- };
- let capability = validate_device(&record).map_err(VulkanRuntimeCapabilityError::Capability)?;
- Ok(LiveDeviceCandidate {
- physical_device: device,
- capability,
- surface_formats,
- present_modes,
- surface_capabilities,
- })
-}
-
-pub(super) fn unique_queue_families(graphics: u32, present: u32) -> Vec<u32> {
- if graphics == present {
- vec![graphics]
- } else {
- vec![graphics, present]
- }
-}
-
fn device_extension_cstrings(values: &[String]) -> Result<Vec<CString>, String> {
values
.iter()
.map(|extension| CString::new(extension.as_str()).map_err(|_| extension.clone()))
.collect()
}
-
-fn physical_device_name(properties: &vk::PhysicalDeviceProperties, index: usize) -> String {
- // SAFETY: Vulkan device names are fixed-size NUL-terminated C strings per the spec.
- let name = unsafe { CStr::from_ptr(properties.device_name.as_ptr()) }
- .to_string_lossy()
- .trim()
- .to_string();
- if name.is_empty() {
- format!("physical-device-{index}")
- } else {
- name
- }
-}
-
-fn live_device_extensions(
- instance: &VulkanInstanceProbe,
- device: vk::PhysicalDevice,
- name: &str,
-) -> Result<Vec<String>, VulkanRuntimeCapabilityError> {
- let properties = {
- // SAFETY: `device` was returned by this live instance and no borrowed data escapes.
- unsafe {
- instance
- .instance
- .enumerate_device_extension_properties(device)
- }
- }
- .map_err(
- |error| VulkanRuntimeCapabilityError::EnumerateDeviceExtensionsFailed {
- device: name.to_string(),
- result: error,
- },
- )?;
- let mut extensions = properties
- .iter()
- .map(|property| {
- // SAFETY: Vulkan extension names are fixed-size NUL-terminated C strings per the spec.
- unsafe { CStr::from_ptr(property.extension_name.as_ptr()) }
- .to_string_lossy()
- .into_owned()
- })
- .collect::<Vec<_>>();
- extensions.sort();
- extensions.dedup();
- Ok(extensions)
-}
-
-pub(super) fn live_surface_formats(
- surface: &VulkanSurfaceProbe,
- device: vk::PhysicalDevice,
- name: &str,
-) -> Result<Vec<VulkanSurfaceFormat>, VulkanRuntimeCapabilityError> {
- let formats = {
- // SAFETY: The physical device and surface are live query inputs and no handles are retained.
- unsafe {
- surface
- .loader
- .get_physical_device_surface_formats(device, surface.surface)
- }
- }
- .map_err(|error| VulkanRuntimeCapabilityError::SurfaceFormatsFailed {
- device: name.to_string(),
- result: error,
- })?;
- Ok(formats
- .into_iter()
- .map(|format| VulkanSurfaceFormat {
- format: format.format.as_raw(),
- color_space: format.color_space.as_raw(),
- })
- .collect())
-}
-
-pub(super) fn live_present_modes(
- surface: &VulkanSurfaceProbe,
- device: vk::PhysicalDevice,
- name: &str,
-) -> Result<Vec<i32>, VulkanRuntimeCapabilityError> {
- let modes = {
- // SAFETY: The physical device and surface are live query inputs and no handles are retained.
- unsafe {
- surface
- .loader
- .get_physical_device_surface_present_modes(device, surface.surface)
- }
- }
- .map_err(|error| VulkanRuntimeCapabilityError::PresentModesFailed {
- device: name.to_string(),
- result: error,
- })?;
- Ok(modes.into_iter().map(vk::PresentModeKHR::as_raw).collect())
-}
-
-pub(super) fn live_surface_capabilities(
- surface: &VulkanSurfaceProbe,
- device: vk::PhysicalDevice,
- name: &str,
-) -> Result<VulkanSwapchainSurfaceCapabilities, VulkanRuntimeCapabilityError> {
- let 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, surface.surface)
- }
- }
- .map_err(
- |error| VulkanRuntimeCapabilityError::SurfaceCapabilitiesFailed {
- device: name.to_string(),
- result: error,
- },
- )?;
- Ok(VulkanSwapchainSurfaceCapabilities {
- current_extent: if capabilities.current_extent.width == u32::MAX {
- None
- } else {
- Some((
- capabilities.current_extent.width,
- capabilities.current_extent.height,
- ))
- },
- min_extent: (
- capabilities.min_image_extent.width,
- capabilities.min_image_extent.height,
- ),
- max_extent: (
- capabilities.max_image_extent.width,
- capabilities.max_image_extent.height,
- ),
- min_image_count: capabilities.min_image_count,
- max_image_count: capabilities.max_image_count,
- supported_usage_flags: capabilities.supported_usage_flags.as_raw(),
- })
-}