迁移到vulkan hpp

This commit is contained in:
2025-12-31 02:02:01 +08:00
parent b63b48732b
commit ecdc23ee19
56 changed files with 2943 additions and 3052 deletions

View File

@@ -32,21 +32,21 @@ frame_sync::frame_sync(std::shared_ptr<vulkan_device> device,
// 创建同步对象和命令缓冲
if (!create_sync_objects()) {
LOG_ERROR("Failed to create sync objects");
MILAI_LOG_ERROR("Failed to create sync objects");
return;
}
if (!create_command_buffers()) {
LOG_ERROR("Failed to create command buffers");
MILAI_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);
images_in_flight_.resize(image_count, nullptr);
LOG_DEBUG("Frame sync created with {} frames in flight", frames_in_flight_);
MILAI_LOG_DEBUG("Frame sync created with {} frames in flight", frames_in_flight_);
}
frame_sync::~frame_sync() {
@@ -73,7 +73,7 @@ frame_sync::frame_sync(frame_sync&& other) noexcept
, 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.command_pool_ = nullptr;
other.frames_in_flight_ = 0;
other.current_frame_ = 0;
other.current_image_index_ = 0;
@@ -102,7 +102,7 @@ frame_sync& frame_sync::operator=(frame_sync&& other) noexcept {
on_frame_end_ = std::move(other.on_frame_end_);
// 清空源对象
other.command_pool_ = VK_NULL_HANDLE;
other.command_pool_ = nullptr;
other.frames_in_flight_ = 0;
other.current_frame_ = 0;
other.current_image_index_ = 0;
@@ -118,18 +118,16 @@ std::pair<frame_begin_result, u32> frame_sync::begin_frame() {
const auto& resources = frame_resources_[current_frame_];
// 等待当前帧的栅栏
VkResult result = vkWaitForFences(device_->get_device(), 1,
&resources.in_flight_fence,
VK_TRUE, fence_timeout_);
vk::Result result = device_->get_device().waitForFences(resources.in_flight_fence, vk::True, fence_timeout_);
if (result == VK_TIMEOUT) {
LOG_WARN("Frame fence wait timed out");
if (result == vk::Result::eTimeout) {
MILAI_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");
} else if (result == vk::Result::eErrorDeviceLost) {
MILAI_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));
} else if (result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to wait for frame fence: {}", vk::to_string(result));
return {frame_begin_result::error, 0};
}
@@ -141,24 +139,22 @@ std::pair<frame_begin_result, u32> frame_sync::begin_frame() {
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");
MILAI_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_);
if (images_in_flight_[image_index]) {
device_->get_device().waitForFences(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);
device_->get_device().resetFences(resources.in_flight_fence);
// 调用帧开始回调
if (on_frame_begin_) {
@@ -168,7 +164,7 @@ std::pair<frame_begin_result, u32> frame_sync::begin_frame() {
return {frame_begin_result::success, current_image_index_};
}
frame_end_result frame_sync::end_frame(VkCommandBuffer cmd_buffer) {
frame_end_result frame_sync::end_frame(vk::CommandBuffer cmd_buffer) {
if (!is_valid() || !swapchain_) {
return frame_end_result::error;
}
@@ -176,33 +172,26 @@ frame_end_result frame_sync::end_frame(VkCommandBuffer cmd_buffer) {
const auto& resources = frame_resources_[current_frame_];
// 提交命令缓冲
VkSubmitInfo submit_info{};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
vk::SubmitInfo 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;
vk::Semaphore wait_semaphores[] = {resources.image_available_semaphore};
vk::PipelineStageFlags wait_stages[] = {vk::PipelineStageFlagBits::eColorAttachmentOutput};
submit_info.setWaitSemaphores(wait_semaphores)
.setWaitDstStageMask(wait_stages)
.setCommandBuffers(cmd_buffer);
VkSemaphore signal_semaphores[] = {resources.render_finished_semaphore};
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = signal_semaphores;
vk::Semaphore signal_semaphores[] = {resources.render_finished_semaphore};
submit_info.setSignalSemaphores(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));
vk::Result submit_result = device_->get_graphics_queue().submit(submit_info, resources.in_flight_fence);
if (submit_result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to submit command buffer: {}", vk::to_string(submit_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});
auto present_result = swapchain_->present(current_image_index_,
resources.render_finished_semaphore);
// 调用帧结束回调
if (on_frame_end_) {
@@ -234,12 +223,11 @@ bool frame_sync::wait_for_current_frame() {
}
const auto& resources = frame_resources_[current_frame_];
VkResult result = vkWaitForFences(device_->get_device(), 1,
&resources.in_flight_fence,
VK_TRUE, fence_timeout_);
vk::Result result = device_->get_device().waitForFences(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));
if (result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to wait for current frame: {}", vk::to_string(result));
return false;
}
@@ -252,10 +240,10 @@ bool frame_sync::wait_for_all_frames() {
}
// 收集所有栅栏
std::vector<VkFence> fences;
std::vector<vk::Fence> fences;
fences.reserve(frames_in_flight_);
for (const auto& resources : frame_resources_) {
if (resources.in_flight_fence != VK_NULL_HANDLE) {
if (resources.in_flight_fence) {
fences.push_back(resources.in_flight_fence);
}
}
@@ -264,12 +252,10 @@ bool frame_sync::wait_for_all_frames() {
return true;
}
VkResult result = vkWaitForFences(device_->get_device(),
static_cast<u32>(fences.size()),
fences.data(), VK_TRUE, fence_timeout_);
vk::Result result = device_->get_device().waitForFences(fences, vk::True, fence_timeout_);
if (result != VK_SUCCESS) {
LOG_ERROR("Failed to wait for all frames: {}", vk_result_to_string(result));
if (result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to wait for all frames: {}", vk::to_string(result));
return false;
}
@@ -290,22 +276,22 @@ bool frame_sync::recreate(std::shared_ptr<swapchain> new_swapchain) {
// 重新初始化图像飞行中栅栏
u32 image_count = swapchain_ ? swapchain_->get_image_count() : 0;
images_in_flight_.clear();
images_in_flight_.resize(image_count, VK_NULL_HANDLE);
images_in_flight_.resize(image_count, nullptr);
// 重置当前帧索引
current_frame_ = 0;
current_image_index_ = 0;
LOG_DEBUG("Frame sync recreated for new swapchain");
MILAI_LOG_DEBUG("Frame sync recreated for new swapchain");
return true;
}
void frame_sync::on_created() {
LOG_DEBUG("Frame sync created");
MILAI_LOG_DEBUG("Frame sync created");
}
void frame_sync::on_destroying() {
LOG_DEBUG("Frame sync destroying");
MILAI_LOG_DEBUG("Frame sync destroying");
}
bool frame_sync::create_sync_objects() {
@@ -315,45 +301,43 @@ bool frame_sync::create_sync_objects() {
frame_resources_.resize(frames_in_flight_);
VkSemaphoreCreateInfo semaphore_info{};
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
vk::SemaphoreCreateInfo semaphore_info{};
VkFenceCreateInfo fence_info{};
fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fence_info.flags = VK_FENCE_CREATE_SIGNALED_BIT; // 初始状态为已信号
vk::FenceCreateInfo fence_info{};
fence_info.flags = vk::FenceCreateFlagBits::eSignaled; // 初始状态为已信号
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));
auto image_sem_result = device_->get_device().createSemaphore(semaphore_info);
if (image_sem_result.result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to create image available semaphore: {}",
vk::to_string(image_sem_result.result));
return false;
}
resources.image_available_semaphore = image_sem_result.value;
// 创建渲染完成信号量
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));
auto render_sem_result = device_->get_device().createSemaphore(semaphore_info);
if (render_sem_result.result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to create render finished semaphore: {}",
vk::to_string(render_sem_result.result));
return false;
}
resources.render_finished_semaphore = render_sem_result.value;
// 创建飞行中栅栏
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));
auto fence_result = device_->get_device().createFence(fence_info);
if (fence_result.result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to create in flight fence: {}",
vk::to_string(fence_result.result));
return false;
}
resources.in_flight_fence = fence_result.value;
}
LOG_DEBUG("Created {} sets of sync objects", frames_in_flight_);
MILAI_LOG_DEBUG("Created {} sets of sync objects", frames_in_flight_);
return true;
}
@@ -363,38 +347,40 @@ bool frame_sync::create_command_buffers() {
}
// 创建命令池
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));
vk::CommandPoolCreateInfo pool_info{};
pool_info.flags = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;
if (device_->get_queue_family_indices().graphics_family.has_value()) {
pool_info.queueFamilyIndex = device_->get_queue_family_indices().graphics_family.value();
} else {
MILAI_LOG_ERROR("No graphics queue family found");
return false;
}
auto pool_result = device_->get_device().createCommandPool(pool_info);
if (pool_result.result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to create command pool: {}", vk::to_string(pool_result.result));
return false;
}
command_pool_ = pool_result.value;
// 分配命令缓冲
std::vector<VkCommandBuffer> buffers(frames_in_flight_);
VkCommandBufferAllocateInfo alloc_info{};
alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
vk::CommandBufferAllocateInfo alloc_info{};
alloc_info.commandPool = command_pool_;
alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
alloc_info.level = vk::CommandBufferLevel::ePrimary;
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));
auto alloc_result = device_->get_device().allocateCommandBuffers(alloc_info);
if (alloc_result.result != vk::Result::eSuccess) {
MILAI_LOG_ERROR("Failed to allocate command buffers: {}", vk::to_string(alloc_result.result));
return false;
}
auto buffers = alloc_result.value;
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_);
MILAI_LOG_DEBUG("Created command pool and {} command buffers", frames_in_flight_);
return true;
}
@@ -404,20 +390,17 @@ void frame_sync::destroy_sync_objects() {
}
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.image_available_semaphore) {
device_->get_device().destroySemaphore(resources.image_available_semaphore);
resources.image_available_semaphore = nullptr;
}
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.render_finished_semaphore) {
device_->get_device().destroySemaphore(resources.render_finished_semaphore);
resources.render_finished_semaphore = nullptr;
}
if (resources.in_flight_fence != VK_NULL_HANDLE) {
vkDestroyFence(device_->get_device(),
resources.in_flight_fence, nullptr);
resources.in_flight_fence = VK_NULL_HANDLE;
if (resources.in_flight_fence) {
device_->get_device().destroyFence(resources.in_flight_fence);
resources.in_flight_fence = nullptr;
}
}
}
@@ -428,13 +411,13 @@ void frame_sync::destroy_command_buffers() {
}
// 命令缓冲在命令池销毁时自动释放
if (command_pool_ != VK_NULL_HANDLE) {
vkDestroyCommandPool(device_->get_device(), command_pool_, nullptr);
command_pool_ = VK_NULL_HANDLE;
if (command_pool_) {
device_->get_device().destroyCommandPool(command_pool_);
command_pool_ = nullptr;
}
for (auto& resources : frame_resources_) {
resources.command_buffer = VK_NULL_HANDLE;
resources.command_buffer = nullptr;
}
}