aboutsummaryrefslogtreecommitdiff
path: root/adapters/fparkan-render-vulkan/src
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-06-25 07:10:31 +0300
committerValentin Popov <valentin@popov.link>2026-06-25 10:45:40 +0300
commitd146953bcc949ddf8b8326deab8d7aebeec5696d (patch)
tree7e7654cdeb7ed93e55ab296ddd820037e8f5681b /adapters/fparkan-render-vulkan/src
parentb617e2958d186cff5588335b9c736e33f05eb7ba (diff)
downloadfparkan-d146953bcc949ddf8b8326deab8d7aebeec5696d.tar.xz
fparkan-d146953bcc949ddf8b8326deab8d7aebeec5696d.zip
fix(vulkan-smoke): track bootstrap timeout evidence
Diffstat (limited to 'adapters/fparkan-render-vulkan/src')
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi.rs5
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke.rs15
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs80
3 files changed, 98 insertions, 2 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi.rs b/adapters/fparkan-render-vulkan/src/ffi.rs
index 5977f43..ece45e0 100644
--- a/adapters/fparkan-render-vulkan/src/ffi.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi.rs
@@ -58,8 +58,9 @@ pub use self::runtime::{
VulkanLogicalDeviceReport,
};
pub use self::smoke_types::{
- VulkanSmokeFrameOutcome, VulkanSmokeRenderer, VulkanSmokeRendererCreateInfo,
- VulkanSmokeRendererError, VulkanSmokeRendererReport, VulkanValidationReport,
+ VulkanSmokeBootstrapProgress, VulkanSmokeBootstrapSnapshot, VulkanSmokeFrameOutcome,
+ VulkanSmokeRenderer, VulkanSmokeRendererCreateInfo, VulkanSmokeRendererError,
+ VulkanSmokeRendererReport, VulkanValidationReport,
};
#[cfg(test)]
use self::surface::extension_name;
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
index e11706f..02ea0d6 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke.rs
@@ -76,9 +76,11 @@ impl VulkanSmokeRenderer {
///
/// Returns [`VulkanSmokeRendererError`] when Vulkan bootstrap, pipeline creation,
/// memory allocation, or synchronization resource creation fails.
+ #[allow(clippy::too_many_lines)]
pub fn new(
create_info: &VulkanSmokeRendererCreateInfo,
) -> Result<Self, VulkanSmokeRendererError> {
+ let bootstrap_progress = create_info.bootstrap_progress.as_ref();
let shader_manifest = validate_shader_manifest(&triangle_shader_manifest())
.map_err(VulkanSmokeRendererError::ShaderManifest)?;
let surface_plan = plan_vulkan_surface(Some(create_info.native_handles))
@@ -90,6 +92,10 @@ impl VulkanSmokeRenderer {
instance_config.enable_validation = create_info.enable_validation;
let instance = create_vulkan_instance_probe(&instance_config)
.map_err(VulkanSmokeRendererError::Instance)?;
+ if let Some(progress) = bootstrap_progress {
+ progress.mark_loader_available();
+ progress.mark_instance_created();
+ }
let validation = if create_info.enable_validation {
Some(create_validation_messenger(&instance)?)
} else {
@@ -97,9 +103,15 @@ impl VulkanSmokeRenderer {
};
let surface = create_vulkan_surface_probe(&instance, Some(create_info.native_handles))
.map_err(VulkanSmokeRendererError::Surface)?;
+ if let Some(progress) = bootstrap_progress {
+ progress.mark_surface_created();
+ }
let device =
create_vulkan_logical_device_probe(&instance, &surface, create_info.drawable_extent)
.map_err(VulkanSmokeRendererError::LogicalDevice)?;
+ if let Some(progress) = bootstrap_progress {
+ progress.mark_logical_device_created();
+ }
let swapchain = create_vulkan_swapchain_probe_for_extent(
&instance,
&surface,
@@ -108,6 +120,9 @@ impl VulkanSmokeRenderer {
vk::SwapchainKHR::null(),
)
.map_err(VulkanSmokeRendererError::Swapchain)?;
+ if let Some(progress) = bootstrap_progress {
+ progress.mark_swapchain_created();
+ }
let command_pool = create_command_pool(&device)?;
let vertex_buffer = match create_triangle_vertex_buffer(&instance, &device) {
Ok(buffer) => buffer,
diff --git a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
index 87d7992..836f82d 100644
--- a/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
+++ b/adapters/fparkan-render-vulkan/src/ffi/smoke_types.rs
@@ -1,5 +1,7 @@
use ash::vk;
use fparkan_platform::NativeWindowHandles;
+use std::sync::atomic::{AtomicU8, Ordering};
+use std::sync::Arc;
use super::{
VulkanAllocatedBuffer, VulkanFrameSync, VulkanInstanceError, VulkanInstanceProbe,
@@ -20,8 +22,86 @@ pub struct VulkanSmokeRendererCreateInfo {
pub drawable_extent: (u32, u32),
/// Whether validation layers must be enabled.
pub enable_validation: bool,
+ /// Optional shared bootstrap progress tracker for failure evidence.
+ pub bootstrap_progress: Option<Arc<VulkanSmokeBootstrapProgress>>,
}
+/// Shared bootstrap progress used to report partial renderer startup evidence.
+#[derive(Debug, Default)]
+pub struct VulkanSmokeBootstrapProgress {
+ flags: AtomicU8,
+}
+
+impl VulkanSmokeBootstrapProgress {
+ /// Marks the Vulkan loader as available.
+ pub fn mark_loader_available(&self) {
+ self.set_flag(BOOTSTRAP_LOADER_AVAILABLE);
+ }
+
+ /// Marks the Vulkan instance as created.
+ pub fn mark_instance_created(&self) {
+ self.set_flag(BOOTSTRAP_INSTANCE_CREATED);
+ }
+
+ /// Marks the Vulkan surface as created.
+ pub fn mark_surface_created(&self) {
+ self.set_flag(BOOTSTRAP_SURFACE_CREATED);
+ }
+
+ /// Marks a suitable Vulkan device as selected and the logical device as created.
+ pub fn mark_logical_device_created(&self) {
+ self.set_flag(BOOTSTRAP_DEVICE_SELECTED | BOOTSTRAP_LOGICAL_DEVICE_CREATED);
+ }
+
+ /// Marks the Vulkan swapchain as created.
+ pub fn mark_swapchain_created(&self) {
+ self.set_flag(BOOTSTRAP_SWAPCHAIN_CREATED);
+ }
+
+ /// Returns a stable snapshot of the measured bootstrap state.
+ #[must_use]
+ pub fn snapshot(&self) -> VulkanSmokeBootstrapSnapshot {
+ let flags = self.flags.load(Ordering::SeqCst);
+ VulkanSmokeBootstrapSnapshot {
+ loader_available: flags & BOOTSTRAP_LOADER_AVAILABLE != 0,
+ instance_created: flags & BOOTSTRAP_INSTANCE_CREATED != 0,
+ surface_created: flags & BOOTSTRAP_SURFACE_CREATED != 0,
+ device_selected: flags & BOOTSTRAP_DEVICE_SELECTED != 0,
+ logical_device_created: flags & BOOTSTRAP_LOGICAL_DEVICE_CREATED != 0,
+ swapchain_created: flags & BOOTSTRAP_SWAPCHAIN_CREATED != 0,
+ }
+ }
+
+ fn set_flag(&self, flag: u8) {
+ self.flags.fetch_or(flag, Ordering::SeqCst);
+ }
+}
+
+/// Stable snapshot of measured bootstrap progress.
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+#[allow(clippy::struct_excessive_bools)]
+pub struct VulkanSmokeBootstrapSnapshot {
+ /// Whether the Vulkan loader was resolved.
+ pub loader_available: bool,
+ /// Whether the Vulkan instance was created.
+ pub instance_created: bool,
+ /// Whether the Vulkan surface was created.
+ pub surface_created: bool,
+ /// Whether a suitable Vulkan device was selected.
+ pub device_selected: bool,
+ /// Whether the logical device was created.
+ pub logical_device_created: bool,
+ /// Whether the swapchain was created.
+ pub swapchain_created: bool,
+}
+
+const BOOTSTRAP_LOADER_AVAILABLE: u8 = 1 << 0;
+const BOOTSTRAP_INSTANCE_CREATED: u8 = 1 << 1;
+const BOOTSTRAP_SURFACE_CREATED: u8 = 1 << 2;
+const BOOTSTRAP_DEVICE_SELECTED: u8 = 1 << 3;
+const BOOTSTRAP_LOGICAL_DEVICE_CREATED: u8 = 1 << 4;
+const BOOTSTRAP_SWAPCHAIN_CREATED: u8 = 1 << 5;
+
/// Stable smoke renderer bootstrap report.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct VulkanSmokeRendererReport {