添加windows构建适配,禁用ImGui多视口功能
This commit is contained in:
+154
-154
@@ -1,154 +1,154 @@
|
||||
//
|
||||
// Created by atdunbg on 2026/9/22.
|
||||
//
|
||||
|
||||
#include <Engine/ImGui/ImGuiLayer.h>
|
||||
#include <Engine/Core/Window.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Renderer/Renderer.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <backends/imgui_impl_glfw.h>
|
||||
#include <backends/imgui_impl_vulkan.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
namespace {
|
||||
void CheckVkResult(VkResult err)
|
||||
{
|
||||
if (err != VK_SUCCESS) {
|
||||
ENGINE_ERROR("ImGui Vulkan backend error: VkResult={}", static_cast<int>(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiLayer::ImGuiLayer(Window& window, Renderer& renderer)
|
||||
: m_Device(renderer.GetDevice())
|
||||
{
|
||||
Device& device = renderer.GetDevice();
|
||||
|
||||
// 1. 描述符池(ImGui 自用:字体贴图 + 用户贴图)
|
||||
std::array<vk::DescriptorPoolSize, 11> poolSizes = {{
|
||||
{ vk::DescriptorType::eSampler, 1000 },
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 1000 },
|
||||
{ vk::DescriptorType::eSampledImage, 1000 },
|
||||
{ vk::DescriptorType::eStorageImage, 1000 },
|
||||
{ vk::DescriptorType::eUniformTexelBuffer, 1000 },
|
||||
{ vk::DescriptorType::eStorageTexelBuffer, 1000 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 1000 },
|
||||
{ vk::DescriptorType::eStorageBuffer, 1000 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 1000 },
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 1000 },
|
||||
{ vk::DescriptorType::eInputAttachment, 1000 },
|
||||
}};
|
||||
vk::DescriptorPoolCreateInfo poolInfo;
|
||||
poolInfo.setFlags(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet)
|
||||
.setMaxSets(1000)
|
||||
.setPoolSizes(poolSizes);
|
||||
m_Pool = device.GetDevice().createDescriptorPool(poolInfo);
|
||||
|
||||
// 2. ImGui 上下文 + 平台/渲染后端
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark(); // 深色主题(ImGui 默认是灰白 Classic)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // docking 分支
|
||||
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // 多视口
|
||||
|
||||
ImGui_ImplGlfw_InitForVulkan(window.GetHandle(), true);
|
||||
|
||||
ImGui_ImplVulkan_InitInfo info = {};
|
||||
info.ApiVersion = VK_API_VERSION_1_4;
|
||||
info.Instance = device.GetInstance();
|
||||
info.PhysicalDevice = device.GetPhysicalDevice();
|
||||
info.Device = device.GetDevice();
|
||||
info.QueueFamily = device.GetGraphicsFamily();
|
||||
info.Queue = device.GetGraphicsQueue();
|
||||
info.DescriptorPool = m_Pool;
|
||||
info.MinImageCount = 2; // kMaxFramesInFlight
|
||||
info.ImageCount = renderer.GetSwapchainImageCount();
|
||||
info.CheckVkResultFn = CheckVkResult;
|
||||
|
||||
// 与引擎共存的关键:不用 RenderPass,走 dynamic rendering,
|
||||
// 颜色格式 = swapchain 格式(引擎无 vk::Pipeline,全动态状态)
|
||||
info.UseDynamicRendering = true;
|
||||
const vk::Format colorFormat = renderer.GetSwapchainFormat();
|
||||
|
||||
VkPipelineRenderingCreateInfoKHR pri{};
|
||||
pri.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR;
|
||||
pri.colorAttachmentCount = 1;
|
||||
pri.pColorAttachmentFormats =
|
||||
reinterpret_cast<const VkFormat*>(&colorFormat);
|
||||
info.PipelineInfoMain.PipelineRenderingCreateInfo = pri;
|
||||
// 多视口子窗口同格式
|
||||
info.PipelineInfoForViewports.PipelineRenderingCreateInfo = pri;
|
||||
|
||||
ImGui_ImplVulkan_Init(&info);
|
||||
|
||||
ENGINE_INFO("ImGuiLayer initialized (docking + viewports, dynamic rendering)");
|
||||
}
|
||||
|
||||
ImGuiLayer::~ImGuiLayer()
|
||||
{
|
||||
// 后端销毁自己的管线/字体资源前先等 GPU 空闲(层先于 Renderer 析构)
|
||||
m_Device.GetDevice().waitIdle();
|
||||
|
||||
// 场景纹理描述符先归还(后端 shutdown 前必须完成)
|
||||
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
|
||||
UpdateSceneTexture(slot, vk::ImageView{});
|
||||
}
|
||||
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
m_Device.GetDevice().destroyDescriptorPool(m_Pool);
|
||||
|
||||
ENGINE_INFO("ImGuiLayer shut down");
|
||||
}
|
||||
|
||||
void ImGuiLayer::UpdateSceneTexture(u32 slot, vk::ImageView view)
|
||||
{
|
||||
if (slot >= kMaxFramesInFlight) return;
|
||||
|
||||
// 旧描述符先归还(池带 eFreeDescriptorSet;resize 重建时 GPU 已
|
||||
// waitIdle,无在飞引用)
|
||||
if (m_SceneTextures[slot]) {
|
||||
ImGui_ImplVulkan_RemoveTexture(
|
||||
(VkDescriptorSet)(intptr_t)m_SceneTextures[slot]);
|
||||
m_SceneTextures[slot] = ImTextureID_Invalid;
|
||||
}
|
||||
if (view) {
|
||||
// 后端自有采样器(linear):只需提供 view 与采样期 layout——
|
||||
// RG 已保证 ImGuiPass 执行期处于 eShaderReadOnlyOptimal
|
||||
m_SceneTextures[slot] = (ImTextureID)(intptr_t)
|
||||
ImGui_ImplVulkan_AddTexture(
|
||||
(VkImageView)view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiLayer::NewFrame()
|
||||
{
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void ImGuiLayer::BuildDrawData()
|
||||
{
|
||||
ImGui::Render();
|
||||
}
|
||||
|
||||
void ImGuiLayer::RenderDrawData(vk::CommandBuffer cmd)
|
||||
{
|
||||
if (!m_Enabled) return;
|
||||
|
||||
ImDrawData* drawData = ImGui::GetDrawData();
|
||||
if (drawData && drawData->CmdListsCount > 0) {
|
||||
ImGui_ImplVulkan_RenderDrawData(drawData, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Engine
|
||||
//
|
||||
// Created by atdunbg on 2026/9/22.
|
||||
//
|
||||
|
||||
#include <Engine/ImGui/ImGuiLayer.h>
|
||||
#include <Engine/Core/Window.h>
|
||||
#include <Engine/Core/Log.h>
|
||||
#include <Engine/Vulkan/Device.h>
|
||||
#include <Engine/Renderer/Renderer.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <backends/imgui_impl_glfw.h>
|
||||
#include <backends/imgui_impl_vulkan.h>
|
||||
|
||||
namespace Engine {
|
||||
|
||||
namespace {
|
||||
void CheckVkResult(VkResult err)
|
||||
{
|
||||
if (err != VK_SUCCESS) {
|
||||
ENGINE_ERROR("ImGui Vulkan backend error: VkResult={}", static_cast<int>(err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGuiLayer::ImGuiLayer(Window& window, Renderer& renderer)
|
||||
: m_Device(renderer.GetDevice())
|
||||
{
|
||||
Device& device = renderer.GetDevice();
|
||||
|
||||
// 1. 描述符池(ImGui 自用:字体贴图 + 用户贴图)
|
||||
std::array<vk::DescriptorPoolSize, 11> poolSizes = {{
|
||||
{ vk::DescriptorType::eSampler, 1000 },
|
||||
{ vk::DescriptorType::eCombinedImageSampler, 1000 },
|
||||
{ vk::DescriptorType::eSampledImage, 1000 },
|
||||
{ vk::DescriptorType::eStorageImage, 1000 },
|
||||
{ vk::DescriptorType::eUniformTexelBuffer, 1000 },
|
||||
{ vk::DescriptorType::eStorageTexelBuffer, 1000 },
|
||||
{ vk::DescriptorType::eUniformBuffer, 1000 },
|
||||
{ vk::DescriptorType::eStorageBuffer, 1000 },
|
||||
{ vk::DescriptorType::eUniformBufferDynamic, 1000 },
|
||||
{ vk::DescriptorType::eStorageBufferDynamic, 1000 },
|
||||
{ vk::DescriptorType::eInputAttachment, 1000 },
|
||||
}};
|
||||
vk::DescriptorPoolCreateInfo poolInfo;
|
||||
poolInfo.setFlags(vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet)
|
||||
.setMaxSets(1000)
|
||||
.setPoolSizes(poolSizes);
|
||||
m_Pool = device.GetDevice().createDescriptorPool(poolInfo);
|
||||
|
||||
// 2. ImGui 上下文 + 平台/渲染后端
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGui::StyleColorsDark(); // 深色主题(ImGui 默认是灰白 Classic)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // docking 分支
|
||||
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // 多视口
|
||||
|
||||
ImGui_ImplGlfw_InitForVulkan(window.GetHandle(), true);
|
||||
|
||||
ImGui_ImplVulkan_InitInfo info = {};
|
||||
info.ApiVersion = VK_API_VERSION_1_4;
|
||||
info.Instance = device.GetInstance();
|
||||
info.PhysicalDevice = device.GetPhysicalDevice();
|
||||
info.Device = device.GetDevice();
|
||||
info.QueueFamily = device.GetGraphicsFamily();
|
||||
info.Queue = device.GetGraphicsQueue();
|
||||
info.DescriptorPool = m_Pool;
|
||||
info.MinImageCount = 2; // kMaxFramesInFlight
|
||||
info.ImageCount = renderer.GetSwapchainImageCount();
|
||||
info.CheckVkResultFn = CheckVkResult;
|
||||
|
||||
// 与引擎共存的关键:不用 RenderPass,走 dynamic rendering,
|
||||
// 颜色格式 = swapchain 格式(引擎无 vk::Pipeline,全动态状态)
|
||||
info.UseDynamicRendering = true;
|
||||
const vk::Format colorFormat = renderer.GetSwapchainFormat();
|
||||
|
||||
VkPipelineRenderingCreateInfoKHR pri{};
|
||||
pri.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR;
|
||||
pri.colorAttachmentCount = 1;
|
||||
pri.pColorAttachmentFormats =
|
||||
reinterpret_cast<const VkFormat*>(&colorFormat);
|
||||
info.PipelineInfoMain.PipelineRenderingCreateInfo = pri;
|
||||
// 多视口子窗口同格式
|
||||
info.PipelineInfoForViewports.PipelineRenderingCreateInfo = pri;
|
||||
|
||||
ImGui_ImplVulkan_Init(&info);
|
||||
|
||||
ENGINE_INFO("ImGuiLayer initialized (docking + viewports, dynamic rendering)");
|
||||
}
|
||||
|
||||
ImGuiLayer::~ImGuiLayer()
|
||||
{
|
||||
// 后端销毁自己的管线/字体资源前先等 GPU 空闲(层先于 Renderer 析构)
|
||||
m_Device.GetDevice().waitIdle();
|
||||
|
||||
// 场景纹理描述符先归还(后端 shutdown 前必须完成)
|
||||
for (u32 slot = 0; slot < kMaxFramesInFlight; ++slot) {
|
||||
UpdateSceneTexture(slot, vk::ImageView{});
|
||||
}
|
||||
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
m_Device.GetDevice().destroyDescriptorPool(m_Pool);
|
||||
|
||||
ENGINE_INFO("ImGuiLayer shut down");
|
||||
}
|
||||
|
||||
void ImGuiLayer::UpdateSceneTexture(u32 slot, vk::ImageView view)
|
||||
{
|
||||
if (slot >= kMaxFramesInFlight) return;
|
||||
|
||||
// 旧描述符先归还(池带 eFreeDescriptorSet;resize 重建时 GPU 已
|
||||
// waitIdle,无在飞引用)
|
||||
if (m_SceneTextures[slot]) {
|
||||
ImGui_ImplVulkan_RemoveTexture(
|
||||
(VkDescriptorSet)(intptr_t)m_SceneTextures[slot]);
|
||||
m_SceneTextures[slot] = ImTextureID_Invalid;
|
||||
}
|
||||
if (view) {
|
||||
// 后端自有采样器(linear):只需提供 view 与采样期 layout——
|
||||
// RG 已保证 ImGuiPass 执行期处于 eShaderReadOnlyOptimal
|
||||
m_SceneTextures[slot] = (ImTextureID)(intptr_t)
|
||||
ImGui_ImplVulkan_AddTexture(
|
||||
(VkImageView)view, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiLayer::NewFrame()
|
||||
{
|
||||
ImGui_ImplVulkan_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void ImGuiLayer::BuildDrawData()
|
||||
{
|
||||
ImGui::Render();
|
||||
}
|
||||
|
||||
void ImGuiLayer::RenderDrawData(vk::CommandBuffer cmd)
|
||||
{
|
||||
if (!m_Enabled) return;
|
||||
|
||||
ImDrawData* drawData = ImGui::GetDrawData();
|
||||
if (drawData && drawData->CmdListsCount > 0) {
|
||||
ImGui_ImplVulkan_RenderDrawData(drawData, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Engine
|
||||
|
||||
Reference in New Issue
Block a user