Skip to content

Commit

Permalink
Merge branch 'feature/vk_re_create_pipeline_2' into feature/docking_v…
Browse files Browse the repository at this point in the history
…k_re_create_pipeline_2
  • Loading branch information
SuperRonan committed Oct 29, 2024
1 parent 646df39 commit 7a50853
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 24 deletions.
133 changes: 116 additions & 17 deletions backends/imgui_impl_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -887,10 +887,21 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAlloca
}
}

static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
struct ImGui_ImplVulkan_PipelineCreateInfo
{
VkDevice Device = VK_NULL_HANDLE;
const VkAllocationCallbacks* Allocator = nullptr;
VkPipelineCache PipelineCache = VK_NULL_HANDLE;
VkRenderPass RenderPass = VK_NULL_HANDLE;
uint32_t Subpass = 0;
VkSampleCountFlagBits MSAASamples = {};
const ImGui_ImplVulkan_PipelineRenderingInfo* pRenderingInfo = nullptr;
};

static VkPipeline ImGui_ImplVulkan_CreatePipeline(ImGui_ImplVulkan_PipelineCreateInfo const& pci)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_CreateShaderModules(device, allocator);
ImGui_ImplVulkan_CreateShaderModules(pci.Device, pci.Allocator);

VkPipelineShaderStageCreateInfo stage[2] = {};
stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
Expand Down Expand Up @@ -945,7 +956,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC

VkPipelineMultisampleStateCreateInfo ms_info = {};
ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT;
ms_info.rasterizationSamples = (pci.MSAASamples != 0) ? pci.MSAASamples : VK_SAMPLE_COUNT_1_BIT;

VkPipelineColorBlendAttachmentState color_attachment[1] = {};
color_attachment[0].blendEnable = VK_TRUE;
Expand Down Expand Up @@ -985,21 +996,22 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
info.pColorBlendState = &blend_info;
info.pDynamicState = &dynamic_state;
info.layout = bd->PipelineLayout;
info.renderPass = renderPass;
info.subpass = subpass;
info.renderPass = pci.RenderPass;
info.subpass = pci.Subpass;

#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (bd->VulkanInitInfo.UseDynamicRendering)
{
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
IM_ASSERT(bd->VulkanInitInfo.PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo pNext must be NULL");
info.pNext = &bd->VulkanInitInfo.PipelineRenderingCreateInfo;
info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr.
IM_ASSERT(pci.pRenderingInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR");
IM_ASSERT(pci.pRenderingInfo->pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be NULL");
info.pNext = pci.pRenderingInfo;
}
#endif

VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
VkPipeline res;
VkResult err = vkCreateGraphicsPipelines(pci.Device, pci.PipelineCache, 1, &info, pci.Allocator, &res);
check_vk_result(err);
return res;
}

bool ImGui_ImplVulkan_CreateDeviceObjects()
Expand Down Expand Up @@ -1058,11 +1070,43 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
check_vk_result(err);
}

ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, &bd->Pipeline, v->Subpass);

return true;
}

void ImGui_ImplVulkan_ReCreateMainPipeline(ImGui_ImplVulkan_MainPipelineCreateInfo const& info)
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (bd->Pipeline)
{
vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator);
bd->Pipeline = VK_NULL_HANDLE;
}
v->RenderPass = info.RenderPass;
v->MSAASamples = info.MSAASamples;
v->Subpass = info.Subpass;

#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (info.pDynamicRendering)
{
v->PipelineRenderingCreateInfo = *info.pDynamicRendering;
}
#else
IM_ASSERT(p_dynamic_rendering == nullptr);
#endif

ImGui_ImplVulkan_PipelineCreateInfo pci;
pci.Device = v->Device;
pci.Allocator = v->Allocator;
pci.PipelineCache = v->PipelineCache;
pci.RenderPass = v->RenderPass;
pci.Subpass = v->Subpass;
pci.MSAASamples = v->MSAASamples;
pci.pRenderingInfo = info.pDynamicRendering;

bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(pci);
}

void ImGui_ImplVulkan_DestroyDeviceObjects()
{
ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
Expand Down Expand Up @@ -1145,10 +1189,11 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE);
IM_ASSERT(info->MinImageCount >= 2);
IM_ASSERT(info->ImageCount >= info->MinImageCount);
if (info->UseDynamicRendering == false)
IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);
//if (info->UseDynamicRendering == false)
// IM_ASSERT(info->RenderPass != VK_NULL_HANDLE);

