mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-19 06:26:35 +00:00
Examples, Viewport: Vulkan: Experiment (broken) multi-viewport support, merging code from ParticlePeter branches. (#1542, #1042)
This commit is contained in:
parent
f6fc28dfd2
commit
b88492746e
@ -452,6 +452,9 @@ static void ImGui_ImplGlfw_InitPlatformInterface()
|
|||||||
io.PlatformInterface.RenderViewport = ImGui_ImplGlfw_RenderViewport;
|
io.PlatformInterface.RenderViewport = ImGui_ImplGlfw_RenderViewport;
|
||||||
io.PlatformInterface.SwapBuffers = ImGui_ImplGlfw_SwapBuffers;
|
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
|
// Register main window handle
|
||||||
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
ImGuiViewport* main_viewport = ImGui::GetMainViewport();
|
||||||
ImGuiPlatformDataGlfw* data = IM_NEW(ImGuiPlatformDataGlfw)();
|
ImGuiPlatformDataGlfw* data = IM_NEW(ImGuiPlatformDataGlfw)();
|
||||||
|
@ -55,7 +55,7 @@ struct FrameDataForRender
|
|||||||
VkBuffer IndexBuffer;
|
VkBuffer IndexBuffer;
|
||||||
};
|
};
|
||||||
static int g_FrameIndex = 0;
|
static int g_FrameIndex = 0;
|
||||||
static FrameDataForRender g_FramesDataBuffers[IMGUI_VK_QUEUED_FRAMES];
|
static FrameDataForRender g_FramesDataBuffers[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||||
|
|
||||||
// Font data
|
// Font data
|
||||||
static VkSampler g_FontSampler = VK_NULL_HANDLE;
|
static VkSampler g_FontSampler = VK_NULL_HANDLE;
|
||||||
@ -204,6 +204,7 @@ void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData*
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex];
|
FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex];
|
||||||
|
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
|
||||||
|
|
||||||
// Create the Vertex and Index buffers:
|
// Create the Vertex and Index buffers:
|
||||||
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
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();
|
ImGui_ImplVulkan_CreateDeviceObjects();
|
||||||
io.ConfigFlags |= ImGuiConfigFlags_RendererHasViewports;
|
io.ConfigFlags |= ImGuiConfigFlags_RendererHasViewports;
|
||||||
if (io.ConfigFlags & ImGuiConfigFlags_EnableViewports)
|
if (io.ConfigFlags & ImGuiConfigFlags_EnableViewports)
|
||||||
|
{
|
||||||
|
IM_ASSERT(io.PlatformInterface.CreateVkSurface != NULL);
|
||||||
ImGui_ImplVulkan_InitPlatformInterface();
|
ImGui_ImplVulkan_InitPlatformInterface();
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
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
|
// Miscellaneous Vulkan Helpers
|
||||||
// (Those are currently not strictly needed by the binding, but will be once if we support multi-viewports)
|
// (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;
|
CommandPool = VK_NULL_HANDLE;
|
||||||
CommandBuffer = VK_NULL_HANDLE;
|
CommandBuffer = VK_NULL_HANDLE;
|
||||||
Fence = VK_NULL_HANDLE;
|
Fence = VK_NULL_HANDLE;
|
||||||
PresentCompleteSemaphore = VK_NULL_HANDLE;
|
ImageAcquiredSemaphore = VK_NULL_HANDLE;
|
||||||
RenderCompleteSemaphore = VK_NULL_HANDLE;
|
RenderCompleteSemaphore = VK_NULL_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,7 +865,7 @@ void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_
|
|||||||
{
|
{
|
||||||
VkSemaphoreCreateInfo info = {};
|
VkSemaphoreCreateInfo info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_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);
|
check_vk_result(err);
|
||||||
err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore);
|
err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore);
|
||||||
check_vk_result(err);
|
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)
|
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;
|
VkResult err;
|
||||||
VkSwapchainKHR old_swapchain = wd->Swapchain;
|
VkSwapchainKHR old_swapchain = wd->Swapchain;
|
||||||
err = vkDeviceWaitIdle(device);
|
err = vkDeviceWaitIdle(device);
|
||||||
@ -894,11 +906,16 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
|
|||||||
if (wd->RenderPass)
|
if (wd->RenderPass)
|
||||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
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
|
// Create Swapchain
|
||||||
{
|
{
|
||||||
VkSwapchainCreateInfoKHR info = {};
|
VkSwapchainCreateInfoKHR info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
info.surface = wd->Surface;
|
info.surface = wd->Surface;
|
||||||
|
info.minImageCount = min_image_count;
|
||||||
info.imageFormat = wd->SurfaceFormat.format;
|
info.imageFormat = wd->SurfaceFormat.format;
|
||||||
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
|
info.imageColorSpace = wd->SurfaceFormat.colorSpace;
|
||||||
info.imageArrayLayers = 1;
|
info.imageArrayLayers = 1;
|
||||||
@ -912,10 +929,10 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
|
|||||||
VkSurfaceCapabilitiesKHR cap;
|
VkSurfaceCapabilitiesKHR cap;
|
||||||
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
|
err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, wd->Surface, &cap);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
if (cap.maxImageCount > 0)
|
if (info.minImageCount < cap.minImageCount)
|
||||||
info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount;
|
info.minImageCount = cap.minImageCount;
|
||||||
else
|
else if (info.minImageCount > cap.maxImageCount)
|
||||||
info.minImageCount = cap.minImageCount + 2;
|
info.minImageCount = cap.maxImageCount;
|
||||||
|
|
||||||
if (cap.currentExtent.width == 0xffffffff)
|
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)
|
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++)
|
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
|
||||||
{
|
{
|
||||||
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
|
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
|
||||||
vkDestroyFence(device, fd->Fence, allocator);
|
vkDestroyFence(device, fd->Fence, allocator);
|
||||||
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
|
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
|
||||||
vkDestroyCommandPool(device, fd->CommandPool, allocator);
|
vkDestroyCommandPool(device, fd->CommandPool, allocator);
|
||||||
vkDestroySemaphore(device, fd->PresentCompleteSemaphore, allocator);
|
vkDestroySemaphore(device, fd->ImageAcquiredSemaphore, allocator);
|
||||||
vkDestroySemaphore(device, fd->RenderCompleteSemaphore, allocator);
|
vkDestroySemaphore(device, fd->RenderCompleteSemaphore, allocator);
|
||||||
}
|
}
|
||||||
for (uint32_t i = 0; i < wd->BackBufferCount; i++)
|
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)();
|
ImGuiPlatformDataVulkan* data = IM_NEW(ImGuiPlatformDataVulkan)();
|
||||||
viewport->RendererUserData = data;
|
viewport->RendererUserData = data;
|
||||||
|
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
|
||||||
|
|
||||||
// FIXME-PLATFORM
|
// Create surface
|
||||||
//HWND hwnd = (HWND)viewport->PlatformHandle;
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
//IM_ASSERT(hwnd != 0);
|
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)
|
static void ImGui_ImplVulkan_DestroyViewport(ImGuiViewport* viewport)
|
||||||
{
|
{
|
||||||
if (ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData)
|
if (ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData)
|
||||||
{
|
{
|
||||||
//...
|
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, &data->WindowData, g_Allocator);
|
||||||
IM_DELETE(data);
|
IM_DELETE(data);
|
||||||
}
|
}
|
||||||
viewport->RendererUserData = NULL;
|
viewport->RendererUserData = NULL;
|
||||||
@ -1067,32 +1108,107 @@ static void ImGui_ImplVulkan_DestroyViewport(ImGuiViewport* viewport)
|
|||||||
static void ImGui_ImplVulkan_ResizeViewport(ImGuiViewport* viewport, ImVec2 size)
|
static void ImGui_ImplVulkan_ResizeViewport(ImGuiViewport* viewport, ImVec2 size)
|
||||||
{
|
{
|
||||||
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
|
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
|
||||||
//...
|
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
|
||||||
(void)data;
|
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, (int)size.x, (int)size.y);
|
||||||
(void)size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGui_ImplVulkan_RenderViewport(ImGuiViewport* viewport)
|
static void ImGui_ImplVulkan_RenderViewport(ImGuiViewport* viewport)
|
||||||
{
|
{
|
||||||
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
|
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
|
||||||
|
ImGui_ImplVulkan_WindowData* wd = &data->WindowData;
|
||||||
|
VkResult err;
|
||||||
|
|
||||||
ImVec4 clear_color = ImGui::GetStyle().Colors[ImGuiCol_WindowBg]; // FIXME-PLATFORM
|
ImVec4 clear_color = ImGui::GetStyle().Colors[ImGuiCol_WindowBg]; // FIXME-PLATFORM
|
||||||
clear_color.w = 1.0f;
|
clear_color.w = 1.0f;
|
||||||
|
|
||||||
(void)data;
|
{
|
||||||
// clear
|
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
// call ImGui_ImplVulkan_RenderDrawData(&viewport->DrawData)
|
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)
|
static void ImGui_ImplVulkan_SwapBuffers(ImGuiViewport* viewport)
|
||||||
{
|
{
|
||||||
ImGuiPlatformDataVulkan* data = (ImGuiPlatformDataVulkan*)viewport->RendererUserData;
|
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()
|
void ImGui_ImplVulkan_InitPlatformInterface()
|
||||||
{
|
{
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
|
IM_ASSERT(io.PlatformInterface.CreateVkSurface != NULL);
|
||||||
io.RendererInterface.CreateViewport = ImGui_ImplVulkan_CreateViewport;
|
io.RendererInterface.CreateViewport = ImGui_ImplVulkan_CreateViewport;
|
||||||
io.RendererInterface.DestroyViewport = ImGui_ImplVulkan_DestroyViewport;
|
io.RendererInterface.DestroyViewport = ImGui_ImplVulkan_DestroyViewport;
|
||||||
io.RendererInterface.ResizeViewport = ImGui_ImplVulkan_ResizeViewport;
|
io.RendererInterface.ResizeViewport = ImGui_ImplVulkan_ResizeViewport;
|
||||||
@ -1102,6 +1218,7 @@ void ImGui_ImplVulkan_InitPlatformInterface()
|
|||||||
|
|
||||||
void ImGui_ImplVulkan_ShutdownPlatformInterface()
|
void ImGui_ImplVulkan_ShutdownPlatformInterface()
|
||||||
{
|
{
|
||||||
|
ImGui::DestroyViewportsRendererData(ImGui::GetCurrentContext());
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
memset(&io.RendererInterface, 0, sizeof(io.RendererInterface));
|
memset(&io.RendererInterface, 0, sizeof(io.RendererInterface));
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ struct ImGui_ImplVulkan_InitInfo
|
|||||||
IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
|
IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass);
|
||||||
IMGUI_API void ImGui_ImplVulkan_Shutdown();
|
IMGUI_API void ImGui_ImplVulkan_Shutdown();
|
||||||
IMGUI_API void ImGui_ImplVulkan_NewFrame();
|
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);
|
IMGUI_API void ImGui_ImplVulkan_RenderDrawData(VkCommandBuffer command_buffer, ImDrawData* draw_data);
|
||||||
|
|
||||||
// Called by Init/NewFrame/Shutdown
|
// 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 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 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 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
|
struct ImGui_ImplVulkan_FrameData
|
||||||
{
|
{
|
||||||
@ -62,7 +62,7 @@ struct ImGui_ImplVulkan_FrameData
|
|||||||
VkCommandPool CommandPool;
|
VkCommandPool CommandPool;
|
||||||
VkCommandBuffer CommandBuffer;
|
VkCommandBuffer CommandBuffer;
|
||||||
VkFence Fence;
|
VkFence Fence;
|
||||||
VkSemaphore PresentCompleteSemaphore;
|
VkSemaphore ImageAcquiredSemaphore;
|
||||||
VkSemaphore RenderCompleteSemaphore;
|
VkSemaphore RenderCompleteSemaphore;
|
||||||
|
|
||||||
IMGUI_API ImGui_ImplVulkan_FrameData();
|
IMGUI_API ImGui_ImplVulkan_FrameData();
|
||||||
|
@ -479,7 +479,7 @@ int main(int, char**)
|
|||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
||||||
FrameBegin(wd);
|
FrameBegin(wd);
|
||||||
ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
|
ImGui_ImplVulkan_RenderDrawData(wd->Frames[wd->FrameIndex].CommandBuffer, ImGui::GetDrawData());
|
||||||
FrameEnd(wd);
|
FrameEnd(wd);
|
||||||
|
|
||||||
ImGui::RenderAdditionalViewports();
|
ImGui::RenderAdditionalViewports();
|
||||||
|
@ -224,83 +224,79 @@ static void CleanupVulkan()
|
|||||||
vkDestroyInstance(g_Instance, g_Allocator);
|
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;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
|
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);
|
||||||
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
check_vk_result(err);
|
||||||
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;
|
|
||||||
|
|
||||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
check_vk_result(err);
|
{
|
||||||
err = vkResetFences(g_Device, 1, &fd->Fence);
|
err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX); // wait indefinitely instead of periodically checking
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
|
||||||
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)
|
static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
|
||||||
{
|
{
|
||||||
VkResult err;
|
|
||||||
|
|
||||||
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||||
VkPresentInfoKHR info = {};
|
VkPresentInfoKHR info = {};
|
||||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||||
info.waitSemaphoreCount = 1;
|
info.waitSemaphoreCount = 1;
|
||||||
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
||||||
info.swapchainCount = 1;
|
info.swapchainCount = 1;
|
||||||
info.pSwapchains = &wd->Swapchain;
|
info.pSwapchains = &wd->Swapchain;
|
||||||
info.pImageIndices = &fd->BackbufferIndex;
|
info.pImageIndices = &wd->FrameIndex;
|
||||||
err = vkQueuePresentKHR(g_Queue, &info);
|
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||||
check_vk_result(err);
|
check_vk_result(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void glfw_error_callback(int error, const char* description)
|
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_ResizeWanted = true;
|
||||||
g_ResizeWidth = w;
|
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**)
|
int main(int, char**)
|
||||||
{
|
{
|
||||||
// Setup window
|
// Setup window
|
||||||
glfwSetErrorCallback(glfw_error_callback);
|
glfwSetErrorCallback(glfw_error_callback);
|
||||||
if (!glfwInit())
|
if (!glfwInit())
|
||||||
return 1;
|
return 1;
|
||||||
@ -354,6 +361,10 @@ int main(int, char**)
|
|||||||
io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar;
|
io.ConfigFlags |= ImGuiConfigFlags_PlatformNoTaskBar;
|
||||||
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
//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
|
// Setup Vulkan binding
|
||||||
ImGui_ImplVulkan_InitInfo init_info = {};
|
ImGui_ImplVulkan_InitInfo init_info = {};
|
||||||
init_info.Instance = g_Instance;
|
init_info.Instance = g_Instance;
|
||||||
@ -365,7 +376,6 @@ int main(int, char**)
|
|||||||
init_info.DescriptorPool = g_DescriptorPool;
|
init_info.DescriptorPool = g_DescriptorPool;
|
||||||
init_info.Allocator = g_Allocator;
|
init_info.Allocator = g_Allocator;
|
||||||
init_info.CheckVkResultFn = check_vk_result;
|
init_info.CheckVkResultFn = check_vk_result;
|
||||||
ImGui_ImplGlfw_InitForVulkan(window, true);
|
|
||||||
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
||||||
|
|
||||||
// Setup style
|
// 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.
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
if (g_ResizeWanted)
|
if (g_ResizeWanted)
|
||||||
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight);
|
{
|
||||||
g_ResizeWanted = false;
|
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight);
|
||||||
|
g_ResizeWanted = false;
|
||||||
|
}
|
||||||
|
|
||||||
ImGui_ImplVulkan_NewFrame();
|
ImGui_ImplVulkan_NewFrame();
|
||||||
ImGui_ImplGlfw_NewFrame();
|
ImGui_ImplGlfw_NewFrame();
|
||||||
|
|
||||||
@ -443,7 +456,7 @@ int main(int, char**)
|
|||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
ImGui::Text("Hello, world!"); // Display some text (you can use a format string too)
|
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::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("Demo Window", &show_demo_window); // Edit bools storing our windows open/close state
|
||||||
ImGui::Checkbox("Another Window", &show_another_window);
|
ImGui::Checkbox("Another Window", &show_another_window);
|
||||||
@ -476,13 +489,9 @@ int main(int, char**)
|
|||||||
// Rendering
|
// Rendering
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
|
||||||
FrameBegin(wd);
|
FrameRender(wd);
|
||||||
ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
|
|
||||||
FrameEnd(wd);
|
|
||||||
ImGui::RenderAdditionalViewports();
|
ImGui::RenderAdditionalViewports();
|
||||||
FramePresent(wd);
|
FramePresent(wd);
|
||||||
|
|
||||||
wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
3
imgui.h
3
imgui.h
@ -966,6 +966,9 @@ struct ImGuiPlatformInterface
|
|||||||
void (*RenderViewport)(ImGuiViewport* viewport);
|
void (*RenderViewport)(ImGuiViewport* viewport);
|
||||||
void (*SwapBuffers)(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
|
// FIXME-DPI
|
||||||
float (*GetWindowDpiScale)(ImGuiViewport* viewport); // (Optional)
|
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)
|
void (*ChangedViewport)(ImGuiViewport* viewport); // (Optional) Called during Begin() every time the viewport we are outputting into changes (viewport = next viewport)
|
||||||
|
Loading…
Reference in New Issue
Block a user