Green Sky
5dd9834009
b475309fa1e Fonts: Fixed font ascent and descent calculation when a font hits exact integer values. (#7399, #7404) daecfffefbc Text, DrawList: Improved handling of long single-line wrapped text. (#7496, #5720) fab96a6e593 Backends: SDL3: Re-enable calling SDL_StartTextInput()/SDL_StopTextInput(). (#7452, #6306, #6071, #1953) dad1689bf7b Examples: SDL3: amend for removal of SDL_RENDERER_ACCELERATED. 3caa79c8a53 Version 1.90.6 WIP 76bc1b825e6 Extracted part of NewFrame() into SetupDrawListSharedData() for documentation purpose. (#7495, #6406) f790d516652 Silent zealous/stupid warning introduced by Clang 16 (shipping with VS2022) with -Weverything. Pointers are now illegal! 231cbee0fc4 Version 1.90.5 4f9ba19e520 Drags, Sliders, Inputs: Reactivated decimal point replacement for SliderScalar and DragScalar. (#7389, #6719, #2278) e7712ff103d Out of courtesy/consistency move all the DebugHookIdInfo compares into ifndef block. f959c417fec Refactor moving ID stack functions to their own section (part 2) 0bf134a8e2e Refactor moving ID stack functions to their own section. 9a2b598ec1e ListBox: Fixed text-baseline offset when using SameLine()+Text() after a labeled ListBox(). d3c3514a59b Tables: Fixed auto-width columns when using synced-instances of same table. (#7218) 25a492f3307 ProgressBar: Fixed passing fraction==NaN from leading to a crash. (#7451) 9638c2839a1 Internals: adding ImGuiNavMoveFlags_NoClearActiveId even though there's currently no satisfying way to take advantage of it. (#1418) 742e53434f4 Child Windows: adjust resizing limits to match window padding rather than inner clipping rectangle. (#7440) 515b437c084 Child windows: look at the parent window's flags to decide whether to clamp child resizes. (#7440, #1710) 976dc239656 Windows: extend outer resize borders to the edges when there are no corner grips. (#7440, #1710) 37b37fc2a3e DrawList: Allow AddText() to accept null ranges. (#3615, 7391) 5c5ae806aa1 Comments cf4c10bef74 Style: added ImGuiStyleVar_TabBorderSize, ImGuiStyleVar_TableAngledHeadersAngle. (#7411) f0802287db5 Tables: Angled headers: fixed table contents overflowing when a list clipper is used. (#7416) 29ff159f941 Tables: Angled headers: fixed borders not moving back up after TableAngleHeadersRow stops being called. (#7416) 38ddfb24f09 Tables: Angled headers: fixed border hit box extending beyond non-scrollable tables. (#7416) 8be48a44f78 Backends: WebGPU: Avoid using -1u literal (#7436) 868facff9de ImDrawList: (Breaking) merge float radius_x/radius_y parameters into ImVec2 radius in PathEllipticalArcTo(), AddEllipse(), AddEllipseFilled(). (#2743, #7417) 0a1f5b94e31 Demo: Two minor fixes (unchecked BeginTooltip + incorrect height constraint) (#7410)l 40df3db1a2a Tweaking terminology da29b776eed Backends: SDL3: Fix leak of SDL_GetGamepads() return value (#7381) 3c435c02978 Inputs: (Breaking) More formally obsoleted GetKeyIndex() when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is set. (#4921) 286cd5bd41e Internals, InputText: removed ImGuiInputSource_Clipboard. (#4005) fc570ac9225 Examples: WGPU: fixed initialization of WGPURenderPassColorAttachment (#7371) 65dc67f63c6 Windows: Double-click to collapse may be disabled via key-ownership mechanism. (#7369) 6b7358e9f36 InputText: adding clarifying note about ImGuiInputTextCallbackData::Buf. (#7363) fbf45ad149b ImDrawList: add PathFillConcave(), AddConcavePolyFilled(): amends (#760) 1ff90c52d5f ImDrawList: add PathFillConcave(), AddConcavePolyFilled() (#760) 04f40014a62 Docs: added a mini wiki index in main source files. c6236699671 Added link to crawlable wiki 0573513d6df Windows: Scrollbar visibility decision uses current size when both size and contents size are submitted by API. (#7252) 44c7dfca030 Menus, Popup: Amend c3f8f4d for static analyzer warning ("condition always true"). (#7325) c3f8f4de257 Menus, Popups: Fixed an issue where sibling menu popups re-opening in successive frames would erroneously close the window. (#7325, #7287, #7063) 98779417751 Popups, Menus: rename ImGuiPopupData::BackupNavWindow > RestoreNavWindow and minor tweaks. Should be functionally a no-op. 725f91922d5 Tables: fixed TableGetHoveredRow() with overlapping frozen rows (#7350, #6588, #6347, #6250) e46d1e69ac3 Version 1.90.5 WIP 277ae93c413 Version 1.90.4 f5be90523d6 Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on windows with the ImGuiWindowFlags_NoNavInputs flag. 13d91ff9188 Nav: Fixed SetKeyboardFocusHere() or programmatic tabbing API from not working on windows with the ImGuiWindowFlags_NoNavInputs flag. 34965cf23a7 Modals: Temporary changes of ImGuiCol_ModalWindowDimBg are properly handled by BeginPopupModal(). (#7340) 659fb41d0a2 Debug Tools: moved DebugStartItemPicker() to public API. Added to Demo->Tools menu. (#2673) 198c38f0b11 Demo: Custom Rendering: better demonstrate PathArcTo(), PathBezierQuadraticCurveTo(), PathBezierCubicCurveTo(), PathStroke(), PathFillConvex() functions. 3b6d924acd0 ProgressBar: Fixed a minor tesselation issue when rendering rounded progress bars. d3f1a7165cb Popups: allow Child Popups to be resizable if not explicitly disabling. e78ce72eb6d Popups: Fixed resizable popup minimum size being too small. Standardized CalcWindowMinSize() logic a bit more. (#73290 014e0ac8c92 Menus, Popups: Fixed an issue where hovering a parent-menu upward would erroneously close the window. (#7325, #7287, #7063) c16043c1d58 Tables: Angled headers: improve clipping of text since multi-line labels makes clipping issues visible. (#6917) 405e54ebd50 Tables: Angled Headers: fixed support for multi-line labels. various padding/layout fixes. (#6917) 6655ab2e43f Tables: Angled Headers: fixed TableAngledHeadersRow() incorrect background fill drawn too low. Fixed row geometry with non-small values of CellPadding. (#6917) 9159cd7b4ac Updated invalid documentation link (#7331) ccc5347e451 Fix typos (#7332) 8a14b71f228 Version 1.90.4 WIP b19a4c5f2b3 Backends: OSX: remove legacy clearing of io.NavInputs in ImGui_ImplOSX_UpdateGamepads(). (#7320) 5b6f03213dd Version 1.90.3 f80e65a4068 Backends:,Examples: Vulkan: moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. (#7308) 829f45df994 Backends: SDL2: removed obsolete ImGui_ImplSDL2_NewFrame(SDL_Window*) signature which was obsoleted in 1.84.. 3cc37170ca7 Examples: GLFW+Metal: Add -I and -L paths for MacPorts. 891b81fc5d7 Backends: SDL3: Fixed gamepad. Added support for disconnection. Added support for multiple gamepads. Added ImGui_ImplSDL3_SetGamepadMode(). (#7180, #3884, #6559, #6890) 262e30e3001 Backends: SDL2: rework new API as ImGui_ImplSDL2_SetGamepadMode(). (#3884, #6559, #6890, #7180) 9dfa2397deb Internals: Fixed ImFileOpen not working before context is created. (#7314, #7315) d15e4100b83 Backends: SDL2: Amend new API, all support for multiple gamepads. (#3884, #6559, #6890) f966da1f8fb Backends: SDL2: Gamepad handlng: amend bf1c96d. (#3884, #6559, #6890) bf1c96d4fa2 Backends: SDL2: Handle gamepad disconnection + fixed increasing refcount. Added ImGui_ImplSDL2_SelectGamepadAuto()/ImGui_ImplSDL2_SelectGamepadExplicit(). (#3884, #6559, #6890) fd8d6dc5d19 Backends: SDL2,SDL3: tidying up. e0ba0d0433a Backends: Vulkan: Fixes for building with pre Vulkan 1.3. Amend 8901931. (#7166) 11d73f03ee5 Backends: Vulkan: Fix/amend 8901931 89019319ddb Backends: Vulkan: use PipelineRenderingCreateInfo for dynamic rendering (#7166, #6855, #5446, #5037) 1d6f0cea0e6 Backends: DX9: use RGBA texture to avoid conversion if supported 3af739a2d17 Menus, Popups: fixed menus and popups with child window flag erroneously not displaying a scrollbar when contents is over parent viewport size. (#7287, #7063) 2af01baffd1 Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore a wrong viewport if none was initially set. 915c6393ad7 Version 1.90.3 WIP 536090303a8 Version 1.90.2 7b5357d817e Debug Tools: Metrics: Improved Monitors and Viewports minimap display. Highlight on hover. 70aa717a8e1 Combo: Fixed not reusing windows optimally when used inside a popup stack. 5cdc4a2a413 Demo: use ImGui::MemAlloc/MemFree for consistency. (#7300) 76e09c4b0fa ClosePopupsOverWindow(): amend to remove _ChildWindow test. 3a078466a7a Nav: ImGuiWindowFlags_NoNavInputs is tested during scoring so NavFlattened windows can use it. 7d67623d15b InputText: Internal: ReloadUserBufXXX functions don't override revert value. (#2890) fix accidental comment. a5e0e90c16a Nav: tweak RenderNavHighlight() syntax. ImGuiNavHighlightFlags_TypeThin -> ImGuiNavHighlightFlags_Compact. 1e8fc01ddd7 InputText: Internal: ReloadUserBufXXX functions don't override revert value. (#2890) + rename a06dd7a27b6 OpenPopup(): Added ImGuiPopupFlags_NoReopen. Nav, Menus: Fixed click on a BeginMenu() followed by right-arrow. (#1497, #1533) f104967c68f Comments 06ce312745e InputText: Internal: added reload from user-buf feature. (#2890) f50ddc431e3 Fixed some typos. (#7282) 6172c22c5dc CI: Update to `actions/checkout` `v4` from `v3`. (#7281) 96839b445e3 Nav: Improve handling of Alt key to toggle menu so that key ownership may be claimed on indiviudal left/right alt key without intefering with the other. 71947563709 Shortcut: fixed single mod-key Shortcut from working e.g. Shortcut(ImGuiKey_LeftCtrl) f1960b60c1a Added "nop" to IM_DEBUG_BREAK macro on GCC to work around GDB bug (#7266) 8491cf36adb Inputs: g.ActiveIdUsingManyKeys[] prevent routes from being claimed. 9176eedf240 Internals: SetShortcutRouting() move code so next commit is easier to read. Should be no-op. 1509842107d Backends: OpenGL3: Shallow tweak of compile-time extensions detection. 1ce41f6218d Backends: OpenGL3: Backup and restore GL_PIXEL_UNPACK_BUFFER. (#7253) 81e0be856a6 Fixed strict-aliasing violation in FormatTextureIDForDebugDisplay(). (#7090, #7256) a201af73544 Added SetNextItemShortcut() wip function. (#456) 4c2c09450a6 Nav: keyboard/gamepad activation feedback properly timed instead of frame buffer. (#456) 5b5e9bd0cb3 Internals: Tweak shallow compaction as Clang complains about MS ABI signage of enums. 7c3fa7d049a Refactor: moved section in imgui_internal.h 9266c0d2d13 Backends: WebGPU: Avoid leaking pipeline layout. (#7245) 595eb86624d Changelog, comment, minor data compaction 6850194f60a CI: Fixes WGPU example build. 5fc0a361b24 Backends: WebGPU: added ImGui_ImplWGPU_InitInfo::PipelineMultisampleState. (#7240) 831d42c1ab3 Backends: WebGPU: ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. (#7240) e3c7ff944d5 Examples: Emscripten+WebGPU: slightly refactor like other Emscripten compatible Desktop examples, as aiming to make this suppot desktop eventually. 15908502ed6 Backends: Vulkan: Define NOMINMAX when VK_USE_PLATFORM_WIN32_KHR is defined. (#7250) 788747f8635 Examples: Emscripten+WebGPU: Remove use of deprecated ObjectBase<...>::Release in favor of ::MoveToCHandle (#7251) 763100b3858 Nav: Fixed pressing Escape while in a child window with _NavFlattened flag. (#7237) c7edb446caa Shortcut(): always test ownership. 1844f903d55 Nav: space/enter poll check ownership. InputText: declare ownership of Enter key as it doesn't go through Shortcut 5ddfbb80d86 Backends: Vulkan: Fixed vkAcquireNextImageKHR() validation errors in VulkanSDK 1.3.275 by allocating one extra semaphore than in-flight frames. (#7236) 2f483373355 Examples: Vulkan: Rename compile-time defies for the examples to remove misleading IMGUI_ prefixes. d7c2a0e38f4 Shortcut(): fixed 8323a06 adding _Repeat to all Shortcut() calls. 3b828d3701e Refactor: moving ItemAdd() into a section abote ItemSize(). No logic change (part 2) ff5f3aa38b5 Refactor: moving ItemAdd() into a section abote ItemSize(). No logic change (part 1) 1a48a634466 Enclosed a few more remaining sections in ifndef IMGUI_DISABLE_DEBUG_TOOLS for completeness. 33fabdf392d Scrollbar() doesn't forcefully mark itself as hovered when held. d431d85839b Internals: removed obsolete ImPool::GetSize() (last used by implot 0.10, changed in implot 0.11) f0d1f61fa51 Internals: commented out long-time obsoleted FocusableItemRegister()/FocusableItemUnregister() documentaton-only leftovers. + 095665977f6 Nav: marking NavId as hovered in ButtonBehavior() doesn't check for ActiveId. d10641b04a3 Nav: keyboard/gamepad activation mark widgets as held to give better visual feedback. 03417cc77d1 Backends: WebGPU: Filling all WGPUDepthStencilState fields explicitly as a recent Dawn update stopped setting default values. (#7232) 5fdcdf7080a Shortcut: ImGuiInputFlags_RouteFocused policy can filter Shortcuts conflicting with character input when an item is active. (#456) 80d5cb1ab1f Comments around ImGuiInputFlags. 1cc0eb4d322 Internals: Rename NavFocusScopePath to NavFocusRoute + fixed a static analyzer warning. 46e5f44ec8c Shortcut()/SetShortcutRouting(): use mixed current window focus scope + ParentWindowForFocusRoute. (#6798, #2637, #456) e0c8c80adaa Shortcut()/SetShortcutRouting(): focus route testing now use ParentWindowForFocusRoute. Automatically set on child-window, manually configurable otherwise. (#6798, #2637, #456) 4b20a0217eb Internals: add window to FocusScopeStack. (#6798) 2156db7a075 Debug Log: added InputRouting logging. Made GetKeyChordName() use its own buffer. Fixed debug break in SetShortcutRouting(). (#6798, #2637, #456) dd0efdc6371 Fixed SetKeyboardFocusHere() not working when current nav focus is in different scope. (#7226) 8a3dfda8d08 Commented out obsolete ImGuiIO::ImeWindowHandle marked obsolete in 1.87, favor of writing to 'void* ImGuiViewport::PlatformHandleRaw'. 6228c2e1ec7 Backends: Vulkan: moved ImGui_ImplVulkanH_DestroyFrameRenderBuffers/ImGui_ImplVulkanH_DestroyWindowRenderBuffers as they are always used in a state where backend data is available. 70bb6d1e790 Backends: Vulkan: Fixed vkMapMemory() calls unnecessarily using full buffer size. (#3957) 82df7c8bf41 Backends: Vulkan: Fixed handling of ImGui_ImplVulkan_InitInfo::MinAllocationSize field. (#7189, #4238) 29809d72202 Version 1.90.2 WIP db049db8608 Docs: tweak, fixed misplaced changelog entry. (#7084) git-subtree-dir: external/imgui/imgui git-subtree-split: b475309fa1e9d7a91825a169e243f9c4fa085f71
563 lines
24 KiB
C++
563 lines
24 KiB
C++
// Dear ImGui: standalone example application for Glfw + Vulkan
|
|
|
|
// Learn about Dear ImGui:
|
|
// - FAQ https://dearimgui.com/faq
|
|
// - Getting Started https://dearimgui.com/getting-started
|
|
// - Documentation https://dearimgui.com/docs (same as your local docs/ folder).
|
|
// - Introduction, links and more at the top of imgui.cpp
|
|
|
|
// Important note to the reader who wish to integrate imgui_impl_vulkan.cpp/.h in their own engine/app.
|
|
// - Common ImGui_ImplVulkan_XXX functions and structures are used to interface with imgui_impl_vulkan.cpp/.h.
|
|
// You will use those if you want to use this rendering backend in your engine/app.
|
|
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
|
// the backend itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
|
|
// Read comments in imgui_impl_vulkan.h.
|
|
|
|
#include "imgui.h"
|
|
#include "imgui_impl_glfw.h"
|
|
#include "imgui_impl_vulkan.h"
|
|
#include <stdio.h> // printf, fprintf
|
|
#include <stdlib.h> // abort
|
|
#define GLFW_INCLUDE_NONE
|
|
#define GLFW_INCLUDE_VULKAN
|
|
#include <GLFW/glfw3.h>
|
|
#include <vulkan/vulkan.h>
|
|
//#include <vulkan/vulkan_beta.h>
|
|
|
|
// [Win32] Our example includes a copy of glfw3.lib pre-compiled with VS2010 to maximize ease of testing and compatibility with old VS compilers.
|
|
// To link with VS2010-era libraries, VS2015+ requires linking with legacy_stdio_definitions.lib, which we do using this pragma.
|
|
// 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.
|
|
#if defined(_MSC_VER) && (_MSC_VER >= 1900) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS)
|
|
#pragma comment(lib, "legacy_stdio_definitions")
|
|
#endif
|
|
|
|
//#define APP_USE_UNLIMITED_FRAME_RATE
|
|
#ifdef _DEBUG
|
|
#define APP_USE_VULKAN_DEBUG_REPORT
|
|
#endif
|
|
|
|
// Data
|
|
static VkAllocationCallbacks* g_Allocator = nullptr;
|
|
static VkInstance g_Instance = VK_NULL_HANDLE;
|
|
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
|
static VkDevice g_Device = VK_NULL_HANDLE;
|
|
static uint32_t g_QueueFamily = (uint32_t)-1;
|
|
static VkQueue g_Queue = VK_NULL_HANDLE;
|
|
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
|
|
static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
|
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
|
|
|
static ImGui_ImplVulkanH_Window g_MainWindowData;
|
|
static int g_MinImageCount = 2;
|
|
static bool g_SwapChainRebuild = false;
|
|
|
|
static void glfw_error_callback(int error, const char* description)
|
|
{
|
|
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
|
}
|
|
static void check_vk_result(VkResult err)
|
|
{
|
|
if (err == 0)
|
|
return;
|
|
fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
|
|
if (err < 0)
|
|
abort();
|
|
}
|
|
|
|
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
|
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)
|
|
{
|
|
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
|
|
fprintf(stderr, "[vulkan] Debug report from ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
|
|
return VK_FALSE;
|
|
}
|
|
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
|
|
|
static bool IsExtensionAvailable(const ImVector<VkExtensionProperties>& properties, const char* extension)
|
|
{
|
|
for (const VkExtensionProperties& p : properties)
|
|
if (strcmp(p.extensionName, extension) == 0)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
static VkPhysicalDevice SetupVulkan_SelectPhysicalDevice()
|
|
{
|
|
uint32_t gpu_count;
|
|
VkResult err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, nullptr);
|
|
check_vk_result(err);
|
|
IM_ASSERT(gpu_count > 0);
|
|
|
|
ImVector<VkPhysicalDevice> gpus;
|
|
gpus.resize(gpu_count);
|
|
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus.Data);
|
|
check_vk_result(err);
|
|
|
|
// If a number >1 of GPUs got reported, find discrete GPU if present, or use first one available. This covers
|
|
// most common cases (multi-gpu/integrated+dedicated graphics). Handling more complicated setups (multiple
|
|
// dedicated GPUs) is out of scope of this sample.
|
|
for (VkPhysicalDevice& device : gpus)
|
|
{
|
|
VkPhysicalDeviceProperties properties;
|
|
vkGetPhysicalDeviceProperties(device, &properties);
|
|
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
|
return device;
|
|
}
|
|
|
|
// Use first GPU (Integrated) is a Discrete one is not available.
|
|
if (gpu_count > 0)
|
|
return gpus[0];
|
|
return VK_NULL_HANDLE;
|
|
}
|
|
|
|
static void SetupVulkan(ImVector<const char*> instance_extensions)
|
|
{
|
|
VkResult err;
|
|
|
|
// Create Vulkan Instance
|
|
{
|
|
VkInstanceCreateInfo create_info = {};
|
|
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
|
|
// Enumerate available extensions
|
|
uint32_t properties_count;
|
|
ImVector<VkExtensionProperties> properties;
|
|
vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, nullptr);
|
|
properties.resize(properties_count);
|
|
err = vkEnumerateInstanceExtensionProperties(nullptr, &properties_count, properties.Data);
|
|
check_vk_result(err);
|
|
|
|
// Enable required extensions
|
|
if (IsExtensionAvailable(properties, VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
|
instance_extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
|
#ifdef VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME
|
|
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME))
|
|
{
|
|
instance_extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
|
create_info.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
|
}
|
|
#endif
|
|
|
|
// Enabling validation layers
|
|
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
|
const char* layers[] = { "VK_LAYER_KHRONOS_validation" };
|
|
create_info.enabledLayerCount = 1;
|
|
create_info.ppEnabledLayerNames = layers;
|
|
instance_extensions.push_back("VK_EXT_debug_report");
|
|
#endif
|
|
|
|
// Create Vulkan Instance
|
|
create_info.enabledExtensionCount = (uint32_t)instance_extensions.Size;
|
|
create_info.ppEnabledExtensionNames = instance_extensions.Data;
|
|
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
|
|
check_vk_result(err);
|
|
|
|
// Setup the debug report callback
|
|
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
|
auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT");
|
|
IM_ASSERT(vkCreateDebugReportCallbackEXT != nullptr);
|
|
VkDebugReportCallbackCreateInfoEXT debug_report_ci = {};
|
|
debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
|
debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
|
debug_report_ci.pfnCallback = debug_report;
|
|
debug_report_ci.pUserData = nullptr;
|
|
err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport);
|
|
check_vk_result(err);
|
|
#endif
|
|
}
|
|
|
|
// Select Physical Device (GPU)
|
|
g_PhysicalDevice = SetupVulkan_SelectPhysicalDevice();
|
|
|
|
// Select graphics queue family
|
|
{
|
|
uint32_t count;
|
|
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, nullptr);
|
|
VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count);
|
|
vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues);
|
|
for (uint32_t i = 0; i < count; i++)
|
|
if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
|
{
|
|
g_QueueFamily = i;
|
|
break;
|
|
}
|
|
free(queues);
|
|
IM_ASSERT(g_QueueFamily != (uint32_t)-1);
|
|
}
|
|
|
|
// Create Logical Device (with 1 queue)
|
|
{
|
|
ImVector<const char*> device_extensions;
|
|
device_extensions.push_back("VK_KHR_swapchain");
|
|
|
|
// Enumerate physical device extension
|
|
uint32_t properties_count;
|
|
ImVector<VkExtensionProperties> properties;
|
|
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, nullptr);
|
|
properties.resize(properties_count);
|
|
vkEnumerateDeviceExtensionProperties(g_PhysicalDevice, nullptr, &properties_count, properties.Data);
|
|
#ifdef VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME
|
|
if (IsExtensionAvailable(properties, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME))
|
|
device_extensions.push_back(VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME);
|
|
#endif
|
|
|
|
const float queue_priority[] = { 1.0f };
|
|
VkDeviceQueueCreateInfo queue_info[1] = {};
|
|
queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
queue_info[0].queueFamilyIndex = g_QueueFamily;
|
|
queue_info[0].queueCount = 1;
|
|
queue_info[0].pQueuePriorities = queue_priority;
|
|
VkDeviceCreateInfo create_info = {};
|
|
create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
create_info.queueCreateInfoCount = sizeof(queue_info) / sizeof(queue_info[0]);
|
|
create_info.pQueueCreateInfos = queue_info;
|
|
create_info.enabledExtensionCount = (uint32_t)device_extensions.Size;
|
|
create_info.ppEnabledExtensionNames = device_extensions.Data;
|
|
err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device);
|
|
check_vk_result(err);
|
|
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
|
|
}
|
|
|
|
// Create Descriptor Pool
|
|
// The example only requires a single combined image sampler descriptor for the font image and only uses one descriptor set (for that)
|
|
// If you wish to load e.g. additional textures you may need to alter pools sizes.
|
|
{
|
|
VkDescriptorPoolSize pool_sizes[] =
|
|
{
|
|
{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1 },
|
|
};
|
|
VkDescriptorPoolCreateInfo pool_info = {};
|
|
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
|
pool_info.maxSets = 1;
|
|
pool_info.poolSizeCount = (uint32_t)IM_ARRAYSIZE(pool_sizes);
|
|
pool_info.pPoolSizes = pool_sizes;
|
|
err = vkCreateDescriptorPool(g_Device, &pool_info, g_Allocator, &g_DescriptorPool);
|
|
check_vk_result(err);
|
|
}
|
|
}
|
|
|
|
// All the ImGui_ImplVulkanH_XXX structures/functions are optional helpers used by the demo.
|
|
// Your real engine/app may not use them.
|
|
static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface, int width, int height)
|
|
{
|
|
wd->Surface = surface;
|
|
|
|
// 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);
|
|
}
|
|
|
|
// Select 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);
|
|
|
|
// Select Present Mode
|
|
#ifdef APP_USE_UNLIMITED_FRAME_RATE
|
|
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_MAILBOX_KHR, VK_PRESENT_MODE_IMMEDIATE_KHR, VK_PRESENT_MODE_FIFO_KHR };
|
|
#else
|
|
VkPresentModeKHR present_modes[] = { VK_PRESENT_MODE_FIFO_KHR };
|
|
#endif
|
|
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_modes[0], IM_ARRAYSIZE(present_modes));
|
|
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
|
|
|
// Create SwapChain, RenderPass, Framebuffer, etc.
|
|
IM_ASSERT(g_MinImageCount >= 2);
|
|
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
|
}
|
|
|
|
static void CleanupVulkan()
|
|
{
|
|
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
|
|
|
#ifdef APP_USE_VULKAN_DEBUG_REPORT
|
|
// Remove the debug report callback
|
|
auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT");
|
|
vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator);
|
|
#endif // APP_USE_VULKAN_DEBUG_REPORT
|
|
|
|
vkDestroyDevice(g_Device, g_Allocator);
|
|
vkDestroyInstance(g_Instance, g_Allocator);
|
|
}
|
|
|
|
static void CleanupVulkanWindow()
|
|
{
|
|
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
|
|
}
|
|
|
|
static void FrameRender(ImGui_ImplVulkanH_Window* wd, ImDrawData* draw_data)
|
|
{
|
|
VkResult err;
|
|
|
|
VkSemaphore image_acquired_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].ImageAcquiredSemaphore;
|
|
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
|
err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);
|
|
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
|
{
|
|
g_SwapChainRebuild = true;
|
|
return;
|
|
}
|
|
check_vk_result(err);
|
|
|
|
ImGui_ImplVulkanH_Frame* 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 = fd->Framebuffer;
|
|
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 dear imgui primitives into command buffer
|
|
ImGui_ImplVulkan_RenderDrawData(draw_data, fd->CommandBuffer);
|
|
|
|
// 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 = &render_complete_semaphore;
|
|
|
|
err = vkEndCommandBuffer(fd->CommandBuffer);
|
|
check_vk_result(err);
|
|
err = vkQueueSubmit(g_Queue, 1, &info, fd->Fence);
|
|
check_vk_result(err);
|
|
}
|
|
}
|
|
|
|
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
|
{
|
|
if (g_SwapChainRebuild)
|
|
return;
|
|
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
|
VkPresentInfoKHR info = {};
|
|
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
info.waitSemaphoreCount = 1;
|
|
info.pWaitSemaphores = &render_complete_semaphore;
|
|
info.swapchainCount = 1;
|
|
info.pSwapchains = &wd->Swapchain;
|
|
info.pImageIndices = &wd->FrameIndex;
|
|
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
|
if (err == VK_ERROR_OUT_OF_DATE_KHR || err == VK_SUBOPTIMAL_KHR)
|
|
{
|
|
g_SwapChainRebuild = true;
|
|
return;
|
|
}
|
|
check_vk_result(err);
|
|
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->SemaphoreCount; // Now we can use the next set of semaphores
|
|
}
|
|
|
|
// Main code
|
|
int main(int, char**)
|
|
{
|
|
glfwSetErrorCallback(glfw_error_callback);
|
|
if (!glfwInit())
|
|
return 1;
|
|
|
|
// Create window with Vulkan context
|
|
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
|
GLFWwindow* window = glfwCreateWindow(1280, 720, "Dear ImGui GLFW+Vulkan example", nullptr, nullptr);
|
|
if (!glfwVulkanSupported())
|
|
{
|
|
printf("GLFW: Vulkan Not Supported\n");
|
|
return 1;
|
|
}
|
|
|
|
ImVector<const char*> extensions;
|
|
uint32_t extensions_count = 0;
|
|
const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
|
|
for (uint32_t i = 0; i < extensions_count; i++)
|
|
extensions.push_back(glfw_extensions[i]);
|
|
SetupVulkan(extensions);
|
|
|
|
// Create Window Surface
|
|
VkSurfaceKHR surface;
|
|
VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &surface);
|
|
check_vk_result(err);
|
|
|
|
// Create Framebuffers
|
|
int w, h;
|
|
glfwGetFramebufferSize(window, &w, &h);
|
|
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
|
SetupVulkanWindow(wd, surface, w, h);
|
|
|
|
// Setup Dear ImGui context
|
|
IMGUI_CHECKVERSION();
|
|
ImGui::CreateContext();
|
|
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
|
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
|
|
|
|
// Setup Dear ImGui style
|
|
ImGui::StyleColorsDark();
|
|
//ImGui::StyleColorsLight();
|
|
|
|
// Setup Platform/Renderer backends
|
|
ImGui_ImplGlfw_InitForVulkan(window, true);
|
|
ImGui_ImplVulkan_InitInfo init_info = {};
|
|
init_info.Instance = g_Instance;
|
|
init_info.PhysicalDevice = g_PhysicalDevice;
|
|
init_info.Device = g_Device;
|
|
init_info.QueueFamily = g_QueueFamily;
|
|
init_info.Queue = g_Queue;
|
|
init_info.PipelineCache = g_PipelineCache;
|
|
init_info.DescriptorPool = g_DescriptorPool;
|
|
init_info.RenderPass = wd->RenderPass;
|
|
init_info.Subpass = 0;
|
|
init_info.MinImageCount = g_MinImageCount;
|
|
init_info.ImageCount = wd->ImageCount;
|
|
init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT;
|
|
init_info.Allocator = g_Allocator;
|
|
init_info.CheckVkResultFn = check_vk_result;
|
|
ImGui_ImplVulkan_Init(&init_info);
|
|
|
|
// Load Fonts
|
|
// - 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.
|
|
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
|
|
// - If the file cannot be loaded, the function will return a nullptr. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
|
|
// - 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.
|
|
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
|
|
// - Read 'docs/FONTS.md' for more instructions and details.
|
|
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
|
|
//io.Fonts->AddFontDefault();
|
|
//io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\segoeui.ttf", 18.0f);
|
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
|
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
|
|
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
|
|
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, nullptr, io.Fonts->GetGlyphRangesJapanese());
|
|
//IM_ASSERT(font != nullptr);
|
|
|
|
// Our state
|
|
bool show_demo_window = true;
|
|
bool show_another_window = false;
|
|
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
|
|
|
|
// Main loop
|
|
while (!glfwWindowShouldClose(window))
|
|
{
|
|
// Poll and handle events (inputs, window resize, etc.)
|
|
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
|
|
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application, or clear/overwrite your copy of the mouse data.
|
|
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application, or clear/overwrite your copy of the keyboard data.
|
|
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
|
glfwPollEvents();
|
|
|
|
// Resize swap chain?
|
|
if (g_SwapChainRebuild)
|
|
{
|
|
int width, height;
|
|
glfwGetFramebufferSize(window, &width, &height);
|
|
if (width > 0 && height > 0)
|
|
{
|
|
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
|
ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
|
g_MainWindowData.FrameIndex = 0;
|
|
g_SwapChainRebuild = false;
|
|
}
|
|
}
|
|
|
|
// Start the Dear ImGui frame
|
|
ImGui_ImplVulkan_NewFrame();
|
|
ImGui_ImplGlfw_NewFrame();
|
|
ImGui::NewFrame();
|
|
|
|
// 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!).
|
|
if (show_demo_window)
|
|
ImGui::ShowDemoWindow(&show_demo_window);
|
|
|
|
// 2. Show a simple window that we create ourselves. We use a Begin/End pair to create a named window.
|
|
{
|
|
static float f = 0.0f;
|
|
static int counter = 0;
|
|
|
|
ImGui::Begin("Hello, world!"); // Create a window called "Hello, world!" and append into it.
|
|
|
|
ImGui::Text("This is some useful text."); // Display some text (you can use a format strings too)
|
|
ImGui::Checkbox("Demo Window", &show_demo_window); // Edit bools storing our window open/close state
|
|
ImGui::Checkbox("Another Window", &show_another_window);
|
|
|
|
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
|
|
|
|
if (ImGui::Button("Button")) // Buttons return true when clicked (most widgets return true when edited/activated)
|
|
counter++;
|
|
ImGui::SameLine();
|
|
ImGui::Text("counter = %d", counter);
|
|
|
|
ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io.Framerate, io.Framerate);
|
|
ImGui::End();
|
|
}
|
|
|
|
// 3. Show another simple window.
|
|
if (show_another_window)
|
|
{
|
|
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)
|
|
ImGui::Text("Hello from another window!");
|
|
if (ImGui::Button("Close Me"))
|
|
show_another_window = false;
|
|
ImGui::End();
|
|
}
|
|
|
|
// Rendering
|
|
ImGui::Render();
|
|
ImDrawData* draw_data = ImGui::GetDrawData();
|
|
const bool is_minimized = (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f);
|
|
if (!is_minimized)
|
|
{
|
|
wd->ClearValue.color.float32[0] = clear_color.x * clear_color.w;
|
|
wd->ClearValue.color.float32[1] = clear_color.y * clear_color.w;
|
|
wd->ClearValue.color.float32[2] = clear_color.z * clear_color.w;
|
|
wd->ClearValue.color.float32[3] = clear_color.w;
|
|
FrameRender(wd, draw_data);
|
|
FramePresent(wd);
|
|
}
|
|
}
|
|
|
|
// Cleanup
|
|
err = vkDeviceWaitIdle(g_Device);
|
|
check_vk_result(err);
|
|
ImGui_ImplVulkan_Shutdown();
|
|
ImGui_ImplGlfw_Shutdown();
|
|
ImGui::DestroyContext();
|
|
|
|
CleanupVulkanWindow();
|
|
CleanupVulkan();
|
|
|
|
glfwDestroyWindow(window);
|
|
glfwTerminate();
|
|
|
|
return 0;
|
|
}
|