Examples, Viewport: Vulkan: Experiment (broken) multi-viewport support, merging code from ParticlePeter branches. (#1542, #1042)

This commit is contained in:
omar 2018-03-12 18:43:25 +01:00
parent f6fc28dfd2
commit b88492746e
6 changed files with 244 additions and 112 deletions

View File

@ -452,6 +452,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
io.PlatformInterface.RenderViewport = ImGui_ImplGlfw_RenderViewport;
io.PlatformInterface.SwapBuffers = ImGui_ImplGlfw_SwapBuffers;
// We let the user set up the link to glfwCreateWindowSurface() here, so this binding can work with old GLFW and without Vulkan headers
io.PlatformInterface.CreateVkSurface = NULL;
// Register main window handle
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
ImGuiPlatformDataGlfw* data = IM_NEW(ImGuiPlatformDataGlfw)();

View File

@ -55,7 +55,7 @@ struct FrameDataForRender
VkBuffer IndexBuffer;
};
static int g_FrameIndex = 0;
static FrameDataForRender g_FramesDataBuffers[IMGUI_VK_QUEUED_FRAMES];
static FrameDataForRender g_FramesDataBuffers[IMGUI_VK_QUEUED_FRAMES] = {};
// Font data
static VkSampler g_FontSampler = VK_NULL_HANDLE;
@ -204,6 +204,7 @@ void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData*
return;
FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex];
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
// Create the Vertex and Index buffers:
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
@ -713,7 +714,10 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
ImGui_ImplVulkan_CreateDeviceObjects();
io.ConfigFlags |= ImGuiConfigFlags_RendererHasViewports;
if (io.ConfigFlags & ImGuiConfigFlags_EnableViewports)
{
IM_ASSERT(io.PlatformInterface.CreateVkSurface != NULL);
ImGui_ImplVulkan_InitPlatformInterface();
}
return true;
}
@ -728,12 +732,6 @@ void ImGui_ImplVulkan_NewFrame()
{
}
void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer)
{
ImGui_ImplVulkan_RenderDrawData(command_buffer, ImGui::GetDrawData());
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
}
//-------------------------------------------------------------------------
// Miscellaneous Vulkan Helpers
// (Those are currently not strictly needed by the binding, but will be once if we support multi-viewports)
@ -747,7 +745,7 @@ ImGui_ImplVulkan_FrameData::ImGui_ImplVulkan_FrameData()
CommandPool = VK_NULL_HANDLE;
CommandBuffer = VK_NULL_HANDLE;
Fence = VK_NULL_HANDLE;
PresentCompleteSemaphore = VK_NULL_HANDLE;
ImageAcquiredSemaphore = VK_NULL_HANDLE;
RenderCompleteSemaphore = VK_NULL_HANDLE;
}
@ -867,7 +865,7 @@ void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_
{
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
err = vkCreateSemaphore(device, &info, allocator, &fd->PresentCompleteSemaphore);
err = vkCreateSemaphore(device, &info, allocator, &fd->ImageAcquiredSemaphore);
check_vk_result(err);
err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore);
check_vk_result(err);
@ -875,8 +873,22 @@ void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_
}
}
int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode)
{
if (present_mode == VK_PRESENT_MODE_MAILBOX_KHR)
return 3;
if (present_mode == VK_PRESENT_MODE_FIFO_KHR || present_mode == VK_PRESENT_MODE_FIFO_RELAXED_KHR)
return 2;
if (present_mode == VK_PRESENT_MODE_IMMEDIATE_KHR)
return 1;
IM_ASSERT(0);
return 1;
}
void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h)
{
uint32_t min_image_count = 2; // FIXME: this should become a function parameter
VkResult err;
VkSwapchainKHR old_swapchain = wd->Swapchain;
err = vkDeviceWaitIdle(device);
@ -894,11 +906,16 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
if (wd->RenderPass)
vkDestroyRenderPass(device, wd->RenderPass, allocator);
// If min image count was not specified, request different count of images dependent on selected present mode
if (min_image_count == 0)
min_image_count = ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(wd->PresentMode);
// Create Swapchain
{
VkSwapchainCreateInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
info.surface = wd->Surface;
info.minImageCount = min_image_count;
info.imageFormat = wd->SurfaceFormat.format;
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
info.imageArrayLayers = 1;
@ -912,10 +929,10 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
VkSurfaceCapabilitiesKHR cap;
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
check_vk_result(err);
if (cap.maxImageCount > 0)
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
else
info.minImageCount = cap.minImageCount + 2;
if (info.minImageCount < cap.minImageCount)
info.minImageCount = cap.minImageCount;
else if (info.minImageCount > cap.maxImageCount)
info.minImageCount = cap.maxImageCount;
if (cap.currentExtent.width == 0xffffffff)
{
@ -1007,14 +1024,16 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator)
{
vkDeviceWaitIdle(device);
vkDeviceWaitIdle(device); // FIXME: We could wait on the Queue if we had the queue in wd-> (otherwise VulkanH functions can't use globals)
//vkQueueWaitIdle(g_Queue);
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
vkDestroyFence(device, fd->Fence, allocator);
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
vkDestroyCommandPool(device, fd->CommandPool, allocator);
vkDestroySemaphore(device, fd->PresentCompleteSemaphore, allocator);
vkDestroySemaphore(device, fd->ImageAcquiredSemaphore, allocator);
vkDestroySemaphore(device, fd->RenderCompleteSemaphore, allocator);
}
for (uint32_t i = 0; i < wd->BackBufferCount; i++)
@ -1046,19 +1065,41 @@ static void ImGui_ImplVulkan_CreateViewport(ImGuiViewport* viewport)
{
ImGuiPlatformDataVulkan* data = IM_NEW(ImGuiPlatformDataVulkan)();
viewport->RendererUserData = data;
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
// FIXME-PLATFORM
//HWND hwnd = (HWND)viewport->PlatformHandle;
//IM_ASSERT(hwnd != 0);
// Create surface
ImGuiIO& io = ImGui::GetIO();
VkResult err = (VkResult)io.PlatformInterface.CreateVkSurface(viewport->PlatformHandle, (ImU64)g_Instance, (const void*)g_Allocator, (ImU64*)&wd->Surface);
check_vk_result(err);
//...
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
exit(-1);
}
// Get Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Get Present Mode
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
// Create SwapChain, RenderPass, Framebuffer, etc.
ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, (int)viewport->Size.x, (int)viewport->Size.y);
}
static void ImGui_ImplVulkan_DestroyViewport(ImGuiViewport* viewport)
{
if (ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData)
{
//...
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, &data->WindowData, g_Allocator);
IM_DELETE(data);
}
viewport->RendererUserData = NULL;
@ -1067,32 +1108,107 @@ static void ImGui_ImplVulkan_DestroyViewport(ImGuiViewport* viewport)
static void ImGui_ImplVulkan_ResizeViewport(ImGuiViewport* viewport, ImVec2 size)
{
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
//...
(void)data;
(void)size;
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, (int)size.x, (int)size.y);
}
static void ImGui_ImplVulkan_RenderViewport(ImGuiViewport* viewport)
{
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
VkResult err;
ImVec4 clear_color = ImGui::GetStyle().Colors[ImGuiCol_WindowBg]; // FIXME-PLATFORM
clear_color.w = 1.0f;
(void)data;
// clear
// call ImGui_ImplVulkan_RenderDrawData(&viewport->DrawData)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
for (;;)
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, 100);
if (err == VK_SUCCESS) break;
if (err == VK_TIMEOUT) continue;
check_vk_result(err);
}
{
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, fd->ImageAcquiredSemaphore, VK_NULL_HANDLE, &fd->BackbufferIndex);
check_vk_result(err);
}
{
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
check_vk_result(err);
VkCommandBufferBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
check_vk_result(err);
}
{
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = wd->RenderPass;
info.framebuffer = wd->Framebuffer[fd->BackbufferIndex];
info.renderArea.extent.width = wd->Width;
info.renderArea.extent.height = wd->Height;
info.clearValueCount = 1;
info.pClearValues = &wd->ClearValue;
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
}
}
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
ImGui_ImplVulkan_RenderDrawData(wd->Frames[wd->FrameIndex].CommandBuffer, &viewport->DrawData);
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->ImageAcquiredSemaphore;
info.pWaitDstStageMask = &wait_stage;
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
err = vkEndCommandBuffer(fd->CommandBuffer);
check_vk_result(err);
err = vkResetFences(g_Device, 1, &fd->Fence);
check_vk_result(err);
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
check_vk_result(err);
}
}
}
static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport)
{
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
(void)data;
//...
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
VkResult err;
uint32_t PresentIndex = wd->FrameIndex;
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex];
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &fd->BackbufferIndex;
err = vkQueuePresentKHR(g_Queue, &info);
check_vk_result(err);
wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
}
void ImGui_ImplVulkan_InitPlatformInterface()
{
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.PlatformInterface.CreateVkSurface != NULL);
io.RendererInterface.CreateViewport = ImGui_ImplVulkan_CreateViewport;
io.RendererInterface.DestroyViewport = ImGui_ImplVulkan_DestroyViewport;
io.RendererInterface.ResizeViewport = ImGui_ImplVulkan_ResizeViewport;
@ -1102,6 +1218,7 @@ void ImGui_ImplVulkan_InitPlatformInterface()
void ImGui_ImplVulkan_ShutdownPlatformInterface()
{
ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext());
ImGuiIO& io = ImGui::GetIO();
memset(&io.RendererInterface, 0, sizeof(io.RendererInterface));
}

