aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src/ffi.rs
diff options
context:
space:
mode:
Diffstat (limited to 'adapters/fparkan-render-vulkan/src/ffi.rs')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi.rs163
1 files changed, 8 insertions, 155 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi.rs b/adapters/fparkan-render-vulkan/src/ffi.rs
index 070c2ad..9be61eb 100644
--- a/adapters/fparkan-render-vulkan/src/ffi.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi.rs
@@ -28,6 +28,7 @@
//! This crate is the declared low-level Vulkan boundary.
mod instance;
+mod surface;
pub use self::instance::{
create_vulkan_instance_probe, plan_vulkan_instance, probe_vulkan_loader,
@@ -37,19 +38,20 @@ pub use self::instance::{
};
#[cfg(test)]
use self::instance::{cstring_vec, ensure_instance_extensions_available};
+#[cfg(test)]
+use self::surface::extension_name;
+pub use self::surface::{
+ create_vulkan_surface_probe, plan_vulkan_surface, render_surface_plan_json, VulkanSurfaceError,
+ VulkanSurfacePlan, VulkanSurfaceProbe,
+};
use crate::policy::*;
use crate::shader_manifest::{
triangle_shader_manifest, validate_shader_manifest, VulkanShaderManifestError,
};
-use ash::{
- khr::{surface, swapchain},
- vk,
-};
+use ash::{khr::swapchain, vk};
use fparkan_platform::NativeWindowHandles;
-use serde::Serialize;
use std::collections::BTreeSet;
use std::ffi::{CStr, CString};
-use std::os::raw::c_char;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Mutex;
/// Minimum Vulkan API version accepted by the Stage 0 backend.
@@ -442,74 +444,6 @@ pub(crate) const TRIANGLE_FRAGMENT_SHADER_WORDS: &[u32] = &[
0x0001_0038,
];
-/// Deterministic Vulkan surface creation plan.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct VulkanSurfacePlan {
- /// Report schema version.
- pub schema: u32,
- /// Instance extensions required by the native display backend.
- pub required_instance_extensions: Vec<String>,
-}
-
-/// Vulkan surface bootstrap error.
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum VulkanSurfaceError {
- /// No native raw window/display handles were available.
- MissingNativeHandles,
- /// Required platform surface extensions could not be enumerated.
- RequiredExtensionsFailed {
- /// Vulkan result.
- result: vk::Result,
- },
- /// A required extension pointer was not valid UTF-8.
- InvalidExtensionName,
- /// Surface creation failed.
- CreateFailed {
- /// Vulkan result.
- result: vk::Result,
- },
-}
-
-impl std::fmt::Display for VulkanSurfaceError {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Self::MissingNativeHandles => {
- write!(
- f,
- "native window/display handles are required for Vulkan surface creation"
- )
- }
- Self::RequiredExtensionsFailed { result } => write!(
- f,
- "failed to enumerate required Vulkan surface extensions: {result:?}"
- ),
- Self::InvalidExtensionName => {
- write!(f, "Vulkan surface extension name is not valid UTF-8")
- }
- Self::CreateFailed { result } => {
- write!(f, "Vulkan surface creation failed: {result:?}")
- }
- }
- }
-}
-
-impl std::error::Error for VulkanSurfaceError {}
-
-/// Created Vulkan surface probe.
-pub struct VulkanSurfaceProbe {
- loader: surface::Instance,
- surface: vk::SurfaceKHR,
- /// Deterministic surface creation report.
- pub report: VulkanSurfacePlan,
-}
-
-impl Drop for VulkanSurfaceProbe {
- fn drop(&mut self) {
- // SAFETY: The `SurfaceKHR` was created by this probe and is destroyed once during drop.
- unsafe { self.loader.destroy_surface(self.surface, None) };
- }
-}
-
/// Live Vulkan device/surface capability probe.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VulkanRuntimeCapabilityProbe {
@@ -2308,61 +2242,6 @@ impl std::fmt::Display for VulkanSwapchainProbeError {
impl std::error::Error for VulkanSwapchainProbeError {}
-/// Builds a deterministic Vulkan surface plan from native window handles.
-///
-/// # Errors
-///
-/// Returns [`VulkanSurfaceError`] when no native handles exist or the platform
-/// display backend has no Vulkan surface extension mapping.
-pub fn plan_vulkan_surface(
- handles: Option<NativeWindowHandles>,
-) -> Result<VulkanSurfacePlan, VulkanSurfaceError> {
- let handles = handles.ok_or(VulkanSurfaceError::MissingNativeHandles)?;
- let required = ash_window::enumerate_required_extensions(handles.display)
- .map_err(|error| VulkanSurfaceError::RequiredExtensionsFailed { result: error })?;
- let mut required_instance_extensions = Vec::with_capacity(required.len());
- for extension in required {
- let name = extension_name(*extension)?;
- required_instance_extensions.push(name);
- }
- required_instance_extensions.sort();
- required_instance_extensions.dedup();
- Ok(VulkanSurfacePlan {
- schema: 1,
- required_instance_extensions,
- })
-}
-
-/// Creates a Vulkan surface probe from native window handles.
-///
-/// # Errors
-///
-/// Returns [`VulkanSurfaceError`] when handles are missing, required extensions
-/// cannot be planned, or `vkCreate*SurfaceKHR` fails.
-pub fn create_vulkan_surface_probe(
- instance: &VulkanInstanceProbe,
- handles: Option<NativeWindowHandles>,
-) -> Result<VulkanSurfaceProbe, VulkanSurfaceError> {
- let handles = handles.ok_or(VulkanSurfaceError::MissingNativeHandles)?;
- let report = plan_vulkan_surface(Some(handles))?;
- // SAFETY: The platform handles are only used to create a child surface owned by this probe.
- let surface = unsafe {
- ash_window::create_surface(
- &instance.entry,
- &instance.instance,
- handles.display,
- handles.window,
- None,
- )
- }
- .map_err(|error| VulkanSurfaceError::CreateFailed { result: error })?;
- Ok(VulkanSurfaceProbe {
- loader: surface::Instance::new(&instance.entry, &instance.instance),
- surface,
- report,
- })
-}
-
/// Probes live Vulkan device, queue, surface and swapchain capabilities.
///
/// # Errors
@@ -2841,32 +2720,6 @@ fn live_surface_capabilities(
})
}
-/// Renders a deterministic JSON Vulkan surface plan.
-#[must_use]
-pub fn render_surface_plan_json(plan: &VulkanSurfacePlan) -> String {
- #[derive(Serialize)]
- struct SurfacePlanJson<'a> {
- schema: u32,
- required_instance_extensions: &'a [String],
- }
-
- serialize_json_or_fallback(
- &SurfacePlanJson {
- schema: plan.schema,
- required_instance_extensions: &plan.required_instance_extensions,
- },
- "{\"schema\":0,\"required_instance_extensions\":[]}",
- )
-}
-
-fn extension_name(extension: *const c_char) -> Result<String, VulkanSurfaceError> {
- // SAFETY: `ash-window` returns extension pointers to static NUL-terminated Vulkan names.
- let name = unsafe { CStr::from_ptr(extension) };
- name.to_str()
- .map(str::to_string)
- .map_err(|_| VulkanSurfaceError::InvalidExtensionName)
-}
-
#[cfg(test)]
mod tests {
use super::*;