aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-06-25 05:57:26 +0300
committerValentin Popov <valentin@popov.link>2026-06-25 10:45:37 +0300
commit8f8fa426d58b0f764b350356fab97895e8b42ffc (patch)
tree5741a8d270606697b59e151e60bc6dcda78568da
parent4d0cb594a7800d8b6b4d5995aaf579b8e7b32e67 (diff)
downloadfparkan-8f8fa426d58b0f764b350356fab97895e8b42ffc.tar.xz
fparkan-8f8fa426d58b0f764b350356fab97895e8b42ffc.zip
refactor(vulkan-backend): satisfy ci quality gates
-rw-r--r--adapters/fparkan-render-vulkan/src/ffi/resources.rs147
-rw-r--r--adapters/fparkan-render-vulkan/src/planning_backend.rs25
-rw-r--r--apps/fparkan-game/src/main.rs4
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)
))
}