refactor(vulkan-backend): extract planning facade module
This commit is contained in:
@@ -32,11 +32,8 @@ use ash::{
|
|||||||
vk,
|
vk,
|
||||||
};
|
};
|
||||||
use fparkan_binary::{sha256, sha256_hex};
|
use fparkan_binary::{sha256, sha256_hex};
|
||||||
use fparkan_platform::{NativeWindowHandles, RenderRequest};
|
use fparkan_platform::NativeWindowHandles;
|
||||||
use fparkan_render::{
|
use fparkan_render::{validate_command_list, RenderCommand, RenderCommandList, RenderError};
|
||||||
canonical_capture, validate_command_list, FrameOutput, RenderBackend, RenderCommand,
|
|
||||||
RenderCommandList, RenderError,
|
|
||||||
};
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::collections::BTreeSet;
|
use std::collections::BTreeSet;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
@@ -3600,23 +3597,6 @@ fn render_shader_manifest_without_hash_json(modules: &[VulkanShaderModuleReport]
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Vulkan backend migration readiness.
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
||||||
pub enum VulkanPlanningBackendState {
|
|
||||||
/// Adapter prepared and able to accept commands.
|
|
||||||
Ready,
|
|
||||||
/// Adapter is tracking a recoverable runtime surface/depth pipeline fault.
|
|
||||||
Degraded,
|
|
||||||
/// Adapter has encountered a non-recoverable error.
|
|
||||||
Error,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for VulkanPlanningBackendState {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Degraded
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Synthetic physical-device type used by deterministic capability scoring.
|
/// Synthetic physical-device type used by deterministic capability scoring.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum VulkanDeviceType {
|
pub enum VulkanDeviceType {
|
||||||
@@ -4320,139 +4300,12 @@ fn format_api_version(version: u32) -> String {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Diagnostics for Vulkan planning backend setup and frame progression.
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct VulkanPlanningBackendReport {
|
|
||||||
/// Total frames executed.
|
|
||||||
pub frames_executed: u64,
|
|
||||||
/// Total command submissions.
|
|
||||||
pub submissions: u64,
|
|
||||||
/// Last command-capture byte size.
|
|
||||||
pub last_capture_size: usize,
|
|
||||||
/// Number of simulated present calls issued by the planning facade.
|
|
||||||
pub simulated_presents: u64,
|
|
||||||
/// Number of resize-driven surface plan refreshes.
|
|
||||||
pub resize_rebuilds: u64,
|
|
||||||
/// Last render request observed.
|
|
||||||
pub request: RenderRequest,
|
|
||||||
/// Last deterministic frame submission plan.
|
|
||||||
pub last_frame_submission: Option<VulkanFrameSubmissionPlan>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for VulkanPlanningBackendReport {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
frames_executed: 0,
|
|
||||||
submissions: 0,
|
|
||||||
last_capture_size: 0,
|
|
||||||
simulated_presents: 0,
|
|
||||||
resize_rebuilds: 0,
|
|
||||||
request: RenderRequest::conservative(),
|
|
||||||
last_frame_submission: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Vulkan planning backend façade used by the game entrypoint.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct VulkanPlanningBackend {
|
|
||||||
state: VulkanPlanningBackendState,
|
|
||||||
report: VulkanPlanningBackendReport,
|
|
||||||
swapchain_plan: VulkanSwapchainPlan,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for VulkanPlanningBackend {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl VulkanPlanningBackend {
|
|
||||||
/// Creates a new Vulkan planning backend façade.
|
|
||||||
#[must_use]
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
state: VulkanPlanningBackendState::Ready,
|
|
||||||
report: VulkanPlanningBackendReport::default(),
|
|
||||||
swapchain_plan: default_stage0_swapchain_plan(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replaces active surface/profile request.
|
|
||||||
pub fn set_render_request(&mut self, request: RenderRequest) {
|
|
||||||
self.report.request = request;
|
|
||||||
self.report.resize_rebuilds = self.report.resize_rebuilds.saturating_add(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns active render request policy.
|
|
||||||
#[must_use]
|
|
||||||
pub const fn render_request(&self) -> RenderRequest {
|
|
||||||
self.report.request
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Replaces active swapchain plan used for frame submission planning.
|
|
||||||
pub fn set_swapchain_plan(&mut self, plan: VulkanSwapchainPlan) {
|
|
||||||
self.swapchain_plan = plan;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns active swapchain plan.
|
|
||||||
#[must_use]
|
|
||||||
pub const fn swapchain_plan(&self) -> &VulkanSwapchainPlan {
|
|
||||||
&self.swapchain_plan
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns adapter state.
|
|
||||||
#[must_use]
|
|
||||||
pub const fn state(&self) -> VulkanPlanningBackendState {
|
|
||||||
self.state
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns backend report.
|
|
||||||
#[must_use]
|
|
||||||
pub fn report(&self) -> &VulkanPlanningBackendReport {
|
|
||||||
&self.report
|
|
||||||
}
|
|
||||||
|
|
||||||
fn simulate_present(&mut self) {
|
|
||||||
self.report.simulated_presents = self.report.simulated_presents.saturating_add(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RenderBackend for VulkanPlanningBackend {
|
|
||||||
fn execute(&mut self, commands: &RenderCommandList) -> Result<FrameOutput, RenderError> {
|
|
||||||
if !matches!(
|
|
||||||
self.state,
|
|
||||||
VulkanPlanningBackendState::Ready | VulkanPlanningBackendState::Degraded
|
|
||||||
) {
|
|
||||||
return Err(RenderError::InvalidRange);
|
|
||||||
}
|
|
||||||
let capture = canonical_capture(commands)?;
|
|
||||||
let frame_plan = plan_vulkan_frame_submission(&self.swapchain_plan, commands)?;
|
|
||||||
self.report.frames_executed = self.report.frames_executed.saturating_add(1);
|
|
||||||
self.report.submissions = self.report.submissions.saturating_add(1);
|
|
||||||
self.report.last_capture_size = capture.len();
|
|
||||||
self.report.last_frame_submission = Some(frame_plan);
|
|
||||||
self.simulate_present();
|
|
||||||
Ok(FrameOutput)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_stage0_swapchain_plan() -> VulkanSwapchainPlan {
|
|
||||||
VulkanSwapchainPlan {
|
|
||||||
schema: 1,
|
|
||||||
extent: (1, 1),
|
|
||||||
format: VulkanSurfaceFormat {
|
|
||||||
format: vk::Format::B8G8R8A8_SRGB.as_raw(),
|
|
||||||
color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR.as_raw(),
|
|
||||||
},
|
|
||||||
present_mode: vk::PresentModeKHR::FIFO.as_raw(),
|
|
||||||
image_count: 2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::*;
|
||||||
|
use fparkan_platform::RenderRequest;
|
||||||
|
use fparkan_render::RenderBackend;
|
||||||
use fparkan_render::{
|
use fparkan_render::{
|
||||||
DrawCommand, DrawId, GpuMaterialId, GpuMeshId, IndexRange, RenderCommand, RenderPhase,
|
DrawCommand, DrawId, GpuMaterialId, GpuMeshId, IndexRange, RenderCommand, RenderPhase,
|
||||||
};
|
};
|
||||||
@@ -4522,8 +4375,14 @@ mod tests {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
let swapchain = VulkanSwapchainPlan {
|
let swapchain = VulkanSwapchainPlan {
|
||||||
|
schema: 1,
|
||||||
|
extent: (1, 1),
|
||||||
|
format: VulkanSurfaceFormat {
|
||||||
|
format: vk::Format::B8G8R8A8_SRGB.as_raw(),
|
||||||
|
color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR.as_raw(),
|
||||||
|
},
|
||||||
|
present_mode: vk::PresentModeKHR::FIFO.as_raw(),
|
||||||
image_count: 3,
|
image_count: 3,
|
||||||
..default_stage0_swapchain_plan()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let plan = plan_vulkan_frame_submission(&swapchain, &commands)?;
|
let plan = plan_vulkan_frame_submission(&swapchain, &commands)?;
|
||||||
|
|||||||
@@ -2,5 +2,7 @@
|
|||||||
//! Vulkan adapter public surface.
|
//! Vulkan adapter public surface.
|
||||||
|
|
||||||
mod ffi;
|
mod ffi;
|
||||||
|
mod planning_backend;
|
||||||
|
|
||||||
pub use ffi::*;
|
pub use ffi::*;
|
||||||
|
pub use planning_backend::*;
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
use ash::vk;
|
||||||
|
use fparkan_platform::RenderRequest;
|
||||||
|
use fparkan_render::{
|
||||||
|
canonical_capture, FrameOutput, RenderBackend, RenderCommandList, RenderError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
plan_vulkan_frame_submission, VulkanFrameSubmissionPlan, VulkanSurfaceFormat,
|
||||||
|
VulkanSwapchainPlan,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Vulkan backend migration readiness.
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
pub enum VulkanPlanningBackendState {
|
||||||
|
/// Adapter prepared and able to accept commands.
|
||||||
|
Ready,
|
||||||
|
/// Adapter is tracking a recoverable runtime surface/depth pipeline fault.
|
||||||
|
Degraded,
|
||||||
|
/// Adapter has encountered a non-recoverable error.
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VulkanPlanningBackendState {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::Degraded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Diagnostics for Vulkan planning backend setup and frame progression.
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct VulkanPlanningBackendReport {
|
||||||
|
/// Total frames executed.
|
||||||
|
pub frames_executed: u64,
|
||||||
|
/// Total command submissions.
|
||||||
|
pub submissions: u64,
|
||||||
|
/// Last command-capture byte size.
|
||||||
|
pub last_capture_size: usize,
|
||||||
|
/// Number of simulated present calls issued by the planning facade.
|
||||||
|
pub simulated_presents: u64,
|
||||||
|
/// Number of resize-driven surface plan refreshes.
|
||||||
|
pub resize_rebuilds: u64,
|
||||||
|
/// Last render request observed.
|
||||||
|
pub request: RenderRequest,
|
||||||
|
/// Last deterministic frame submission plan.
|
||||||
|
pub last_frame_submission: Option<VulkanFrameSubmissionPlan>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VulkanPlanningBackendReport {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
frames_executed: 0,
|
||||||
|
submissions: 0,
|
||||||
|
last_capture_size: 0,
|
||||||
|
simulated_presents: 0,
|
||||||
|
resize_rebuilds: 0,
|
||||||
|
request: RenderRequest::conservative(),
|
||||||
|
last_frame_submission: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Vulkan planning backend facade used by the game entrypoint.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct VulkanPlanningBackend {
|
||||||
|
state: VulkanPlanningBackendState,
|
||||||
|
report: VulkanPlanningBackendReport,
|
||||||
|
swapchain_plan: VulkanSwapchainPlan,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for VulkanPlanningBackend {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VulkanPlanningBackend {
|
||||||
|
/// Creates a new Vulkan planning backend facade.
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
state: VulkanPlanningBackendState::Ready,
|
||||||
|
report: VulkanPlanningBackendReport::default(),
|
||||||
|
swapchain_plan: default_stage0_swapchain_plan(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces active surface/profile request.
|
||||||
|
pub fn set_render_request(&mut self, request: RenderRequest) {
|
||||||
|
self.report.request = request;
|
||||||
|
self.report.resize_rebuilds = self.report.resize_rebuilds.saturating_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns active render request policy.
|
||||||
|
#[must_use]
|
||||||
|
pub const fn render_request(&self) -> RenderRequest {
|
||||||
|
self.report.request
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Replaces active swapchain plan used for frame submission planning.
|
||||||
|
pub fn set_swapchain_plan(&mut self, plan: VulkanSwapchainPlan) {
|
||||||
|
self.swapchain_plan = plan;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns active swapchain plan.
|
||||||
|
#[must_use]
|
||||||
|
pub const fn swapchain_plan(&self) -> &VulkanSwapchainPlan {
|
||||||
|
&self.swapchain_plan
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns adapter state.
|
||||||
|
#[must_use]
|
||||||
|
pub const fn state(&self) -> VulkanPlanningBackendState {
|
||||||
|
self.state
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns backend report.
|
||||||
|
#[must_use]
|
||||||
|
pub fn report(&self) -> &VulkanPlanningBackendReport {
|
||||||
|
&self.report
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simulate_present(&mut self) {
|
||||||
|
self.report.simulated_presents = self.report.simulated_presents.saturating_add(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RenderBackend for VulkanPlanningBackend {
|
||||||
|
fn execute(&mut self, commands: &RenderCommandList) -> Result<FrameOutput, RenderError> {
|
||||||
|
if !matches!(
|
||||||
|
self.state,
|
||||||
|
VulkanPlanningBackendState::Ready | VulkanPlanningBackendState::Degraded
|
||||||
|
) {
|
||||||
|
return Err(RenderError::InvalidRange);
|
||||||
|
}
|
||||||
|
let capture = canonical_capture(commands)?;
|
||||||
|
let frame_plan = plan_vulkan_frame_submission(&self.swapchain_plan, commands)?;
|
||||||
|
self.report.frames_executed = self.report.frames_executed.saturating_add(1);
|
||||||
|
self.report.submissions = self.report.submissions.saturating_add(1);
|
||||||
|
self.report.last_capture_size = capture.len();
|
||||||
|
self.report.last_frame_submission = Some(frame_plan);
|
||||||
|
self.simulate_present();
|
||||||
|
Ok(FrameOutput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_stage0_swapchain_plan() -> VulkanSwapchainPlan {
|
||||||
|
VulkanSwapchainPlan {
|
||||||
|
schema: 1,
|
||||||
|
extent: (1, 1),
|
||||||
|
format: VulkanSurfaceFormat {
|
||||||
|
format: vk::Format::B8G8R8A8_SRGB.as_raw(),
|
||||||
|
color_space: vk::ColorSpaceKHR::SRGB_NONLINEAR.as_raw(),
|
||||||
|
},
|
||||||
|
present_mode: vk::PresentModeKHR::FIFO.as_raw(),
|
||||||
|
image_count: 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user