View File

@ -29,7 +29,6 @@ struct ImGui_ImplVulkan_InitInfo
IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
IMGUI_API void ImGui_ImplVulkan_Shutdown();
IMGUI_API void ImGui_ImplVulkan_NewFrame();
IMGUI_API void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer);
IMGUI_API void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data);
// Called by Init/NewFrame/Shutdown
@ -55,6 +54,7 @@ IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFr
IMGUI_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
IMGUI_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
IMGUI_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
struct ImGui_ImplVulkan_FrameData
{
@ -62,7 +62,7 @@ struct ImGui_ImplVulkan_FrameData
VkCommandPool CommandPool;
VkCommandBuffer CommandBuffer;
VkFence Fence;
VkSemaphore PresentCompleteSemaphore;
VkSemaphore ImageAcquiredSemaphore;
VkSemaphore RenderCompleteSemaphore;
IMGUI_API ImGui_ImplVulkan_FrameData();

View File

@ -479,7 +479,7 @@ int main(int, char**)
ImGui::Render();
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
FrameBegin(wd);
ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
ImGui_ImplVulkan_RenderDrawData(wd->Frames[wd->FrameIndex].CommandBuffer, ImGui::GetDrawData());
FrameEnd(wd);
ImGui::RenderAdditionalViewports();

View File

@ -224,83 +224,79 @@ static void CleanupVulkan()
vkDestroyInstance(g_Instance, g_Allocator);
}
static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
static void FrameRender(ImGui_ImplVulkan_WindowData* wd)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkResult err;
for (;;)
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, 100);
if (err == VK_SUCCESS) break;
if (err == VK_TIMEOUT) continue;
check_vk_result(err);
}
{
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, fd->PresentCompleteSemaphore, VK_NULL_HANDLE, &fd->BackbufferIndex);
check_vk_result(err);
}
{
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
check_vk_result(err);
VkCommandBufferBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
check_vk_result(err);
}
{
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = wd->RenderPass;
info.framebuffer = wd->Framebuffer[fd->BackbufferIndex];
info.renderArea.extent.width = wd->Width;
info.renderArea.extent.height = wd->Height;
info.clearValueCount = 1;
info.pClearValues = &wd->ClearValue;
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
}
}
VkResult err;
static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkResult err;
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->PresentCompleteSemaphore;
info.pWaitDstStageMask = &wait_stage;
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
check_vk_result(err);
err = vkEndCommandBuffer(fd->CommandBuffer);
check_vk_result(err);
err = vkResetFences(g_Device, 1, &fd->Fence);
check_vk_result(err);
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
check_vk_result(err);
}
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
{
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
check_vk_result(err);
err = vkResetFences(g_Device, 1, &fd->Fence);
check_vk_result(err);
}
{
err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
check_vk_result(err);
VkCommandBufferBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
check_vk_result(err);
}
{
VkRenderPassBeginInfo info = {};
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
info.renderPass = wd->RenderPass;
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
info.renderArea.extent.width = wd->Width;
info.renderArea.extent.height = wd->Height;
info.clearValueCount = 1;
info.pClearValues = &wd->ClearValue;
vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
}
// Record Imgui Draw Data and draw funcs into command buffer
ImGui_ImplVulkan_RenderDrawData(fd->CommandBuffer, ImGui::GetDrawData());
// Submit command buffer
vkCmdEndRenderPass(fd->CommandBuffer);
{
VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
VkSubmitInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &image_acquired_semaphore;
info.pWaitDstStageMask = &wait_stage;
info.commandBufferCount = 1;
info.pCommandBuffers = &fd->CommandBuffer;
info.signalSemaphoreCount = 1;
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
err = vkEndCommandBuffer(fd->CommandBuffer);
check_vk_result(err);
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
check_vk_result(err);
}
}
static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
{
VkResult err;
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &fd->BackbufferIndex;
err = vkQueuePresentKHR(g_Queue, &info);
check_vk_result(err);
VkPresentInfoKHR info = {};
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
info.waitSemaphoreCount = 1;
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
info.swapchainCount = 1;
info.pSwapchains = &wd->Swapchain;
info.pImageIndices = &wd->FrameIndex;
VkResult err = vkQueuePresentKHR(g_Queue, &info);
check_vk_result(err);
}
static void glfw_error_callback(int error, const char* description)
@ -312,12 +308,23 @@ static void glfw_resize_callback(GLFWwindow*, int w, int h)
{
g_ResizeWanted = true;
g_ResizeWidth = w;
g_ResizeHeight = h;
g_ResizeHeight = h;
}
static int glfw_create_vk_surface(void* platform_handle, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface)
{
GLFWwindow* window = (GLFWwindow*)platform_handle;
VkInstance instance = (VkInstance)vk_instance;
const VkAllocationCallbacks* allocator = (const VkAllocationCallbacks*)vk_allocator;
VkSurfaceKHR* surface = (VkSurfaceKHR*)out_vk_surface;
VkResult err = glfwCreateWindowSurface(instance, window, allocator, surface);
check_vk_result(err);
return (int)err;
}
int main(int, char**)
{
// Setup window
// Setup window
glfwSetErrorCallback(glfw_error_callback);
if (!glfwInit())
return 1;
@ -354,6 +361,10 @@ int main(int, char**)
io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
// Setup GLFW binding
ImGui_ImplGlfw_InitForVulkan(window, true);
io.PlatformInterface.CreateVkSurface = glfw_create_vk_surface;
// Setup Vulkan binding
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = g_Instance;
@ -365,7 +376,6 @@ int main(int, char**)
init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplGlfw_InitForVulkan(window, true);
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
// Setup style
@ -430,9 +440,12 @@ int main(int, char**)
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents();
if (g_ResizeWanted)
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight);
g_ResizeWanted = false;
if (g_ResizeWanted)
{
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight);
g_ResizeWanted = false;
}
ImGui_ImplVulkan_NewFrame();
ImGui_ImplGlfw_NewFrame();
@ -443,7 +456,7 @@ int main(int, char**)
static int counter = 0;
ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
ImGui::SliderFloat("float", &f, 0.0f, 1.0f); // Edit 1 float using a slider from 0.0f to 1.0f
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color (nb: you could use (float*)&wd->ClearValue instead)
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
ImGui::Checkbox("Another Window", &show_another_window);
@ -476,13 +489,9 @@ int main(int, char**)
// Rendering
ImGui::Render();
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
FrameBegin(wd);
ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
FrameEnd(wd);
FrameRender(wd);
ImGui::RenderAdditionalViewports();
FramePresent(wd);
wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
}
// Cleanup

View File

@ -966,6 +966,9 @@ struct ImGuiPlatformInterface
void (*RenderViewport)(ImGuiViewport* viewport);
void (*SwapBuffers)(ImGuiViewport* viewport);
// FIXME-VIEWPORT: Experimenting with back-end abstraction. This probably shouldn't stay as is.
int (*CreateVkSurface)(void* platform_handle, ImU64 vk_instance, const void* vk_allocator, ImU64* out_vk_surface);
// FIXME-DPI
float (*GetWindowDpiScale)(ImGuiViewport* viewport); // (Optional)
void (*ChangedViewport)(ImGuiViewport* viewport); // (Optional) Called during Begin() every time the viewport we are outputting into changes (viewport = next viewport)