代码生成完成,待整理

This commit is contained in:
2025-12-30 20:53:03 +08:00
parent 5a131dd9f6
commit b6d44a1ca0
254 changed files with 108047 additions and 408 deletions

511
src/render/frame_sync.cpp Normal file
View File

@@ -0,0 +1,511 @@
/**
* @file frame_sync.cpp
* @brief MILAI 框架帧同步机制实现
* @author MILAI Team
* @version 0.1.0
*/
#include "frame_sync.hpp"
#include "logger.hpp"
namespace milai {
// ================================================================================================
// frame_sync 实现
// ================================================================================================
frame_sync::frame_sync(std::shared_ptr<vulkan_device> device,
std::shared_ptr<swapchain> swap_chain,
const frame_sync_config& config)
: device_(std::move(device))
, swapchain_(std::move(swap_chain))
, frames_in_flight_(config.frames_in_flight)
, fence_timeout_(config.fence_timeout)
{
// 验证参数
if (frames_in_flight_ < 1) {
frames_in_flight_ = 1;
}
if (frames_in_flight_ > 3) {
frames_in_flight_ = 3;
}
// 创建同步对象和命令缓冲
if (!create_sync_objects()) {
LOG_ERROR("Failed to create sync objects");
return;
}
if (!create_command_buffers()) {
LOG_ERROR("Failed to create command buffers");
destroy_sync_objects();
return;
}
// 初始化图像飞行中栅栏
u32 image_count = swapchain_ ? swapchain_->get_image_count() : 0;
images_in_flight_.resize(image_count, VK_NULL_HANDLE);
LOG_DEBUG("Frame sync created with {} frames in flight", frames_in_flight_);
}
frame_sync::~frame_sync() {
if (device_ && device_->is_valid()) {
// 等待设备空闲
device_->wait_idle();
// 销毁资源
destroy_command_buffers();
destroy_sync_objects();
}
}
frame_sync::frame_sync(frame_sync&& other) noexcept
: device_(std::move(other.device_))
, swapchain_(std::move(other.swapchain_))
, command_pool_(other.command_pool_)
, frame_resources_(std::move(other.frame_resources_))
, images_in_flight_(std::move(other.images_in_flight_))
, frames_in_flight_(other.frames_in_flight_)
, current_frame_(other.current_frame_)
, current_image_index_(other.current_image_index_)
, fence_timeout_(other.fence_timeout_)
, on_frame_begin_(std::move(other.on_frame_begin_))
, on_frame_end_(std::move(other.on_frame_end_))
{
other.command_pool_ = VK_NULL_HANDLE;
other.frames_in_flight_ = 0;
other.current_frame_ = 0;
other.current_image_index_ = 0;
}
frame_sync& frame_sync::operator=(frame_sync&& other) noexcept {
if (this != &other) {
// 清理现有资源
if (device_ && device_->is_valid()) {
device_->wait_idle();
destroy_command_buffers();
destroy_sync_objects();
}
// 移动资源
device_ = std::move(other.device_);
swapchain_ = std::move(other.swapchain_);
command_pool_ = other.command_pool_;
frame_resources_ = std::move(other.frame_resources_);
images_in_flight_ = std::move(other.images_in_flight_);
frames_in_flight_ = other.frames_in_flight_;
current_frame_ = other.current_frame_;
current_image_index_ = other.current_image_index_;
fence_timeout_ = other.fence_timeout_;
on_frame_begin_ = std::move(other.on_frame_begin_);
on_frame_end_ = std::move(other.on_frame_end_);
// 清空源对象
other.command_pool_ = VK_NULL_HANDLE;
other.frames_in_flight_ = 0;
other.current_frame_ = 0;
other.current_image_index_ = 0;
}
return *this;
}
std::pair<frame_begin_result, u32> frame_sync::begin_frame() {
if (!is_valid() || !swapchain_) {
return {frame_begin_result::error, 0};
}
const auto& resources = frame_resources_[current_frame_];
// 等待当前帧的栅栏
VkResult result = vkWaitForFences(device_->get_device(), 1,
&resources.in_flight_fence,
VK_TRUE, fence_timeout_);
if (result == VK_TIMEOUT) {
LOG_WARN("Frame fence wait timed out");
return {frame_begin_result::timeout, 0};
} else if (result == VK_ERROR_DEVICE_LOST) {
LOG_ERROR("Device lost while waiting for frame fence");
return {frame_begin_result::device_lost, 0};
} else if (result != VK_SUCCESS) {
LOG_ERROR("Failed to wait for frame fence: {}", vk_result_to_string(result));
return {frame_begin_result::error, 0};
}
// 获取下一个交换链图像
auto [acquire_result, image_index] = swapchain_->acquire_next_image(
resources.image_available_semaphore);
if (acquire_result == acquire_result::out_of_date) {
return {frame_begin_result::swapchain_out_of_date, 0};
} else if (acquire_result != acquire_result::success &&
acquire_result != acquire_result::suboptimal) {
LOG_ERROR("Failed to acquire swapchain image");
return {frame_begin_result::error, 0};
}
current_image_index_ = image_index;
// 检查图像是否仍在使用中
if (images_in_flight_[image_index] != VK_NULL_HANDLE) {
vkWaitForFences(device_->get_device(), 1,
&images_in_flight_[image_index],
VK_TRUE, fence_timeout_);
}
// 标记该图像为当前帧正在使用
images_in_flight_[image_index] = resources.in_flight_fence;
// 重置栅栏
vkResetFences(device_->get_device(), 1, &resources.in_flight_fence);
// 调用帧开始回调
if (on_frame_begin_) {
on_frame_begin_(current_frame_, current_image_index_);
}
return {frame_begin_result::success, current_image_index_};
}
frame_end_result frame_sync::end_frame(VkCommandBuffer cmd_buffer) {
if (!is_valid() || !swapchain_) {
return frame_end_result::error;
}
const auto& resources = frame_resources_[current_frame_];
// 提交命令缓冲
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
VkSemaphore wait_semaphores[] = {resources.image_available_semaphore};
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = wait_semaphores;
submit_info.pWaitDstStageMask = wait_stages;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &cmd_buffer;
VkSemaphore signal_semaphores[] = {resources.render_finished_semaphore};
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = signal_semaphores;
VkResult result = vkQueueSubmit(device_->get_graphics_queue(), 1,
&submit_info, resources.in_flight_fence);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to submit command buffer: {}", vk_result_to_string(result));
return frame_end_result::error;
}
// 呈现图像
VkSemaphore present_wait_semaphores[] = {resources.render_finished_semaphore};
auto present_result = swapchain_->present(device_->get_present_queue(),
{present_wait_semaphores, 1});
// 调用帧结束回调
if (on_frame_end_) {
on_frame_end_(current_frame_);
}
// 推进到下一帧
advance_frame();
// 检查呈现结果
if (present_result == present_result::out_of_date) {
return frame_end_result::swapchain_out_of_date;
} else if (present_result == present_result::suboptimal) {
return frame_end_result::swapchain_suboptimal;
} else if (present_result != present_result::success) {
return frame_end_result::error;
}
return frame_end_result::success;
}
frame_end_result frame_sync::end_frame() {
return end_frame(frame_resources_[current_frame_].command_buffer);
}
bool frame_sync::wait_for_current_frame() {
if (!is_valid()) {
return false;
}
const auto& resources = frame_resources_[current_frame_];
VkResult result = vkWaitForFences(device_->get_device(), 1,
&resources.in_flight_fence,
VK_TRUE, fence_timeout_);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to wait for current frame: {}", vk_result_to_string(result));
return false;
}
return true;
}
bool frame_sync::wait_for_all_frames() {
if (!is_valid()) {
return false;
}
// 收集所有栅栏
std::vector<VkFence> fences;
fences.reserve(frames_in_flight_);
for (const auto& resources : frame_resources_) {
if (resources.in_flight_fence != VK_NULL_HANDLE) {
fences.push_back(resources.in_flight_fence);
}
}
if (fences.empty()) {
return true;
}
VkResult result = vkWaitForFences(device_->get_device(),
static_cast<u32>(fences.size()),
fences.data(), VK_TRUE, fence_timeout_);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to wait for all frames: {}", vk_result_to_string(result));
return false;
}
return true;
}
bool frame_sync::recreate(std::shared_ptr<swapchain> new_swapchain) {
if (!device_ || !device_->is_valid()) {
return false;
}
// 等待所有帧完成
wait_for_all_frames();
// 更新交换链
swapchain_ = std::move(new_swapchain);
// 重新初始化图像飞行中栅栏
u32 image_count = swapchain_ ? swapchain_->get_image_count() : 0;
images_in_flight_.clear();
images_in_flight_.resize(image_count, VK_NULL_HANDLE);
// 重置当前帧索引
current_frame_ = 0;
current_image_index_ = 0;
LOG_DEBUG("Frame sync recreated for new swapchain");
return true;
}
void frame_sync::on_created() {
LOG_DEBUG("Frame sync created");
}
void frame_sync::on_destroying() {
LOG_DEBUG("Frame sync destroying");
}
bool frame_sync::create_sync_objects() {
if (!device_ || !device_->is_valid()) {
return false;
}
frame_resources_.resize(frames_in_flight_);
VkSemaphoreCreateInfo semaphore_info{};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
VkFenceCreateInfo fence_info{};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; // 初始状态为已信号
for (u32 i = 0; i < frames_in_flight_; ++i) {
auto& resources = frame_resources_[i];
// 创建图像可用信号量
VkResult result = vkCreateSemaphore(device_->get_device(), &semaphore_info,
nullptr, &resources.image_available_semaphore);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to create image available semaphore: {}",
vk_result_to_string(result));
return false;
}
// 创建渲染完成信号量
result = vkCreateSemaphore(device_->get_device(), &semaphore_info,
nullptr, &resources.render_finished_semaphore);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to create render finished semaphore: {}",
vk_result_to_string(result));
return false;
}
// 创建飞行中栅栏
result = vkCreateFence(device_->get_device(), &fence_info,
nullptr, &resources.in_flight_fence);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to create in flight fence: {}",
vk_result_to_string(result));
return false;
}
}
LOG_DEBUG("Created {} sets of sync objects", frames_in_flight_);
return true;
}
bool frame_sync::create_command_buffers() {
if (!device_ || !device_->is_valid()) {
return false;
}
// 创建命令池
VkCommandPoolCreateInfo pool_info{};
pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
pool_info.queueFamilyIndex = device_->get_queue_family_indices().graphics_family;
VkResult result = vkCreateCommandPool(device_->get_device(), &pool_info,
nullptr, &command_pool_);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to create command pool: {}", vk_result_to_string(result));
return false;
}
// 分配命令缓冲
std::vector<VkCommandBuffer> buffers(frames_in_flight_);
VkCommandBufferAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
alloc_info.commandPool = command_pool_;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.commandBufferCount = frames_in_flight_;
result = vkAllocateCommandBuffers(device_->get_device(), &alloc_info, buffers.data());
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to allocate command buffers: {}", vk_result_to_string(result));
return false;
}
for (u32 i = 0; i < frames_in_flight_; ++i) {
frame_resources_[i].command_buffer = buffers[i];
}
LOG_DEBUG("Created command pool and {} command buffers", frames_in_flight_);
return true;
}
void frame_sync::destroy_sync_objects() {
if (!device_ || !device_->is_valid()) {
return;
}
for (auto& resources : frame_resources_) {
if (resources.image_available_semaphore != VK_NULL_HANDLE) {
vkDestroySemaphore(device_->get_device(),
resources.image_available_semaphore, nullptr);
resources.image_available_semaphore = VK_NULL_HANDLE;
}
if (resources.render_finished_semaphore != VK_NULL_HANDLE) {
vkDestroySemaphore(device_->get_device(),
resources.render_finished_semaphore, nullptr);
resources.render_finished_semaphore = VK_NULL_HANDLE;
}
if (resources.in_flight_fence != VK_NULL_HANDLE) {
vkDestroyFence(device_->get_device(),
resources.in_flight_fence, nullptr);
resources.in_flight_fence = VK_NULL_HANDLE;
}
}
}
void frame_sync::destroy_command_buffers() {
if (!device_ || !device_->is_valid()) {
return;
}
// 命令缓冲在命令池销毁时自动释放
if (command_pool_ != VK_NULL_HANDLE) {
vkDestroyCommandPool(device_->get_device(), command_pool_, nullptr);
command_pool_ = VK_NULL_HANDLE;
}
for (auto& resources : frame_resources_) {
resources.command_buffer = VK_NULL_HANDLE;
}
}
// ================================================================================================
// frame_time_tracker 实现
// ================================================================================================
frame_time_tracker::frame_time_tracker(u32 sample_count)
: sample_count_(sample_count)
{
frame_time_samples_.resize(sample_count, 0.0);
}
void frame_time_tracker::begin_frame() {
frame_start_time_ = std::chrono::high_resolution_clock::now();
}
void frame_time_tracker::end_frame() {
auto end_time = std::chrono::high_resolution_clock::now();
auto duration = std::chrono::duration<f64, std::milli>(end_time - frame_start_time_);
current_frame_time_ms_ = duration.count();
// 更新样本
frame_time_samples_[current_sample_index_] = current_frame_time_ms_;
current_sample_index_ = (current_sample_index_ + 1) % sample_count_;
if (!samples_filled_ && current_sample_index_ == 0) {
samples_filled_ = true;
}
// 更新统计
++frame_count_;
total_time_s_ += current_frame_time_ms_ / 1000.0;
}
frame_timing frame_time_tracker::get_timing() const {
frame_timing timing;
timing.cpu_frame_time_ms = current_frame_time_ms_;
timing.gpu_frame_time_ms = 0.0; // GPU 时间需要使用 GPU 查询获取
timing.fps = current_frame_time_ms_ > 0.0 ? 1000.0 / current_frame_time_ms_ : 0.0;
timing.frame_count = frame_count_;
timing.total_time_s = total_time_s_;
return timing;
}
f64 frame_time_tracker::get_average_frame_time_ms() const {
u32 count = samples_filled_ ? sample_count_ : current_sample_index_;
if (count == 0) {
return 0.0;
}
f64 sum = 0.0;
for (u32 i = 0; i < count; ++i) {
sum += frame_time_samples_[i];
}
return sum / static_cast<f64>(count);
}
f64 frame_time_tracker::get_average_fps() const {
f64 avg_time = get_average_frame_time_ms();
return avg_time > 0.0 ? 1000.0 / avg_time : 0.0;
}
void frame_time_tracker::reset() {
std::fill(frame_time_samples_.begin(), frame_time_samples_.end(), 0.0);
current_sample_index_ = 0;
samples_filled_ = false;
current_frame_time_ms_ = 0.0;
frame_count_ = 0;
total_time_s_ = 0.0;
}
} // namespace milai