bd->VulkanInitInfo = *info;
ImGui_ImplVulkan_InitInfo * v = &bd->VulkanInitInfo;
*v = *info;

ImGui_ImplVulkan_CreateDeviceObjects();

Expand All @@ -1158,6 +1203,35 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)

ImGui_ImplVulkan_InitMultiViewportSupport();

{
bool create_pipeline = false;
const ImGui_ImplVulkan_PipelineRenderingInfo * p_dynamic_rendering = nullptr;
if (v->RenderPass)
{
create_pipeline = true;
}
else
{
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
if (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR)
{
p_dynamic_rendering = &v->PipelineRenderingCreateInfo;
create_pipeline = true;
}
#endif
}
if (create_pipeline)
{
ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {};
mp_info.RenderPass = v->RenderPass;
mp_info.Subpass = v->Subpass;
mp_info.MSAASamples = info->MSAASamples;
mp_info.pDynamicRendering = p_dynamic_rendering;

ImGui_ImplVulkan_ReCreateMainPipeline(mp_info);
}
}

return true;
}

Expand Down Expand Up @@ -1699,8 +1773,33 @@ static void ImGui_ImplVulkan_CreateWindow(ImGuiViewport* viewport)
vd->WindowOwned = true;

// Create pipeline (shared by all secondary viewports)
if (bd->PipelineForViewports == VK_NULL_HANDLE)
ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &bd->PipelineForViewports, 0);
if (bd->PipelineForViewports == VK_NULL_HANDLE)
{
ImGui_ImplVulkan_PipelineCreateInfo pci;
pci.Device = v->Device;
pci.Allocator = v->Allocator;
pci.PipelineCache = VK_NULL_HANDLE;
pci.RenderPass = wd->RenderPass;
pci.Subpass = 0;
pci.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
VkPipelineRenderingCreateInfoKHR rendering_info = {};
if (wd->UseDynamicRendering)
{
rendering_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO;
rendering_info.pNext = nullptr;
rendering_info.viewMask = 0;
rendering_info.colorAttachmentCount = 1;
rendering_info.pColorAttachmentFormats = &wd->SurfaceFormat.format;
rendering_info.depthAttachmentFormat = VK_FORMAT_UNDEFINED;
rendering_info.stencilAttachmentFormat = VK_FORMAT_UNDEFINED;
pci.RenderPass = VK_NULL_HANDLE;
pci.pRenderingInfo = &rendering_info;
}
#endif
bd->PipelineForViewports = ImGui_ImplVulkan_CreatePipeline(pci);

}
}

static void ImGui_ImplVulkan_DestroyWindow(ImGuiViewport* viewport)
Expand Down
29 changes: 22 additions & 7 deletions backends/imgui_impl_vulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@
#define IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
#endif

#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
typedef VkPipelineRenderingCreateInfoKHR ImGui_ImplVulkan_PipelineRenderingInfo;
#else
typedef void ImGui_ImplVulkan_PipelineRenderingInfo;
#endif

// Initialization data, for ImGui_ImplVulkan_Init()
// - VkDescriptorPool should be created with VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
// and must contain a pool size large enough to hold an ImGui VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER descriptor.
Expand Down Expand Up @@ -98,13 +104,22 @@ struct ImGui_ImplVulkan_InitInfo
};

// Follow "Getting Started" link and check examples/ folder to learn about using backends!
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info);
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture();
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontsTexture();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); // The main pipeline will be created if possible (RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType is correct))
#define IMGUI_IMPL_VULKAN_HAS_MAIN_PIPELINE_RE_CREATION 1
struct ImGui_ImplVulkan_MainPipelineCreateInfo
{
VkRenderPass RenderPass = VK_NULL_HANDLE;
uint32_t Subpass = 0;
VkSampleCountFlagBits MSAASamples = {};
const ImGui_ImplVulkan_PipelineRenderingInfo* pDynamicRendering = nullptr;
};
IMGUI_IMPL_API void ImGui_ImplVulkan_ReCreateMainPipeline(ImGui_ImplVulkan_MainPipelineCreateInfo const& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))
IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE);
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture();
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontsTexture();
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)

// Register a texture (VkDescriptorSet == ImTextureID)
// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem
Expand Down

0 comments on commit 7a50853

Please sign in to comment.