imgui

FORK: Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
git clone https://git.neptards.moe/neptards/imgui.git
Log | Files | Refs

main.cpp (24532B)


      1 // Dear ImGui: standalone example application for Glfw + Vulkan
      2 // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
      3 // Read online: https://github.com/ocornut/imgui/tree/master/docs
      4 
      5 // Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
      6 // - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
      7 //   You will use those if you want to use this rendering backend in your engine/app.
      8 // - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
      9 //   the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
     10 // Read comments in imgui_impl_vulkan.h.
     11 
     12 #include "imgui.h"
     13 #include "imgui_impl_glfw.h"
     14 #include "imgui_impl_vulkan.h"
     15 #include <stdio.h>          // printf, fprintf
     16 #include <stdlib.h>         // abort
     17 #define GLFW_INCLUDE_NONE
     18 #define GLFW_INCLUDE_VULKAN
     19 #include <GLFW/glfw3.h>
     20 #include <vulkan/vulkan.h>
     21 
     22 // [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
     23 // To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
     24 // Your own project should not be affected, as you are likely to link with a newer binary of GLFW that is adequate for your version of Visual Studio.
     25 #if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
     26 #pragma comment(lib, "legacy_stdio_definitions")
     27 #endif
     28 
     29 //#define IMGUI_UNLIMITED_FRAME_RATE
     30 #ifdef _DEBUG
     31 #define IMGUI_VULKAN_DEBUG_REPORT
     32 #endif
     33 
     34 static VkAllocationCallbacks*   g_Allocator = NULL;
     35 static VkInstance               g_Instance = VK_NULL_HANDLE;
     36 static VkPhysicalDevice         g_PhysicalDevice = VK_NULL_HANDLE;
     37 static VkDevice                 g_Device = VK_NULL_HANDLE;
     38 static uint32_t                 g_QueueFamily = (uint32_t)-1;
     39 static VkQueue                  g_Queue = VK_NULL_HANDLE;
     40 static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
     41 static VkPipelineCache          g_PipelineCache = VK_NULL_HANDLE;
     42 static VkDescriptorPool         g_DescriptorPool = VK_NULL_HANDLE;
     43 
     44 static ImGui_ImplVulkanH_Window g_MainWindowData;
     45 static int                      g_MinImageCount = 2;
     46 static bool                     g_SwapChainRebuild = false;
     47 
     48 static void check_vk_result(VkResult err)
     49 {
     50     if (err == 0)
     51         return;
     52     fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
     53     if (err < 0)
     54         abort();
     55 }
     56 
     57 #ifdef IMGUI_VULKAN_DEBUG_REPORT
     58 static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
     59 {
     60     (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
     61     fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
     62     return VK_FALSE;
     63 }
     64 #endif // IMGUI_VULKAN_DEBUG_REPORT
     65 
     66 static void SetupVulkan(const char** extensions, uint32_t extensions_count)
     67 {
     68     VkResult err;
     69 
     70     // Create Vulkan Instance
     71     {
     72         VkInstanceCreateInfo create_info = {};
     73         create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
     74         create_info.enabledExtensionCount = extensions_count;
     75         create_info.ppEnabledExtensionNames = extensions;
     76 #ifdef IMGUI_VULKAN_DEBUG_REPORT
     77         // Enabling validation layers
     78         const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
     79         create_info.enabledLayerCount = 1;
     80         create_info.ppEnabledLayerNames = layers;
     81 
     82         // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it)
     83         const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1));
     84         memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*));
     85         extensions_ext[extensions_count] = "VK_EXT_debug_report";
     86         create_info.enabledExtensionCount = extensions_count + 1;
     87         create_info.ppEnabledExtensionNames = extensions_ext;
     88 
     89         // Create Vulkan Instance
     90         err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
     91         check_vk_result(err);
     92         free(extensions_ext);
     93 
     94         // Get the function pointer (required for any extensions)
     95         auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
     96         IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL);
     97 
     98         // Setup the debug report callback
     99         VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
    100         debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
    101         debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
    102         debug_report_ci.pfnCallback = debug_report;
    103         debug_report_ci.pUserData = NULL;
    104         err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
    105         check_vk_result(err);
    106 #else
    107         // Create Vulkan Instance without any debug feature
    108         err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
    109         check_vk_result(err);
    110         IM_UNUSED(g_DebugReport);
    111 #endif
    112     }
    113 
    114     // Select GPU
    115     {
    116         uint32_t gpu_count;
    117         err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
    118         check_vk_result(err);
    119         IM_ASSERT(gpu_count > 0);
    120 
    121         VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
    122         err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
    123         check_vk_result(err);
    124 
    125         // If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
    126         // most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
    127         // dedicated GPUs) is out of scope of this sample.
    128         int use_gpu = 0;
    129         for (int i = 0; i < (int)gpu_count; i++)
    130         {
    131             VkPhysicalDeviceProperties properties;
    132             vkGetPhysicalDeviceProperties(gpus[i], &properties);
    133             if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
    134             {
    135                 use_gpu = i;
    136                 break;
    137             }
    138         }
    139 
    140         g_PhysicalDevice = gpus[use_gpu];
    141         free(gpus);
    142     }
    143 
    144     // Select graphics queue family
    145     {
    146         uint32_t count;
    147         vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL);
    148         VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
    149         vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
    150         for (uint32_t i = 0; i < count; i++)
    151             if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
    152             {
    153                 g_QueueFamily = i;
    154                 break;
    155             }
    156         free(queues);
    157         IM_ASSERT(g_QueueFamily != (uint32_t)-1);
    158     }
    159 
    160     // Create Logical Device (with 1 queue)
    161     {
    162         int device_extension_count = 1;
    163         const char* device_extensions[] = { "VK_KHR_swapchain" };
    164         const float queue_priority[] = { 1.0f };
    165         VkDeviceQueueCreateInfo queue_info[1] = {};
    166         queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    167         queue_info[0].queueFamilyIndex = g_QueueFamily;
    168         queue_info[0].queueCount = 1;
    169         queue_info[0].pQueuePriorities = queue_priority;
    170         VkDeviceCreateInfo create_info = {};
    171         create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    172         create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
    173         create_info.pQueueCreateInfos = queue_info;
    174         create_info.enabledExtensionCount = device_extension_count;
    175         create_info.ppEnabledExtensionNames = device_extensions;
    176         err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
    177         check_vk_result(err);
    178         vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
    179     }
    180 
    181     // Create Descriptor Pool
    182     {
    183         VkDescriptorPoolSize pool_sizes[] =
    184         {
    185             { VK_DESCRIPTOR_TYPE_SAMPLER, 1000 },
    186             { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1000 },
    187             { VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1000 },
    188             { VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1000 },
    189             { VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1000 },
    190             { VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1000 },
    191             { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1000 },
    192             { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1000 },
    193             { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1000 },
    194             { VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1000 },
    195             { VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1000 }
    196         };
    197         VkDescriptorPoolCreateInfo pool_info = {};
    198         pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
    199         pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
    200         pool_info.maxSets = 1000 * IM_ARRAYSIZE(pool_sizes);
    201         pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
    202         pool_info.pPoolSizes = pool_sizes;
    203         err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
    204         check_vk_result(err);
    205     }
    206 }
    207 
    208 // All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
    209 // Your real engine/app may not use them.
    210 static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
    211 {
    212     wd->Surface = surface;
    213 
    214     // Check for WSI support
    215     VkBool32 res;
    216     vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
    217     if (res != VK_TRUE)
    218     {
    219         fprintf(stderr, "Error no WSI support on physical device 0\n");
    220         exit(-1);
    221     }
    222 
    223     // Select Surface Format
    224     const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
    225     const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
    226     wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
    227 
    228     // Select Present Mode
    229 #ifdef IMGUI_UNLIMITED_FRAME_RATE
    230     VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
    231 #else
    232     VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
    233 #endif
    234     wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
    235     //printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
    236 
    237     // Create SwapChain, RenderPass, Framebuffer, etc.
    238     IM_ASSERT(g_MinImageCount >= 2);
    239     ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
    240 }
    241 
    242 static void CleanupVulkan()
    243 {
    244     vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
    245 
    246 #ifdef IMGUI_VULKAN_DEBUG_REPORT
    247     // Remove the debug report callback
    248     auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
    249     vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
    250 #endif // IMGUI_VULKAN_DEBUG_REPORT
    251 
    252     vkDestroyDevice(g_Device, g_Allocator);
    253     vkDestroyInstance(g_Instance, g_Allocator);
    254 }
    255 
    256 static void CleanupVulkanWindow()
    257 {
    258     ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
    259 }
    260 
    261 static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
    262 {
    263     VkResult err;
    264 
    265     VkSemaphore image_acquired_semaphore  = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
    266     VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
    267     err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
    268     if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
    269     {
    270         g_SwapChainRebuild = true;
    271         return;
    272     }
    273     check_vk_result(err);
    274 
    275     ImGui_ImplVulkanH_Frame* fd = &wd->Frames[wd->FrameIndex];
    276     {
    277         err = vkWaitForFences(g_Device, 1, &fd->Fence, VK_TRUE, UINT64_MAX);    // wait indefinitely instead of periodically checking
    278         check_vk_result(err);
    279 
    280         err = vkResetFences(g_Device, 1, &fd->Fence);
    281         check_vk_result(err);
    282     }
    283     {
    284         err = vkResetCommandPool(g_Device, fd->CommandPool, 0);
    285         check_vk_result(err);
    286         VkCommandBufferBeginInfo info = {};
    287         info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    288         info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    289         err = vkBeginCommandBuffer(fd->CommandBuffer, &info);
    290         check_vk_result(err);
    291     }
    292     {
    293         VkRenderPassBeginInfo info = {};
    294         info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
    295         info.renderPass = wd->RenderPass;
    296         info.framebuffer = fd->Framebuffer;
    297         info.renderArea.extent.width = wd->Width;
    298         info.renderArea.extent.height = wd->Height;
    299         info.clearValueCount = 1;
    300         info.pClearValues = &wd->ClearValue;
    301         vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
    302     }
    303 
    304     // Record dear imgui primitives into command buffer
    305     ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
    306 
    307     // Submit command buffer
    308     vkCmdEndRenderPass(fd->CommandBuffer);
    309     {
    310         VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    311         VkSubmitInfo info = {};
    312         info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    313         info.waitSemaphoreCount = 1;
    314         info.pWaitSemaphores = &image_acquired_semaphore;
    315         info.pWaitDstStageMask = &wait_stage;
    316         info.commandBufferCount = 1;
    317         info.pCommandBuffers = &fd->CommandBuffer;
    318         info.signalSemaphoreCount = 1;
    319         info.pSignalSemaphores = &render_complete_semaphore;
    320 
    321         err = vkEndCommandBuffer(fd->CommandBuffer);
    322         check_vk_result(err);
    323         err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
    324         check_vk_result(err);
    325     }
    326 }
    327 
    328 static void FramePresent(ImGui_ImplVulkanH_Window* wd)
    329 {
    330     if (g_SwapChainRebuild)
    331         return;
    332     VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
    333     VkPresentInfoKHR info = {};
    334     info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    335     info.waitSemaphoreCount = 1;
    336     info.pWaitSemaphores = &render_complete_semaphore;
    337     info.swapchainCount = 1;
    338     info.pSwapchains = &wd->Swapchain;
    339     info.pImageIndices = &wd->FrameIndex;
    340     VkResult err = vkQueuePresentKHR(g_Queue, &info);
    341     if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
    342     {
    343         g_SwapChainRebuild = true;
    344         return;
    345     }
    346     check_vk_result(err);
    347     wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
    348 }
    349 
    350 static void glfw_error_callback(int error, const char* description)
    351 {
    352     fprintf(stderr, "Glfw Error %d: %s\n", error, description);
    353 }
    354 
    355 int main(int, char**)
    356 {
    357     // Setup GLFW window
    358     glfwSetErrorCallback(glfw_error_callback);
    359     if (!glfwInit())
    360         return 1;
    361 
    362     glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    363     GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Vulkan example", NULL, NULL);
    364 
    365     // Setup Vulkan
    366     if (!glfwVulkanSupported())
    367     {
    368         printf("GLFW: Vulkan Not Supported\n");
    369         return 1;
    370     }
    371     uint32_t extensions_count = 0;
    372     const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
    373     SetupVulkan(extensions, extensions_count);
    374 
    375     // Create Window Surface
    376     VkSurfaceKHR surface;
    377     VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &surface);
    378     check_vk_result(err);
    379 
    380     // Create Framebuffers
    381     int w, h;
    382     glfwGetFramebufferSize(window, &w, &h);
    383     ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
    384     SetupVulkanWindow(wd, surface, w, h);
    385 
    386     // Setup Dear ImGui context
    387     IMGUI_CHECKVERSION();
    388     ImGui::CreateContext();
    389     ImGuiIO& io = ImGui::GetIO(); (void)io;
    390     //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;     // Enable Keyboard Controls
    391     //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;      // Enable Gamepad Controls
    392 
    393     // Setup Dear ImGui style
    394     ImGui::StyleColorsDark();
    395     //ImGui::StyleColorsClassic();
    396 
    397     // Setup Platform/Renderer backends
    398     ImGui_ImplGlfw_InitForVulkan(window, true);
    399     ImGui_ImplVulkan_InitInfo init_info = {};
    400     init_info.Instance = g_Instance;
    401     init_info.PhysicalDevice = g_PhysicalDevice;
    402     init_info.Device = g_Device;
    403     init_info.QueueFamily = g_QueueFamily;
    404     init_info.Queue = g_Queue;
    405     init_info.PipelineCache = g_PipelineCache;
    406     init_info.DescriptorPool = g_DescriptorPool;
    407     init_info.Allocator = g_Allocator;
    408     init_info.MinImageCount = g_MinImageCount;
    409     init_info.ImageCount = wd->ImageCount;
    410     init_info.CheckVkResultFn = check_vk_result;
    411     ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
    412 
    413     // Load Fonts
    414     // - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
    415     // - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
    416     // - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
    417     // - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
    418     // - Read 'docs/FONTS.md' for more instructions and details.
    419     // - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
    420     //io.Fonts->AddFontDefault();
    421     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
    422     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
    423     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
    424     //io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
    425     //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
    426     //IM_ASSERT(font != NULL);
    427 
    428     // Upload Fonts
    429     {
    430         // Use any command queue
    431         VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
    432         VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
    433 
    434         err = vkResetCommandPool(g_Device, command_pool, 0);
    435         check_vk_result(err);
    436         VkCommandBufferBeginInfo begin_info = {};
    437         begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    438         begin_info.flags |= VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
    439         err = vkBeginCommandBuffer(command_buffer, &begin_info);
    440         check_vk_result(err);
    441 
    442         ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
    443 
    444         VkSubmitInfo end_info = {};
    445         end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    446         end_info.commandBufferCount = 1;
    447         end_info.pCommandBuffers = &command_buffer;
    448         err = vkEndCommandBuffer(command_buffer);
    449         check_vk_result(err);
    450         err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE);
    451         check_vk_result(err);
    452 
    453         err = vkDeviceWaitIdle(g_Device);
    454         check_vk_result(err);
    455         ImGui_ImplVulkan_DestroyFontUploadObjects();
    456     }
    457 
    458     // Our state
    459     bool show_demo_window = true;
    460     bool show_another_window = false;
    461     ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
    462 
    463     // Main loop
    464     while (!glfwWindowShouldClose(window))
    465     {
    466         // Poll and handle events (inputs, window resize, etc.)
    467         // You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
    468         // - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
    469         // - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
    470         // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
    471         glfwPollEvents();
    472 
    473         // Resize swap chain?
    474         if (g_SwapChainRebuild)
    475         {
    476             int width, height;
    477             glfwGetFramebufferSize(window, &width, &height);
    478             if (width > 0 && height > 0)
    479             {
    480                 ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
    481                 ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
    482                 g_MainWindowData.FrameIndex = 0;
    483                 g_SwapChainRebuild = false;
    484             }
    485         }
    486 
    487         // Start the Dear ImGui frame
    488         ImGui_ImplVulkan_NewFrame();
    489         ImGui_ImplGlfw_NewFrame();
    490         ImGui::NewFrame();
    491 
    492         // 1. Show the big demo window (Most of the sample code is in ImGui::ShowDemoWindow()! You can browse its code to learn more about Dear ImGui!).
    493         if (show_demo_window)
    494             ImGui::ShowDemoWindow(&show_demo_window);
    495 
    496         // 2. Show a simple window that we create ourselves. We use a Begin/End pair to created a named window.
    497         {
    498             static float f = 0.0f;
    499             static int counter = 0;
    500 
    501             ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.
    502 
    503             ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)
    504             ImGui::Checkbox("Demo Window", &show_demo_window);      // Edit bools storing our window open/close state
    505             ImGui::Checkbox("Another Window", &show_another_window);
    506 
    507             ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f
    508             ImGui::ColorEdit3("clear color", (float*)&clear_color); // Edit 3 floats representing a color
    509 
    510             if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated)
    511                 counter++;
    512             ImGui::SameLine();
    513             ImGui::Text("counter = %d", counter);
    514 
    515             ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
    516             ImGui::End();
    517         }
    518 
    519         // 3. Show another simple window.
    520         if (show_another_window)
    521         {
    522             ImGui::Begin("Another Window", &show_another_window);   // Pass a pointer to our bool variable (the window will have a closing button that will clear the bool when clicked)
    523             ImGui::Text("Hello from another window!");
    524             if (ImGui::Button("Close Me"))
    525                 show_another_window = false;
    526             ImGui::End();
    527         }
    528 
    529         // Rendering
    530         ImGui::Render();
    531         ImDrawData* draw_data = ImGui::GetDrawData();
    532         const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
    533         if (!is_minimized)
    534         {
    535             wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
    536             wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
    537             wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
    538             wd->ClearValue.color.float32[3] = clear_color.w;
    539             FrameRender(wd, draw_data);
    540             FramePresent(wd);
    541         }
    542     }
    543 
    544     // Cleanup
    545     err = vkDeviceWaitIdle(g_Device);
    546     check_vk_result(err);
    547     ImGui_ImplVulkan_Shutdown();
    548     ImGui_ImplGlfw_Shutdown();
    549     ImGui::DestroyContext();
    550 
    551     CleanupVulkanWindow();
    552     CleanupVulkan();
    553 
    554     glfwDestroyWindow(window);
    555     glfwTerminate();
    556 
    557     return 0;
    558 }