diff options
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/ffi/resources.rs | 147 | ||||
| -rw-r--r-- | adapters/fparkan-render-vulkan/src/planning_backend.rs | 25 | ||||
| -rw-r--r-- | apps/fparkan-game/src/main.rs | 4 |
3 files changed, 101 insertions, 75 deletions
diff --git a/adapters/fparkan-render-vulkan/src/ffi/resources.rs b/adapters/fparkan-render-vulkan/src/ffi/resources.rs index 4d061c8..2f33faf 100644 --- a/adapters/fparkan-render-vulkan/src/ffi/resources.rs +++ b/adapters/fparkan-render-vulkan/src/ffi/resources.rs @@ -216,77 +216,45 @@ pub(super) fn create_swapchain_resources( result: error, })?; let mut partial = PartialSwapchainResources { - image_views: Vec::with_capacity(images.len()), + image_views: create_swapchain_image_views( + device, + &images, + swapchain.report.plan.format.format, + )?, render_pass: None, pipeline_layout: None, pipeline: None, - framebuffers: Vec::with_capacity(images.len()), + framebuffers: Vec::new(), command_buffers: Vec::new(), }; - for image in images.iter().copied() { - match create_image_view(device, image, swapchain.report.plan.format.format) { - Ok(image_view) => partial.image_views.push(image_view), - Err(error) => { - destroy_partial_swapchain_resources(device, command_pool, partial); - return Err(error); - } - } - } - let render_pass = match create_render_pass(device, swapchain.report.plan.format.format) { - Ok(render_pass) => render_pass, + let (render_pass, pipeline_layout, pipeline) = match create_swapchain_pipeline_bundle( + device, + swapchain.report.plan.format.format, + swapchain.report.plan.extent, + ) { + Ok(bundle) => bundle, Err(error) => { destroy_partial_swapchain_resources(device, command_pool, partial); return Err(error); } }; partial.render_pass = Some(render_pass); - let pipeline_layout = match create_pipeline_layout(device) { - Ok(pipeline_layout) => pipeline_layout, - Err(error) => { - destroy_partial_swapchain_resources(device, command_pool, partial); - return Err(error); - } - }; partial.pipeline_layout = Some(pipeline_layout); - let pipeline = match create_graphics_pipeline( + partial.pipeline = Some(pipeline); + let framebuffers = match create_swapchain_framebuffers( device, render_pass, - pipeline_layout, + &partial.image_views, swapchain.report.plan.extent, ) { - Ok(pipeline) => pipeline, + Ok(framebuffers) => framebuffers, Err(error) => { destroy_partial_swapchain_resources(device, command_pool, partial); return Err(error); } }; - partial.pipeline = Some(pipeline); - for image_view in partial.image_views.iter().copied() { - match create_framebuffer( - device, - render_pass, - image_view, - swapchain.report.plan.extent, - ) { - Ok(framebuffer) => partial.framebuffers.push(framebuffer), - Err(error) => { - destroy_partial_swapchain_resources(device, command_pool, partial); - return Err(error); - } - } - } - if reuse_command_pool { - // SAFETY: All command buffers allocated from the live pool are freed before reallocating them. - unsafe { - device - .device() - .reset_command_pool(command_pool, vk::CommandPoolResetFlags::empty()) - } - .map_err(|error| VulkanSmokeRendererError::VulkanOperation { - context: "vkResetCommandPool", - result: error, - })?; - } + partial.framebuffers = framebuffers; + reset_reusable_command_pool(device, command_pool, reuse_command_pool)?; let command_buffers = match allocate_command_buffers( device, command_pool, @@ -310,6 +278,85 @@ pub(super) fn create_swapchain_resources( }) } +fn create_swapchain_image_views( + device: &VulkanLogicalDeviceProbe, + images: &[vk::Image], + format: i32, +) -> Result<Vec<vk::ImageView>, VulkanSmokeRendererError> { + let mut image_views = Vec::with_capacity(images.len()); + for image in images.iter().copied() { + image_views.push(create_image_view(device, image, format)?); + } + Ok(image_views) +} + +fn create_swapchain_pipeline_bundle( + device: &VulkanLogicalDeviceProbe, + format: i32, + extent: (u32, u32), +) -> Result<(vk::RenderPass, vk::PipelineLayout, vk::Pipeline), VulkanSmokeRendererError> { + let render_pass = create_render_pass(device, format)?; + let pipeline_layout = create_pipeline_layout(device).inspect_err(|_| { + // SAFETY: The render pass was created above on this live logical device and is destroyed on setup failure. + unsafe { device.device().destroy_render_pass(render_pass, None) }; + })?; + let pipeline = create_graphics_pipeline(device, render_pass, pipeline_layout, extent) + .inspect_err(|_| { + // SAFETY: These objects were created above on this live logical device and are destroyed on setup failure. + unsafe { + device + .device() + .destroy_pipeline_layout(pipeline_layout, None); + device.device().destroy_render_pass(render_pass, None); + } + })?; + Ok((render_pass, pipeline_layout, pipeline)) +} + +fn create_swapchain_framebuffers( + device: &VulkanLogicalDeviceProbe, + render_pass: vk::RenderPass, + image_views: &[vk::ImageView], + extent: (u32, u32), +) -> Result<Vec<vk::Framebuffer>, VulkanSmokeRendererError> { + let mut framebuffers = Vec::with_capacity(image_views.len()); + for image_view in image_views.iter().copied() { + match create_framebuffer(device, render_pass, image_view, extent) { + Ok(framebuffer) => framebuffers.push(framebuffer), + Err(error) => { + // SAFETY: These framebuffers were created above on this live logical device and are destroyed on setup failure. + unsafe { + for framebuffer in framebuffers.iter().copied() { + device.device().destroy_framebuffer(framebuffer, None); + } + } + return Err(error); + } + } + } + Ok(framebuffers) +} + +fn reset_reusable_command_pool( + device: &VulkanLogicalDeviceProbe, + command_pool: vk::CommandPool, + reuse_command_pool: bool, +) -> Result<(), VulkanSmokeRendererError> { + if !reuse_command_pool { + return Ok(()); + } + // SAFETY: All command buffers allocated from the live pool are freed before reallocating them. + unsafe { + device + .device() + .reset_command_pool(command_pool, vk::CommandPoolResetFlags::empty()) + } + .map_err(|error| VulkanSmokeRendererError::VulkanOperation { + context: "vkResetCommandPool", + result: error, + }) +} + fn create_image_view( device: &VulkanLogicalDeviceProbe, image: vk::Image, diff --git a/adapters/fparkan-render-vulkan/src/planning_backend.rs b/adapters/fparkan-render-vulkan/src/planning_backend.rs index a57bc8a..4936007 100644 --- a/adapters/fparkan-render-vulkan/src/planning_backend.rs +++ b/adapters/fparkan-render-vulkan/src/planning_backend.rs @@ -45,7 +45,7 @@ impl Default for VulkanPlanningRequestReport { } /// Diagnostics for planning-facade execution telemetry. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct VulkanPlanningExecutionReport { /// Total frames planned by the facade. pub planned_frames: u64, @@ -57,19 +57,8 @@ pub struct VulkanPlanningExecutionReport { pub simulated_presents: u64, } -impl Default for VulkanPlanningExecutionReport { - fn default() -> Self { - Self { - planned_frames: 0, - submission_plans: 0, - last_capture_size: 0, - simulated_presents: 0, - } - } -} - /// Diagnostics for Vulkan planning backend setup and frame progression. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq)] pub struct VulkanPlanningBackendReport { /// Request-tracking telemetry. pub request: VulkanPlanningRequestReport, @@ -79,16 +68,6 @@ pub struct VulkanPlanningBackendReport { pub last_frame_submission: Option<VulkanFrameSubmissionPlan>, } -impl Default for VulkanPlanningBackendReport { - fn default() -> Self { - Self { - request: VulkanPlanningRequestReport::default(), - execution: VulkanPlanningExecutionReport::default(), - last_frame_submission: None, - } - } -} - /// Vulkan planning backend facade used by the game entrypoint. #[derive(Debug)] pub struct VulkanPlanningBackend { diff --git a/apps/fparkan-game/src/main.rs b/apps/fparkan-game/src/main.rs index 5663330..252cd16 100644 --- a/apps/fparkan-game/src/main.rs +++ b/apps/fparkan-game/src/main.rs @@ -104,8 +104,8 @@ fn run(args: &[String]) -> Result<String, String> { args.frames, last_tick, last_draw_count, - capture_report.submissions, - capture_report.last_capture_size, + capture_report.execution.submission_plans, + capture_report.execution.last_capture_size, json_hash(&last_hash) )) } |
