mirror of
https://github.com/ocornut/imgui.git
synced 2024-12-01 11:39:15 +08:00
Merge branch 'master' into docking
# Conflicts: # examples/imgui_impl_vulkan.cpp
This commit is contained in:
commit
50ceb25003
@ -98,6 +98,11 @@ Other changes:
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Breaking Changes:
|
||||
- Examples: Vulkan: Added MinImageCount/ImageCount fields in ImGui_ImplVulkan_InitInfo, required
|
||||
during initialization to specify the number of in-flight image requested by swap chains.
|
||||
(was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). (#2071, #1677) [@nathanvoglsam]
|
||||
- Examples: Vulkan: Tidying up the demo/internals helpers (most engine/app should not rely
|
||||
on them but it is possible you have!).
|
||||
|
||||
Other Changes:
|
||||
- InputText: Fixed selection background starts rendering one frame after the cursor movement
|
||||
@ -108,11 +113,15 @@ Other Changes:
|
||||
- GetMouseDragDelta(): also returns the delta on the mouse button released frame. (#2419)
|
||||
- GetMouseDragDelta(): verify that mouse positions are valid otherwise returns zero.
|
||||
- Inputs: Also add support for horizontal scroll with Shift+Mouse Wheel. (#2424, #1463) [@LucaRood]
|
||||
- Misc: Added IM_MALLOC/IM_FREE macros mimicking IM_NEW/IM_DELETE so user doesn't need to revert
|
||||
to using the ImGui::MemAlloc()/MemFree() calls directly.
|
||||
- Examples: OpenGL: Added a dummy GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized
|
||||
GL function loaders early, and help users understand what they are missing. (#2421)
|
||||
- Examples: OpenGL3: Minor tweaks + not calling glBindBuffer more than necessary in the render loop.
|
||||
- Examples: Vulkan: Fixed in-flight buffers issues when using multi-viewports. (#2461, #2348, #2378, #2097)
|
||||
- Examples: Vulkan: Added missing support for 32-bit indices (#define ImDrawIdx unsigned int).
|
||||
- Examples: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
|
||||
- Examples: Vulkan: Added ImGui_ImplVulkan_SetMinImageCount() to change min image count at runtime. (#2071) [@nathanvoglsam]
|
||||
- Examples: DirectX9: Fixed erroneous assert in ImGui_ImplDX9_InvalidateDeviceObjects(). (#2454)
|
||||
- Examples: GLUT: Fixed existing FreeGLUT example to work with regular GLUT. (#2465) [@andrewwillmott]
|
||||
- Examples: GLUT: Renamed imgui_impl_freeglut.cpp/.h to imgui_impl_glut.cpp/.h. (#2465) [@andrewwillmott]
|
||||
|
@ -219,29 +219,32 @@ Frequently Asked Question (FAQ)
|
||||
|
||||
**Where is the documentation?**
|
||||
|
||||
- The documentation is at the top of imgui.cpp + effectively imgui.h.
|
||||
- Example code is in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function. It covers most features of ImGui so you can read the code and call the function itself to see its output.
|
||||
- Standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder.
|
||||
- We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments associated to it.
|
||||
This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
|
||||
- Run the examples/ applications and explore them.
|
||||
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
||||
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
|
||||
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/ folder to explain how to integrate Dear ImGui with your own engine/application.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments associated to it.
|
||||
- We obviously needs better documentation! Consider contributing or becoming a [Patron](http://www.patreon.com/imgui) to promote this effort.
|
||||
|
||||
**Which version should I get?**
|
||||
|
||||
I occasionally tag [Releases](https://github.com/ocornut/imgui/releases) but it is generally safe and recommended to sync to master/latest. The library is fairly stable and regressions tend to be fixed fast when reported.
|
||||
|
||||
You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features in the `docking` branch. Several projects are using this branch and it is kept in sync with master regularly.
|
||||
You may also peak at the [Multi-Viewport](https://github.com/ocornut/imgui/issues/1542) and [Docking](https://github.com/ocornut/imgui/issues/2109) features in the `docking` branch. Many projects are using this branch and it is kept in sync with master regularly.
|
||||
|
||||
**Who uses Dear ImGui?**
|
||||
|
||||
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) pages for an (incomplete) list of games/software which are publicly known to use dear imgui. Please add yours if you can!
|
||||
See the [Quotes](https://github.com/ocornut/imgui/wiki/Quotes) and [Software using dear imgui](https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages for a list of games/software which are publicly known to use dear imgui. Please add yours if you can!
|
||||
|
||||
**Why the odd dual naming, "Dear ImGui" vs "ImGui"?**
|
||||
|
||||
The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would taker off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). It seemed confusing and unfair to hog the name. To reduce the ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library in ambiguous situations. Please try to refer to it as "Dear ImGui".
|
||||
The library started its life as "ImGui" due to the fact that I didn't give it a proper name when I released 1.0 and had no particular expectation that it would take off. However, the term IMGUI (immediate-mode graphical user interface) was coined before and is being used in variety of other situations (e.g. Unity uses it own implementation of the IMGUI paradigm). To reduce this ambiguity without affecting existing codebases, I have decided on an alternate, longer name "Dear ImGui" that people can use to refer to this specific library. Please try to refer to this library as "Dear ImGui".
|
||||
|
||||
**How can I tell whether to dispatch mouse/keyboard to imgui or to my application?**
|
||||
<br>**How can I display an image? What is ImTextureID, how does it works?**
|
||||
<br>**How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.**
|
||||
<br>**Why are multiple widgets reacting when I interact with a single one? How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...**
|
||||
<br>**How can I use my own math types instead of ImVec2/ImVec4?**
|
||||
<br>**How can I load a different font than the default?**
|
||||
<br>**How can I easily use icons in my application?**
|
||||
@ -254,7 +257,7 @@ The library started its life as "ImGui" due to the fact that I didn't give it a
|
||||
<br>**I integrated Dear ImGui in my engine and some elements are disappearing when I move windows around..**
|
||||
<br>**How can I help?**
|
||||
|
||||
See the FAQ in imgui.cpp for answers.
|
||||
See the FAQ in [imgui.cpp](https://github.com/ocornut/imgui/blob/master/imgui.cpp) for answers.
|
||||
|
||||
**Can you create elaborate/serious tools with Dear ImGui?**
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
https://github.com/ocornut/imgui/issues/2261
|
||||
|
||||
2. IF YOU ARE HAVING AN ISSUE COMPILING/LINKING/RUNNING/LOADING FONTS, please post on the "Getting Started" Discourse forum:
|
||||
https://discourse.dearimgui.org/c/getting-started
|
||||
https://discourse.dearimgui.org
|
||||
|
||||
3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of ShowDemoWindow() including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1).
|
||||
3. PLEASE MAKE SURE that you have: read the FAQ in imgui.cpp; explored the contents of `ShowDemoWindow()` including the Examples menu; searched among Issues; used your IDE to search for keywords in all sources and text files; and read the link provided in (1).
|
||||
|
||||
4. Be mindful that messages are being sent to the mailbox of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users, unless they browse the site.
|
||||
4. Be mindful that messages are being sent to the e-mail box of "Watching" users. Try to proof-read your messages before sending them. Edits are not seen by those users.
|
||||
|
||||
5. Delete points 1-5 and PLEASE FILL THE TEMPLATE BELOW before submitting your issue.
|
||||
|
||||
|
@ -1,6 +1,13 @@
|
||||
// dear imgui: standalone example application for Glfw + Vulkan
|
||||
// If you are new to dear imgui, see examples/README.txt and documentation 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 back-end in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the back-end 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"
|
||||
@ -23,19 +30,21 @@
|
||||
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||
#endif
|
||||
|
||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||
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 VkAllocationCallbacks* g_Allocator = NULL;
|
||||
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_WindowData g_WindowData;
|
||||
static bool g_ResizeWanted = false;
|
||||
static int g_ResizeWidth = 0, g_ResizeHeight = 0;
|
||||
static ImGui_ImplVulkanH_Window g_MainWindowData;
|
||||
static int g_MinImageCount = 2;
|
||||
static bool g_SwapChainRebuild = false;
|
||||
static int g_SwapChainResizeWidth = 0;
|
||||
static int g_SwapChainResizeHeight = 0;
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
@ -107,6 +116,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
uint32_t gpu_count;
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
||||
check_vk_result(err);
|
||||
IM_ASSERT(gpu_count > 0);
|
||||
|
||||
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
|
||||
@ -183,7 +193,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
}
|
||||
}
|
||||
|
||||
static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR surface, int width, int height)
|
||||
// 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;
|
||||
|
||||
@ -211,14 +223,12 @@ static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// 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, width, height);
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
{
|
||||
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
|
||||
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
|
||||
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||
|
||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||
@ -231,15 +241,21 @@ static void CleanupVulkan()
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
static void CleanupVulkanWindow()
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
|
||||
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);
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||
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);
|
||||
@ -260,7 +276,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = wd->RenderPass;
|
||||
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
|
||||
info.framebuffer = fd->Framebuffer;
|
||||
info.renderArea.extent.width = wd->Width;
|
||||
info.renderArea.extent.height = wd->Height;
|
||||
info.clearValueCount = 1;
|
||||
@ -283,7 +299,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
info.commandBufferCount = 1;
|
||||
info.pCommandBuffers = &fd->CommandBuffer;
|
||||
info.signalSemaphoreCount = 1;
|
||||
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
|
||||
info.pSignalSemaphores = &render_complete_semaphore;
|
||||
|
||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||
check_vk_result(err);
|
||||
@ -292,18 +308,19 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
}
|
||||
}
|
||||
|
||||
static void FramePresent(ImGui_ImplVulkanH_WindowData* wd)
|
||||
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkPresentInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
||||
info.pWaitSemaphores = &render_complete_semaphore;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
check_vk_result(err);
|
||||
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
|
||||
}
|
||||
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
@ -313,14 +330,14 @@ static void glfw_error_callback(int error, const char* description)
|
||||
|
||||
static void glfw_resize_callback(GLFWwindow*, int w, int h)
|
||||
{
|
||||
g_ResizeWanted = true;
|
||||
g_ResizeWidth = w;
|
||||
g_ResizeHeight = h;
|
||||
g_SwapChainRebuild = true;
|
||||
g_SwapChainResizeWidth = w;
|
||||
g_SwapChainResizeHeight = h;
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
// Setup window
|
||||
// Setup GLFW window
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
@ -347,8 +364,8 @@ int main(int, char**)
|
||||
int w, h;
|
||||
glfwGetFramebufferSize(window, &w, &h);
|
||||
glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
|
||||
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
|
||||
SetupVulkanWindowData(wd, surface, w, h);
|
||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||
SetupVulkanWindow(wd, surface, w, h);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
@ -384,6 +401,8 @@ int main(int, char**)
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
||||
|
||||
@ -429,7 +448,7 @@ int main(int, char**)
|
||||
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkan_InvalidateFontUploadObjects();
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
}
|
||||
|
||||
bool show_demo_window = true;
|
||||
@ -445,10 +464,13 @@ int main(int, char**)
|
||||
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
|
||||
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
|
||||
glfwPollEvents();
|
||||
if (g_ResizeWanted)
|
||||
|
||||
if (g_SwapChainRebuild)
|
||||
{
|
||||
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, g_ResizeWidth, g_ResizeHeight);
|
||||
g_ResizeWanted = false;
|
||||
g_SwapChainRebuild = false;
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
@ -514,6 +536,8 @@ int main(int, char**)
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow();
|
||||
CleanupVulkan();
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
|
@ -1,6 +1,13 @@
|
||||
// dear imgui: standalone example application for SDL2 + Vulkan
|
||||
// If you are new to dear imgui, see examples/README.txt and documentation 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 back-end in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the back-end 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_sdl.h"
|
||||
#include "imgui_impl_vulkan.h"
|
||||
@ -15,17 +22,21 @@
|
||||
#define IMGUI_VULKAN_DEBUG_REPORT
|
||||
#endif
|
||||
|
||||
static VkAllocationCallbacks* g_Allocator = NULL;
|
||||
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 VkAllocationCallbacks* g_Allocator = NULL;
|
||||
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_WindowData g_WindowData;
|
||||
static ImGui_ImplVulkanH_Window g_MainWindowData;
|
||||
static uint32_t g_MinImageCount = 2;
|
||||
static bool g_SwapChainRebuild = false;
|
||||
static int g_SwapChainResizeWidth = 0;
|
||||
static int g_SwapChainResizeHeight = 0;
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
@ -97,6 +108,7 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
uint32_t gpu_count;
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL);
|
||||
check_vk_result(err);
|
||||
IM_ASSERT(gpu_count > 0);
|
||||
|
||||
VkPhysicalDevice* gpus = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count);
|
||||
err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, gpus);
|
||||
@ -173,7 +185,9 @@ static void SetupVulkan(const char** extensions, uint32_t extensions_count)
|
||||
}
|
||||
}
|
||||
|
||||
static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR surface, int width, int height)
|
||||
// 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;
|
||||
|
||||
@ -201,14 +215,12 @@ static void SetupVulkanWindowData(ImGui_ImplVulkanH_WindowData* wd, VkSurfaceKHR
|
||||
//printf("[vulkan] Selected PresentMode = %d\n", wd->PresentMode);
|
||||
|
||||
// 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, width, height);
|
||||
IM_ASSERT(g_MinImageCount >= 2);
|
||||
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount);
|
||||
}
|
||||
|
||||
static void CleanupVulkan()
|
||||
{
|
||||
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
|
||||
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
|
||||
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
|
||||
|
||||
#ifdef IMGUI_VULKAN_DEBUG_REPORT
|
||||
@ -221,15 +233,21 @@ static void CleanupVulkan()
|
||||
vkDestroyInstance(g_Instance, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
static void CleanupVulkanWindow()
|
||||
{
|
||||
ImGui_ImplVulkanH_DestroyWindow(g_Instance, g_Device, &g_MainWindowData, g_Allocator);
|
||||
}
|
||||
|
||||
static void FrameRender(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
VkResult err;
|
||||
|
||||
VkSemaphore& image_acquired_semaphore = wd->Frames[wd->FrameIndex].ImageAcquiredSemaphore;
|
||||
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);
|
||||
check_vk_result(err);
|
||||
|
||||
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||
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);
|
||||
@ -250,7 +268,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
VkRenderPassBeginInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||
info.renderPass = wd->RenderPass;
|
||||
info.framebuffer = wd->Framebuffer[wd->FrameIndex];
|
||||
info.framebuffer = fd->Framebuffer;
|
||||
info.renderArea.extent.width = wd->Width;
|
||||
info.renderArea.extent.height = wd->Height;
|
||||
info.clearValueCount = 1;
|
||||
@ -273,7 +291,7 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
info.commandBufferCount = 1;
|
||||
info.pCommandBuffers = &fd->CommandBuffer;
|
||||
info.signalSemaphoreCount = 1;
|
||||
info.pSignalSemaphores = &fd->RenderCompleteSemaphore;
|
||||
info.pSignalSemaphores = &render_complete_semaphore;
|
||||
|
||||
err = vkEndCommandBuffer(fd->CommandBuffer);
|
||||
check_vk_result(err);
|
||||
@ -282,18 +300,19 @@ static void FrameRender(ImGui_ImplVulkanH_WindowData* wd)
|
||||
}
|
||||
}
|
||||
|
||||
static void FramePresent(ImGui_ImplVulkanH_WindowData* wd)
|
||||
static void FramePresent(ImGui_ImplVulkanH_Window* wd)
|
||||
{
|
||||
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[wd->FrameIndex];
|
||||
VkSemaphore render_complete_semaphore = wd->FrameSemaphores[wd->SemaphoreIndex].RenderCompleteSemaphore;
|
||||
VkPresentInfoKHR info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
||||
info.waitSemaphoreCount = 1;
|
||||
info.pWaitSemaphores = &fd->RenderCompleteSemaphore;
|
||||
info.pWaitSemaphores = &render_complete_semaphore;
|
||||
info.swapchainCount = 1;
|
||||
info.pSwapchains = &wd->Swapchain;
|
||||
info.pImageIndices = &wd->FrameIndex;
|
||||
VkResult err = vkQueuePresentKHR(g_Queue, &info);
|
||||
check_vk_result(err);
|
||||
wd->SemaphoreIndex = (wd->SemaphoreIndex + 1) % wd->ImageCount; // Now we can use the next set of semaphores
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
@ -331,8 +350,8 @@ int main(int, char**)
|
||||
// Create Framebuffers
|
||||
int w, h;
|
||||
SDL_GetWindowSize(window, &w, &h);
|
||||
ImGui_ImplVulkanH_WindowData* wd = &g_WindowData;
|
||||
SetupVulkanWindowData(wd, surface, w, h);
|
||||
ImGui_ImplVulkanH_Window* wd = &g_MainWindowData;
|
||||
SetupVulkanWindow(wd, surface, w, h);
|
||||
|
||||
// Setup Dear ImGui context
|
||||
ImGui::CreateContext();
|
||||
@ -366,6 +385,8 @@ int main(int, char**)
|
||||
init_info.PipelineCache = g_PipelineCache;
|
||||
init_info.DescriptorPool = g_DescriptorPool;
|
||||
init_info.Allocator = g_Allocator;
|
||||
init_info.MinImageCount = g_MinImageCount;
|
||||
init_info.ImageCount = wd->ImageCount;
|
||||
init_info.CheckVkResultFn = check_vk_result;
|
||||
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
|
||||
|
||||
@ -411,7 +432,7 @@ int main(int, char**)
|
||||
|
||||
err = vkDeviceWaitIdle(g_Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkan_InvalidateFontUploadObjects();
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
}
|
||||
|
||||
bool show_demo_window = true;
|
||||
@ -434,7 +455,19 @@ int main(int, char**)
|
||||
if (event.type == SDL_QUIT)
|
||||
done = true;
|
||||
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
|
||||
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
|
||||
{
|
||||
g_SwapChainResizeWidth = (int)event.window.data1;
|
||||
g_SwapChainResizeHeight = (int)event.window.data2;
|
||||
g_SwapChainRebuild = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_SwapChainRebuild)
|
||||
{
|
||||
g_SwapChainRebuild = false;
|
||||
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
|
||||
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
|
||||
g_MainWindowData.FrameIndex = 0;
|
||||
}
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
@ -500,6 +533,8 @@ int main(int, char**)
|
||||
ImGui_ImplVulkan_Shutdown();
|
||||
ImGui_ImplSDL2_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
CleanupVulkanWindow();
|
||||
CleanupVulkan();
|
||||
|
||||
SDL_DestroyWindow(window);
|
||||
|
@ -12,8 +12,17 @@
|
||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
||||
// 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 back-end in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
// CHANGELOG
|
||||
// (minor and older changes stripped away, please see git history for details)
|
||||
// 2019-XX-XX: *BREAKING CHANGE*: Vulkan: Added ImageCount/MinImageCount fields in ImGui_ImplVulkan_InitInfo, required for initialization (was previously a hard #define IMGUI_VK_QUEUED_FRAMES 2). Added ImGui_ImplVulkan_SetMinImageCount().
|
||||
// 2019-XX-XX: Vulkan: Added VkInstance argument to ImGui_ImplVulkanH_CreateWindow() optional helper.
|
||||
// 2019-04-04: Vulkan: Avoid passing negative coordinates to vkCmdSetScissor, which debug validation layers do not like.
|
||||
// 2019-04-01: Vulkan: Support for 32-bit index buffer (#define ImDrawIdx unsigned int).
|
||||
// 2019-02-16: Vulkan: Viewport and clipping rectangles correctly using draw_data->FramebufferScale to allow retina display.
|
||||
@ -35,46 +44,61 @@
|
||||
#include "imgui_impl_vulkan.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// Vulkan data
|
||||
static const VkAllocationCallbacks* g_Allocator = NULL;
|
||||
static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE;
|
||||
static VkInstance g_Instance = 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 VkPipelineCache g_PipelineCache = VK_NULL_HANDLE;
|
||||
static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE;
|
||||
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
|
||||
static void (*g_CheckVkResultFn)(VkResult err) = NULL;
|
||||
|
||||
static VkDeviceSize g_BufferMemoryAlignment = 256;
|
||||
static VkPipelineCreateFlags g_PipelineCreateFlags = 0;
|
||||
|
||||
static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE;
|
||||
static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE;
|
||||
static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE;
|
||||
static VkPipeline g_Pipeline = VK_NULL_HANDLE;
|
||||
|
||||
// Frame data
|
||||
struct FrameDataForRender
|
||||
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
|
||||
// [Please zero-clear before use!]
|
||||
struct ImGui_ImplVulkanH_FrameRenderBuffers
|
||||
{
|
||||
VkDeviceMemory VertexBufferMemory;
|
||||
VkDeviceMemory IndexBufferMemory;
|
||||
VkDeviceSize VertexBufferSize;
|
||||
VkDeviceSize IndexBufferSize;
|
||||
VkBuffer VertexBuffer;
|
||||
VkBuffer IndexBuffer;
|
||||
VkDeviceMemory VertexBufferMemory;
|
||||
VkDeviceMemory IndexBufferMemory;
|
||||
VkDeviceSize VertexBufferSize;
|
||||
VkDeviceSize IndexBufferSize;
|
||||
VkBuffer VertexBuffer;
|
||||
VkBuffer IndexBuffer;
|
||||
};
|
||||
static int g_FrameIndex = 0;
|
||||
static FrameDataForRender g_FramesDataBuffers[IMGUI_VK_QUEUED_FRAMES] = {};
|
||||
|
||||
// Each viewport will hold 1 ImGui_ImplVulkanH_WindowRenderBuffers
|
||||
// [Please zero-clear before use!]
|
||||
struct ImGui_ImplVulkanH_WindowRenderBuffers
|
||||
{
|
||||
uint32_t Index;
|
||||
uint32_t Count;
|
||||
ImGui_ImplVulkanH_FrameRenderBuffers* FrameRenderBuffers;
|
||||
};
|
||||
|
||||
// Vulkan data
|
||||
static ImGui_ImplVulkan_InitInfo g_VulkanInitInfo = {};
|
||||
static VkRenderPass g_RenderPass = VK_NULL_HANDLE;
|
||||
static VkDeviceSize g_BufferMemoryAlignment = 256;
|
||||
static VkPipelineCreateFlags g_PipelineCreateFlags = 0x00;
|
||||
static VkDescriptorSetLayout g_DescriptorSetLayout = VK_NULL_HANDLE;
|
||||
static VkPipelineLayout g_PipelineLayout = VK_NULL_HANDLE;
|
||||
static VkDescriptorSet g_DescriptorSet = VK_NULL_HANDLE;
|
||||
static VkPipeline g_Pipeline = VK_NULL_HANDLE;
|
||||
|
||||
// Font data
|
||||
static VkSampler g_FontSampler = VK_NULL_HANDLE;
|
||||
static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE;
|
||||
static VkImage g_FontImage = VK_NULL_HANDLE;
|
||||
static VkImageView g_FontView = VK_NULL_HANDLE;
|
||||
static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE;
|
||||
static VkBuffer g_UploadBuffer = VK_NULL_HANDLE;
|
||||
static VkSampler g_FontSampler = VK_NULL_HANDLE;
|
||||
static VkDeviceMemory g_FontMemory = VK_NULL_HANDLE;
|
||||
static VkImage g_FontImage = VK_NULL_HANDLE;
|
||||
static VkImageView g_FontView = VK_NULL_HANDLE;
|
||||
static VkDeviceMemory g_UploadBufferMemory = VK_NULL_HANDLE;
|
||||
static VkBuffer g_UploadBuffer = VK_NULL_HANDLE;
|
||||
|
||||
// Render buffers
|
||||
static ImGui_ImplVulkanH_WindowRenderBuffers g_MainWindowRenderBuffers;
|
||||
|
||||
// Forward Declarations
|
||||
bool ImGui_ImplVulkan_CreateDeviceObjects();
|
||||
void ImGui_ImplVulkan_DestroyDeviceObjects();
|
||||
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator);
|
||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
||||
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// SHADERS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Forward Declarations
|
||||
static void ImGui_ImplVulkan_InitPlatformInterface();
|
||||
@ -185,10 +209,15 @@ static uint32_t __glsl_shader_frag_spv[] =
|
||||
0x00010038
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// FUNCTIONS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
VkPhysicalDeviceMemoryProperties prop;
|
||||
vkGetPhysicalDeviceMemoryProperties(g_PhysicalDevice, &prop);
|
||||
vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop);
|
||||
for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
|
||||
if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<<i))
|
||||
return i;
|
||||
@ -197,17 +226,19 @@ static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, ui
|
||||
|
||||
static void check_vk_result(VkResult err)
|
||||
{
|
||||
if (g_CheckVkResultFn)
|
||||
g_CheckVkResultFn(err);
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
if (v->CheckVkResultFn)
|
||||
v->CheckVkResultFn(err);
|
||||
}
|
||||
|
||||
static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory, VkDeviceSize& p_buffer_size, size_t new_size, VkBufferUsageFlagBits usage)
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
VkResult err;
|
||||
if (buffer != VK_NULL_HANDLE)
|
||||
vkDestroyBuffer(g_Device, buffer, g_Allocator);
|
||||
if (buffer_memory)
|
||||
vkFreeMemory(g_Device, buffer_memory, g_Allocator);
|
||||
vkDestroyBuffer(v->Device, buffer, v->Allocator);
|
||||
if (buffer_memory != VK_NULL_HANDLE)
|
||||
vkFreeMemory(v->Device, buffer_memory, v->Allocator);
|
||||
|
||||
VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / g_BufferMemoryAlignment + 1) * g_BufferMemoryAlignment;
|
||||
VkBufferCreateInfo buffer_info = {};
|
||||
@ -215,20 +246,20 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
|
||||
buffer_info.size = vertex_buffer_size_aligned;
|
||||
buffer_info.usage = usage;
|
||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &buffer);
|
||||
err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &buffer);
|
||||
check_vk_result(err);
|
||||
|
||||
VkMemoryRequirements req;
|
||||
vkGetBufferMemoryRequirements(g_Device, buffer, &req);
|
||||
vkGetBufferMemoryRequirements(v->Device, buffer, &req);
|
||||
g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &buffer_memory);
|
||||
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &buffer_memory);
|
||||
check_vk_result(err);
|
||||
|
||||
err = vkBindBufferMemory(g_Device, buffer, buffer_memory, 0);
|
||||
err = vkBindBufferMemory(v->Device, buffer, buffer_memory, 0);
|
||||
check_vk_result(err);
|
||||
p_buffer_size = new_size;
|
||||
}
|
||||
@ -243,25 +274,38 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
if (fb_width <= 0 || fb_height <= 0 || draw_data->TotalVtxCount == 0)
|
||||
return;
|
||||
|
||||
VkResult err;
|
||||
FrameDataForRender* fd = &g_FramesDataBuffers[g_FrameIndex];
|
||||
g_FrameIndex = (g_FrameIndex + 1) % IM_ARRAYSIZE(g_FramesDataBuffers);
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
|
||||
// Create the Vertex and Index buffers:
|
||||
// Allocate array to store enough vertex/index buffers
|
||||
ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers;
|
||||
if (wrb->FrameRenderBuffers == NULL)
|
||||
{
|
||||
wrb->Index = 0;
|
||||
wrb->Count = v->ImageCount;
|
||||
wrb->FrameRenderBuffers = (ImGui_ImplVulkanH_FrameRenderBuffers*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
|
||||
memset(wrb->FrameRenderBuffers, 0, sizeof(ImGui_ImplVulkanH_FrameRenderBuffers) * wrb->Count);
|
||||
}
|
||||
IM_ASSERT(wrb->Count == v->ImageCount);
|
||||
wrb->Index = (wrb->Index + 1) % wrb->Count;
|
||||
ImGui_ImplVulkanH_FrameRenderBuffers* rb = &wrb->FrameRenderBuffers[wrb->Index];
|
||||
|
||||
VkResult err;
|
||||
|
||||
// Create or resize the vertex/index buffers
|
||||
size_t vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
size_t index_size = draw_data->TotalIdxCount * sizeof(ImDrawIdx);
|
||||
if (fd->VertexBuffer == VK_NULL_HANDLE || fd->VertexBufferSize < vertex_size)
|
||||
CreateOrResizeBuffer(fd->VertexBuffer, fd->VertexBufferMemory, fd->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
if (fd->IndexBuffer == VK_NULL_HANDLE || fd->IndexBufferSize < index_size)
|
||||
CreateOrResizeBuffer(fd->IndexBuffer, fd->IndexBufferMemory, fd->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
if (rb->VertexBuffer == VK_NULL_HANDLE || rb->VertexBufferSize < vertex_size)
|
||||
CreateOrResizeBuffer(rb->VertexBuffer, rb->VertexBufferMemory, rb->VertexBufferSize, vertex_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
|
||||
if (rb->IndexBuffer == VK_NULL_HANDLE || rb->IndexBufferSize < index_size)
|
||||
CreateOrResizeBuffer(rb->IndexBuffer, rb->IndexBufferMemory, rb->IndexBufferSize, index_size, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
|
||||
|
||||
// Upload vertex/index data into a single contiguous GPU buffer
|
||||
{
|
||||
ImDrawVert* vtx_dst = NULL;
|
||||
ImDrawIdx* idx_dst = NULL;
|
||||
err = vkMapMemory(g_Device, fd->VertexBufferMemory, 0, vertex_size, 0, (void**)(&vtx_dst));
|
||||
err = vkMapMemory(v->Device, rb->VertexBufferMemory, 0, vertex_size, 0, (void**)(&vtx_dst));
|
||||
check_vk_result(err);
|
||||
err = vkMapMemory(g_Device, fd->IndexBufferMemory, 0, index_size, 0, (void**)(&idx_dst));
|
||||
err = vkMapMemory(v->Device, rb->IndexBufferMemory, 0, index_size, 0, (void**)(&idx_dst));
|
||||
check_vk_result(err);
|
||||
for (int n = 0; n < draw_data->CmdListsCount; n++)
|
||||
{
|
||||
@ -273,15 +317,15 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
}
|
||||
VkMappedMemoryRange range[2] = {};
|
||||
range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
range[0].memory = fd->VertexBufferMemory;
|
||||
range[0].memory = rb->VertexBufferMemory;
|
||||
range[0].size = VK_WHOLE_SIZE;
|
||||
range[1].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
range[1].memory = fd->IndexBufferMemory;
|
||||
range[1].memory = rb->IndexBufferMemory;
|
||||
range[1].size = VK_WHOLE_SIZE;
|
||||
err = vkFlushMappedMemoryRanges(g_Device, 2, range);
|
||||
err = vkFlushMappedMemoryRanges(v->Device, 2, range);
|
||||
check_vk_result(err);
|
||||
vkUnmapMemory(g_Device, fd->VertexBufferMemory);
|
||||
vkUnmapMemory(g_Device, fd->IndexBufferMemory);
|
||||
vkUnmapMemory(v->Device, rb->VertexBufferMemory);
|
||||
vkUnmapMemory(v->Device, rb->IndexBufferMemory);
|
||||
}
|
||||
|
||||
// Bind pipeline and descriptor sets:
|
||||
@ -293,10 +337,10 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
|
||||
// Bind Vertex And Index Buffer:
|
||||
{
|
||||
VkBuffer vertex_buffers[1] = { fd->VertexBuffer };
|
||||
VkBuffer vertex_buffers[1] = { rb->VertexBuffer };
|
||||
VkDeviceSize vertex_offset[1] = { 0 };
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, vertex_offset);
|
||||
vkCmdBindIndexBuffer(command_buffer, fd->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);
|
||||
vkCmdBindIndexBuffer(command_buffer, rb->IndexBuffer, 0, sizeof(ImDrawIdx) == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
|
||||
// Setup viewport:
|
||||
@ -379,6 +423,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
|
||||
|
||||
bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
unsigned char* pixels;
|
||||
@ -404,17 +449,17 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
|
||||
info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
err = vkCreateImage(g_Device, &info, g_Allocator, &g_FontImage);
|
||||
err = vkCreateImage(v->Device, &info, v->Allocator, &g_FontImage);
|
||||
check_vk_result(err);
|
||||
VkMemoryRequirements req;
|
||||
vkGetImageMemoryRequirements(g_Device, g_FontImage, &req);
|
||||
vkGetImageMemoryRequirements(v->Device, g_FontImage, &req);
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_FontMemory);
|
||||
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_FontMemory);
|
||||
check_vk_result(err);
|
||||
err = vkBindImageMemory(g_Device, g_FontImage, g_FontMemory, 0);
|
||||
err = vkBindImageMemory(v->Device, g_FontImage, g_FontMemory, 0);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -428,7 +473,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
info.subresourceRange.levelCount = 1;
|
||||
info.subresourceRange.layerCount = 1;
|
||||
err = vkCreateImageView(g_Device, &info, g_Allocator, &g_FontView);
|
||||
err = vkCreateImageView(v->Device, &info, v->Allocator, &g_FontView);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -444,7 +489,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
write_desc[0].descriptorCount = 1;
|
||||
write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
write_desc[0].pImageInfo = desc_image;
|
||||
vkUpdateDescriptorSets(g_Device, 1, write_desc, 0, NULL);
|
||||
vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
|
||||
}
|
||||
|
||||
// Create the Upload Buffer:
|
||||
@ -454,34 +499,34 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
buffer_info.size = upload_size;
|
||||
buffer_info.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
err = vkCreateBuffer(g_Device, &buffer_info, g_Allocator, &g_UploadBuffer);
|
||||
err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &g_UploadBuffer);
|
||||
check_vk_result(err);
|
||||
VkMemoryRequirements req;
|
||||
vkGetBufferMemoryRequirements(g_Device, g_UploadBuffer, &req);
|
||||
vkGetBufferMemoryRequirements(v->Device, g_UploadBuffer, &req);
|
||||
g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
|
||||
VkMemoryAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
alloc_info.allocationSize = req.size;
|
||||
alloc_info.memoryTypeIndex = ImGui_ImplVulkan_MemoryType(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, req.memoryTypeBits);
|
||||
err = vkAllocateMemory(g_Device, &alloc_info, g_Allocator, &g_UploadBufferMemory);
|
||||
err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &g_UploadBufferMemory);
|
||||
check_vk_result(err);
|
||||
err = vkBindBufferMemory(g_Device, g_UploadBuffer, g_UploadBufferMemory, 0);
|
||||
err = vkBindBufferMemory(v->Device, g_UploadBuffer, g_UploadBufferMemory, 0);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
// Upload to Buffer:
|
||||
{
|
||||
char* map = NULL;
|
||||
err = vkMapMemory(g_Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
|
||||
err = vkMapMemory(v->Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
|
||||
check_vk_result(err);
|
||||
memcpy(map, pixels, upload_size);
|
||||
VkMappedMemoryRange range[1] = {};
|
||||
range[0].sType = VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE;
|
||||
range[0].memory = g_UploadBufferMemory;
|
||||
range[0].size = upload_size;
|
||||
err = vkFlushMappedMemoryRanges(g_Device, 1, range);
|
||||
err = vkFlushMappedMemoryRanges(v->Device, 1, range);
|
||||
check_vk_result(err);
|
||||
vkUnmapMemory(g_Device, g_UploadBufferMemory);
|
||||
vkUnmapMemory(v->Device, g_UploadBufferMemory);
|
||||
}
|
||||
|
||||
// Copy to Image:
|
||||
@ -530,6 +575,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
|
||||
|
||||
bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
VkResult err;
|
||||
VkShaderModule vert_module;
|
||||
VkShaderModule frag_module;
|
||||
@ -540,13 +586,13 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
vert_info.codeSize = sizeof(__glsl_shader_vert_spv);
|
||||
vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv;
|
||||
err = vkCreateShaderModule(g_Device, &vert_info, g_Allocator, &vert_module);
|
||||
err = vkCreateShaderModule(v->Device, &vert_info, v->Allocator, &vert_module);
|
||||
check_vk_result(err);
|
||||
VkShaderModuleCreateInfo frag_info = {};
|
||||
frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
frag_info.codeSize = sizeof(__glsl_shader_frag_spv);
|
||||
frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv;
|
||||
err = vkCreateShaderModule(g_Device, &frag_info, g_Allocator, &frag_module);
|
||||
err = vkCreateShaderModule(v->Device, &frag_info, v->Allocator, &frag_module);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -563,7 +609,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
info.minLod = -1000;
|
||||
info.maxLod = 1000;
|
||||
info.maxAnisotropy = 1.0f;
|
||||
err = vkCreateSampler(g_Device, &info, g_Allocator, &g_FontSampler);
|
||||
err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -579,7 +625,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
info.bindingCount = 1;
|
||||
info.pBindings = binding;
|
||||
err = vkCreateDescriptorSetLayout(g_Device, &info, g_Allocator, &g_DescriptorSetLayout);
|
||||
err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -587,10 +633,10 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
{
|
||||
VkDescriptorSetAllocateInfo alloc_info = {};
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
alloc_info.descriptorPool = g_DescriptorPool;
|
||||
alloc_info.descriptorPool = v->DescriptorPool;
|
||||
alloc_info.descriptorSetCount = 1;
|
||||
alloc_info.pSetLayouts = &g_DescriptorSetLayout;
|
||||
err = vkAllocateDescriptorSets(g_Device, &alloc_info, &g_DescriptorSet);
|
||||
err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -608,7 +654,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
layout_info.pSetLayouts = set_layout;
|
||||
layout_info.pushConstantRangeCount = 1;
|
||||
layout_info.pPushConstantRanges = push_constants;
|
||||
err = vkCreatePipelineLayout(g_Device, &layout_info, g_Allocator, &g_PipelineLayout);
|
||||
err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout);
|
||||
check_vk_result(err);
|
||||
}
|
||||
|
||||
@ -706,49 +752,43 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
|
||||
info.pDynamicState = &dynamic_state;
|
||||
info.layout = g_PipelineLayout;
|
||||
info.renderPass = g_RenderPass;
|
||||
err = vkCreateGraphicsPipelines(g_Device, g_PipelineCache, 1, &info, g_Allocator, &g_Pipeline);
|
||||
err = vkCreateGraphicsPipelines(v->Device, v->PipelineCache, 1, &info, v->Allocator, &g_Pipeline);
|
||||
check_vk_result(err);
|
||||
|
||||
vkDestroyShaderModule(g_Device, vert_module, g_Allocator);
|
||||
vkDestroyShaderModule(g_Device, frag_module, g_Allocator);
|
||||
vkDestroyShaderModule(v->Device, vert_module, v->Allocator);
|
||||
vkDestroyShaderModule(v->Device, frag_module, v->Allocator);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_InvalidateFontUploadObjects()
|
||||
void ImGui_ImplVulkan_DestroyFontUploadObjects()
|
||||
{
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
if (g_UploadBuffer)
|
||||
{
|
||||
vkDestroyBuffer(g_Device, g_UploadBuffer, g_Allocator);
|
||||
vkDestroyBuffer(v->Device, g_UploadBuffer, v->Allocator);
|
||||
g_UploadBuffer = VK_NULL_HANDLE;
|
||||
}
|
||||
if (g_UploadBufferMemory)
|
||||
{
|
||||
vkFreeMemory(g_Device, g_UploadBufferMemory, g_Allocator);
|
||||
vkFreeMemory(v->Device, g_UploadBufferMemory, v->Allocator);
|
||||
g_UploadBufferMemory = VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_InvalidateDeviceObjects()
|
||||
void ImGui_ImplVulkan_DestroyDeviceObjects()
|
||||
{
|
||||
ImGui_ImplVulkan_InvalidateFontUploadObjects();
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
|
||||
ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
|
||||
for (int i = 0; i < IM_ARRAYSIZE(g_FramesDataBuffers); i++)
|
||||
{
|
||||
FrameDataForRender* fd = &g_FramesDataBuffers[i];
|
||||
if (fd->VertexBuffer) { vkDestroyBuffer (g_Device, fd->VertexBuffer, g_Allocator); fd->VertexBuffer = VK_NULL_HANDLE; }
|
||||
if (fd->VertexBufferMemory) { vkFreeMemory (g_Device, fd->VertexBufferMemory, g_Allocator); fd->VertexBufferMemory = VK_NULL_HANDLE; }
|
||||
if (fd->IndexBuffer) { vkDestroyBuffer (g_Device, fd->IndexBuffer, g_Allocator); fd->IndexBuffer = VK_NULL_HANDLE; }
|
||||
if (fd->IndexBufferMemory) { vkFreeMemory (g_Device, fd->IndexBufferMemory, g_Allocator); fd->IndexBufferMemory = VK_NULL_HANDLE; }
|
||||
}
|
||||
|
||||
if (g_FontView) { vkDestroyImageView(g_Device, g_FontView, g_Allocator); g_FontView = VK_NULL_HANDLE; }
|
||||
if (g_FontImage) { vkDestroyImage(g_Device, g_FontImage, g_Allocator); g_FontImage = VK_NULL_HANDLE; }
|
||||
if (g_FontMemory) { vkFreeMemory(g_Device, g_FontMemory, g_Allocator); g_FontMemory = VK_NULL_HANDLE; }
|
||||
if (g_FontSampler) { vkDestroySampler(g_Device, g_FontSampler, g_Allocator); g_FontSampler = VK_NULL_HANDLE; }
|
||||
if (g_DescriptorSetLayout) { vkDestroyDescriptorSetLayout(g_Device, g_DescriptorSetLayout, g_Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; }
|
||||
if (g_PipelineLayout) { vkDestroyPipelineLayout(g_Device, g_PipelineLayout, g_Allocator); g_PipelineLayout = VK_NULL_HANDLE; }
|
||||
if (g_Pipeline) { vkDestroyPipeline(g_Device, g_Pipeline, g_Allocator); g_Pipeline = VK_NULL_HANDLE; }
|
||||
if (g_FontView) { vkDestroyImageView(v->Device, g_FontView, v->Allocator); g_FontView = VK_NULL_HANDLE; }
|
||||
if (g_FontImage) { vkDestroyImage(v->Device, g_FontImage, v->Allocator); g_FontImage = VK_NULL_HANDLE; }
|
||||
if (g_FontMemory) { vkFreeMemory(v->Device, g_FontMemory, v->Allocator); g_FontMemory = VK_NULL_HANDLE; }
|
||||
if (g_FontSampler) { vkDestroySampler(v->Device, g_FontSampler, v->Allocator); g_FontSampler = VK_NULL_HANDLE; }
|
||||
if (g_DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, g_DescriptorSetLayout, v->Allocator); g_DescriptorSetLayout = VK_NULL_HANDLE; }
|
||||
if (g_PipelineLayout) { vkDestroyPipelineLayout(v->Device, g_PipelineLayout, v->Allocator); g_PipelineLayout = VK_NULL_HANDLE; }
|
||||
if (g_Pipeline) { vkDestroyPipeline(v->Device, g_Pipeline, v->Allocator); g_Pipeline = VK_NULL_HANDLE; }
|
||||
}
|
||||
|
||||
bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass render_pass)
|
||||
@ -763,19 +803,12 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
|
||||
IM_ASSERT(info->Device != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->Queue != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE);
|
||||
IM_ASSERT(info->MinImageCount >= 2);
|
||||
IM_ASSERT(info->ImageCount >= info->MinImageCount);
|
||||
IM_ASSERT(render_pass != VK_NULL_HANDLE);
|
||||
|
||||
g_Instance = info->Instance;
|
||||
g_PhysicalDevice = info->PhysicalDevice;
|
||||
g_Device = info->Device;
|
||||
g_QueueFamily = info->QueueFamily;
|
||||
g_Queue = info->Queue;
|
||||
g_VulkanInitInfo = *info;
|
||||
g_RenderPass = render_pass;
|
||||
g_PipelineCache = info->PipelineCache;
|
||||
g_DescriptorPool = info->DescriptorPool;
|
||||
g_Allocator = info->Allocator;
|
||||
g_CheckVkResultFn = info->CheckVkResultFn;
|
||||
|
||||
ImGui_ImplVulkan_CreateDeviceObjects();
|
||||
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
@ -787,16 +820,30 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
|
||||
void ImGui_ImplVulkan_Shutdown()
|
||||
{
|
||||
ImGui_ImplVulkan_ShutdownPlatformInterface();
|
||||
ImGui_ImplVulkan_InvalidateDeviceObjects();
|
||||
ImGui_ImplVulkan_DestroyDeviceObjects();
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_NewFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
|
||||
{
|
||||
IM_ASSERT(min_image_count >= 2);
|
||||
if (g_VulkanInitInfo.MinImageCount == min_image_count)
|
||||
return;
|
||||
|
||||
ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
|
||||
VkResult err = vkDeviceWaitIdle(v->Device);
|
||||
check_vk_result(err);
|
||||
ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
|
||||
g_VulkanInitInfo.MinImageCount = min_image_count;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own app.)
|
||||
//-------------------------------------------------------------------------
|
||||
// You probably do NOT need to use or care about those functions.
|
||||
// Those functions only exist because:
|
||||
@ -804,40 +851,12 @@ void ImGui_ImplVulkan_NewFrame()
|
||||
// 2) the upcoming multi-viewport feature will need them internally.
|
||||
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
|
||||
// but it is too much code to duplicate everywhere so we exceptionally expose them.
|
||||
// Your application/engine will likely already have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
//
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
|
||||
// (those functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
|
||||
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h> // malloc
|
||||
|
||||
ImGui_ImplVulkanH_FrameData::ImGui_ImplVulkanH_FrameData()
|
||||
{
|
||||
BackbufferIndex = 0;
|
||||
CommandPool = VK_NULL_HANDLE;
|
||||
CommandBuffer = VK_NULL_HANDLE;
|
||||
Fence = VK_NULL_HANDLE;
|
||||
ImageAcquiredSemaphore = VK_NULL_HANDLE;
|
||||
RenderCompleteSemaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
ImGui_ImplVulkanH_WindowData::ImGui_ImplVulkanH_WindowData()
|
||||
{
|
||||
Width = Height = 0;
|
||||
Swapchain = VK_NULL_HANDLE;
|
||||
Surface = VK_NULL_HANDLE;
|
||||
memset(&SurfaceFormat, 0, sizeof(SurfaceFormat));
|
||||
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
|
||||
RenderPass = VK_NULL_HANDLE;
|
||||
ClearEnable = true;
|
||||
memset(&ClearValue, 0, sizeof(ClearValue));
|
||||
BackBufferCount = 0;
|
||||
memset(&BackBuffer, 0, sizeof(BackBuffer));
|
||||
memset(&BackBufferView, 0, sizeof(BackBufferView));
|
||||
memset(&Framebuffer, 0, sizeof(Framebuffer));
|
||||
FrameIndex = 0;
|
||||
}
|
||||
|
||||
VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space)
|
||||
{
|
||||
IM_ASSERT(request_formats != NULL);
|
||||
@ -904,7 +923,7 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d
|
||||
return VK_PRESENT_MODE_FIFO_KHR; // Always available
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator)
|
||||
void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
IM_ASSERT(physical_device != VK_NULL_HANDLE && device != VK_NULL_HANDLE);
|
||||
(void)physical_device;
|
||||
@ -912,9 +931,10 @@ void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_
|
||||
|
||||
// Create Command Buffers
|
||||
VkResult err;
|
||||
for (int i = 0; i < IM_ARRAYSIZE(wd->Frames); i++)
|
||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||
{
|
||||
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[i];
|
||||
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
|
||||
ImGui_ImplVulkanH_FrameSemaphores* fsd = &wd->FrameSemaphores[i];
|
||||
{
|
||||
VkCommandPoolCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
||||
@ -942,9 +962,9 @@ void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_
|
||||
{
|
||||
VkSemaphoreCreateInfo info = {};
|
||||
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
err = vkCreateSemaphore(device, &info, allocator, &fd->ImageAcquiredSemaphore);
|
||||
err = vkCreateSemaphore(device, &info, allocator, &fsd->ImageAcquiredSemaphore);
|
||||
check_vk_result(err);
|
||||
err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore);
|
||||
err = vkCreateSemaphore(device, &info, allocator, &fsd->RenderCompleteSemaphore);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
@ -962,24 +982,26 @@ int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_m
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h)
|
||||
// Also destroy old swap chain and in-flight frames data, if any.
|
||||
void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count)
|
||||
{
|
||||
uint32_t min_image_count = 2; // FIXME: this should become a function parameter
|
||||
|
||||
VkResult err;
|
||||
VkSwapchainKHR old_swapchain = wd->Swapchain;
|
||||
err = vkDeviceWaitIdle(device);
|
||||
check_vk_result(err);
|
||||
|
||||
// We don't use ImGui_ImplVulkanH_DestroyWindow() because we want to preserve the old swapchain to create the new one.
|
||||
// Destroy old Framebuffer
|
||||
for (uint32_t i = 0; i < wd->BackBufferCount; i++)
|
||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||
{
|
||||
if (wd->BackBufferView[i])
|
||||
vkDestroyImageView(device, wd->BackBufferView[i], allocator);
|
||||
if (wd->Framebuffer[i])
|
||||
vkDestroyFramebuffer(device, wd->Framebuffer[i], allocator);
|
||||
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
|
||||
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
|
||||
}
|
||||
wd->BackBufferCount = 0;
|
||||
IM_FREE(wd->Frames);
|
||||
IM_FREE(wd->FrameSemaphores);
|
||||
wd->Frames = NULL;
|
||||
wd->FrameSemaphores = NULL;
|
||||
wd->ImageCount = 0;
|
||||
if (wd->RenderPass)
|
||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||
|
||||
@ -1023,10 +1045,21 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
|
||||
}
|
||||
err = vkCreateSwapchainKHR(device, &info, allocator, &wd->Swapchain);
|
||||
check_vk_result(err);
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->BackBufferCount, NULL);
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, NULL);
|
||||
check_vk_result(err);
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->BackBufferCount, wd->BackBuffer);
|
||||
VkImage backbuffers[16] = {};
|
||||
IM_ASSERT(wd->ImageCount >= min_image_count);
|
||||
IM_ASSERT(wd->ImageCount < IM_ARRAYSIZE(backbuffers));
|
||||
err = vkGetSwapchainImagesKHR(device, wd->Swapchain, &wd->ImageCount, backbuffers);
|
||||
check_vk_result(err);
|
||||
|
||||
IM_ASSERT(wd->Frames == NULL);
|
||||
wd->Frames = (ImGui_ImplVulkanH_Frame*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_Frame) * wd->ImageCount);
|
||||
wd->FrameSemaphores = (ImGui_ImplVulkanH_FrameSemaphores*)IM_ALLOC(sizeof(ImGui_ImplVulkanH_FrameSemaphores) * wd->ImageCount);
|
||||
memset(wd->Frames, 0, sizeof(wd->Frames[0]) * wd->ImageCount);
|
||||
memset(wd->FrameSemaphores, 0, sizeof(wd->FrameSemaphores[0]) * wd->ImageCount);
|
||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||
wd->Frames[i].Backbuffer = backbuffers[i];
|
||||
}
|
||||
if (old_swapchain)
|
||||
vkDestroySwapchainKHR(device, old_swapchain, allocator);
|
||||
@ -1080,10 +1113,11 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
|
||||
info.components.a = VK_COMPONENT_SWIZZLE_A;
|
||||
VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
||||
info.subresourceRange = image_range;
|
||||
for (uint32_t i = 0; i < wd->BackBufferCount; i++)
|
||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||
{
|
||||
info.image = wd->BackBuffer[i];
|
||||
err = vkCreateImageView(device, &info, allocator, &wd->BackBufferView[i]);
|
||||
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
|
||||
info.image = fd->Backbuffer;
|
||||
err = vkCreateImageView(device, &info, allocator, &fd->BackbufferView);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
@ -1099,38 +1133,82 @@ void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice
|
||||
info.width = wd->Width;
|
||||
info.height = wd->Height;
|
||||
info.layers = 1;
|
||||
for (uint32_t i = 0; i < wd->BackBufferCount; i++)
|
||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||
{
|
||||
attachment[0] = wd->BackBufferView[i];
|
||||
err = vkCreateFramebuffer(device, &info, allocator, &wd->Framebuffer[i]);
|
||||
ImGui_ImplVulkanH_Frame* fd = &wd->Frames[i];
|
||||
attachment[0] = fd->BackbufferView;
|
||||
err = vkCreateFramebuffer(device, &info, allocator, &fd->Framebuffer);
|
||||
check_vk_result(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator)
|
||||
void ImGui_ImplVulkanH_CreateWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count)
|
||||
{
|
||||
(void)instance;
|
||||
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
|
||||
ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
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 < IM_ARRAYSIZE(wd->Frames); i++)
|
||||
for (uint32_t i = 0; i < wd->ImageCount; i++)
|
||||
{
|
||||
ImGui_ImplVulkanH_FrameData* fd = &wd->Frames[i];
|
||||
vkDestroyFence(device, fd->Fence, allocator);
|
||||
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
|
||||
vkDestroyCommandPool(device, fd->CommandPool, allocator);
|
||||
vkDestroySemaphore(device, fd->ImageAcquiredSemaphore, allocator);
|
||||
vkDestroySemaphore(device, fd->RenderCompleteSemaphore, allocator);
|
||||
}
|
||||
for (uint32_t i = 0; i < wd->BackBufferCount; i++)
|
||||
{
|
||||
vkDestroyImageView(device, wd->BackBufferView[i], allocator);
|
||||
vkDestroyFramebuffer(device, wd->Framebuffer[i], allocator);
|
||||
ImGui_ImplVulkanH_DestroyFrame(device, &wd->Frames[i], allocator);
|
||||
ImGui_ImplVulkanH_DestroyFrameSemaphores(device, &wd->FrameSemaphores[i], allocator);
|
||||
}
|
||||
IM_FREE(wd->Frames);
|
||||
IM_FREE(wd->FrameSemaphores);
|
||||
wd->Frames = NULL;
|
||||
wd->FrameSemaphores = NULL;
|
||||
vkDestroyRenderPass(device, wd->RenderPass, allocator);
|
||||
vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
|
||||
vkDestroySurfaceKHR(instance, wd->Surface, allocator);
|
||||
*wd = ImGui_ImplVulkanH_WindowData();
|
||||
|
||||
*wd = ImGui_ImplVulkanH_Window();
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
vkDestroyFence(device, fd->Fence, allocator);
|
||||
vkFreeCommandBuffers(device, fd->CommandPool, 1, &fd->CommandBuffer);
|
||||
vkDestroyCommandPool(device, fd->CommandPool, allocator);
|
||||
fd->Fence = VK_NULL_HANDLE;
|
||||
fd->CommandBuffer = VK_NULL_HANDLE;
|
||||
fd->CommandPool = VK_NULL_HANDLE;
|
||||
|
||||
vkDestroyImageView(device, fd->BackbufferView, allocator);
|
||||
vkDestroyFramebuffer(device, fd->Framebuffer, allocator);
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
vkDestroySemaphore(device, fsd->ImageAcquiredSemaphore, allocator);
|
||||
vkDestroySemaphore(device, fsd->RenderCompleteSemaphore, allocator);
|
||||
fsd->ImageAcquiredSemaphore = fsd->RenderCompleteSemaphore = VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulkanH_FrameRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
if (buffers->VertexBuffer) { vkDestroyBuffer(device, buffers->VertexBuffer, allocator); buffers->VertexBuffer = VK_NULL_HANDLE; }
|
||||
if (buffers->VertexBufferMemory) { vkFreeMemory(device, buffers->VertexBufferMemory, allocator); buffers->VertexBufferMemory = VK_NULL_HANDLE; }
|
||||
if (buffers->IndexBuffer) { vkDestroyBuffer(device, buffers->IndexBuffer, allocator); buffers->IndexBuffer = VK_NULL_HANDLE; }
|
||||
if (buffers->IndexBufferMemory) { vkFreeMemory(device, buffers->IndexBufferMemory, allocator); buffers->IndexBufferMemory = VK_NULL_HANDLE; }
|
||||
buffers->VertexBufferSize = 0;
|
||||
buffers->IndexBufferSize = 0;
|
||||
}
|
||||
|
||||
void ImGui_ImplVulkanH_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkanH_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator)
|
||||
{
|
||||
for (uint32_t n = 0; n < buffers->Count; n++)
|
||||
ImGui_ImplVulkanH_DestroyFrameRenderBuffers(device, &buffers->FrameRenderBuffers[n], allocator);
|
||||
IM_FREE(buffers->FrameRenderBuffers);
|
||||
buffers->FrameRenderBuffers = NULL;
|
||||
buffers->Index = 0;
|
||||
buffers->Count = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
|
@ -12,24 +12,32 @@
|
||||
// The aim of imgui_impl_vulkan.h/.cpp is to be usable in your engine without any modification.
|
||||
// IF YOU FEEL YOU NEED TO MAKE ANY CHANGE TO THIS CODE, please share them and your feedback at https://github.com/ocornut/imgui/
|
||||
|
||||
// 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 back-end in your engine/app.
|
||||
// - Helper ImGui_ImplVulkanH_XXX functions and structures are only used by this example (main.cpp) and by
|
||||
// the back-end itself (imgui_impl_vulkan.cpp), but should PROBABLY NOT be used by your own engine/app code.
|
||||
// Read comments in imgui_impl_vulkan.h.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#define IMGUI_VK_QUEUED_FRAMES 2
|
||||
|
||||
// Please zero-clear before use.
|
||||
// Initialization data, for ImGui_ImplVulkan_Init()
|
||||
// [Please zero-clear before use!]
|
||||
struct ImGui_ImplVulkan_InitInfo
|
||||
{
|
||||
VkInstance Instance;
|
||||
VkPhysicalDevice PhysicalDevice;
|
||||
VkDevice Device;
|
||||
uint32_t QueueFamily;
|
||||
VkQueue Queue;
|
||||
VkPipelineCache PipelineCache;
|
||||
VkDescriptorPool DescriptorPool;
|
||||
const VkAllocationCallbacks* Allocator;
|
||||
void (*CheckVkResultFn)(VkResult err);
|
||||
VkInstance Instance;
|
||||
VkPhysicalDevice PhysicalDevice;
|
||||
VkDevice Device;
|
||||
uint32_t QueueFamily;
|
||||
VkQueue Queue;
|
||||
VkPipelineCache PipelineCache;
|
||||
VkDescriptorPool DescriptorPool;
|
||||
uint32_t MinImageCount; // >= 2
|
||||
uint32_t ImageCount; // >= MinImageCount
|
||||
const VkAllocationCallbacks* Allocator;
|
||||
void (*CheckVkResultFn)(VkResult err);
|
||||
};
|
||||
|
||||
// Called by user code
|
||||
@ -38,16 +46,13 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer);
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateFontUploadObjects();
|
||||
|
||||
// Called by ImGui_ImplVulkan_Init() might be useful elsewhere.
|
||||
IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontUploadObjects();
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated)
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Internal / Miscellaneous Vulkan Helpers
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own app.)
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. PROBABLY NOT used by your own engine/app.)
|
||||
//-------------------------------------------------------------------------
|
||||
// You probably do NOT need to use or care about those functions.
|
||||
// Those functions only exist because:
|
||||
@ -55,38 +60,44 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_InvalidateDeviceObjects();
|
||||
// 2) the multi-viewport / platform window implementation needs them internally.
|
||||
// Generally we avoid exposing any kind of superfluous high-level helpers in the bindings,
|
||||
// but it is too much code to duplicate everywhere so we exceptionally expose them.
|
||||
// Your application/engine will likely already have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
//
|
||||
// Your engine/app will likely _already_ have code to setup all that stuff (swap chain, render pass, frame buffers, etc.).
|
||||
// You may read this code to learn about Vulkan, but it is recommended you use you own custom tailored code to do equivalent work.
|
||||
// (those functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
|
||||
// (The ImGui_ImplVulkanH_XXX functions do not interact with any of the state used by the regular ImGui_ImplVulkan_XXX functions)
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
struct ImGui_ImplVulkanH_FrameData;
|
||||
struct ImGui_ImplVulkanH_WindowData;
|
||||
struct ImGui_ImplVulkanH_Frame;
|
||||
struct ImGui_ImplVulkanH_Window;
|
||||
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_WindowData* wd, const VkAllocationCallbacks* allocator);
|
||||
// Helpers
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count);
|
||||
IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator);
|
||||
IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
|
||||
IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
|
||||
IMGUI_IMPL_API int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_mode);
|
||||
|
||||
// Helper structure to hold the data needed by one rendering frame
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own app.)
|
||||
struct ImGui_ImplVulkanH_FrameData
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
|
||||
// [Please zero-clear before use!]
|
||||
struct ImGui_ImplVulkanH_Frame
|
||||
{
|
||||
uint32_t BackbufferIndex; // Keep track of recently rendered swapchain frame indices
|
||||
VkCommandPool CommandPool;
|
||||
VkCommandBuffer CommandBuffer;
|
||||
VkFence Fence;
|
||||
VkImage Backbuffer;
|
||||
VkImageView BackbufferView;
|
||||
VkFramebuffer Framebuffer;
|
||||
};
|
||||
|
||||
struct ImGui_ImplVulkanH_FrameSemaphores
|
||||
{
|
||||
VkSemaphore ImageAcquiredSemaphore;
|
||||
VkSemaphore RenderCompleteSemaphore;
|
||||
|
||||
IMGUI_IMPL_API ImGui_ImplVulkanH_FrameData();
|
||||
};
|
||||
|
||||
// Helper structure to hold the data needed by one rendering context into one OS window
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own app.)
|
||||
struct ImGui_ImplVulkanH_WindowData
|
||||
// (Used by example's main.cpp. Used by multi-viewport features. Probably NOT used by your own engine/app.)
|
||||
struct ImGui_ImplVulkanH_Window
|
||||
{
|
||||
int Width;
|
||||
int Height;
|
||||
@ -97,13 +108,17 @@ struct ImGui_ImplVulkanH_WindowData
|
||||
VkRenderPass RenderPass;
|
||||
bool ClearEnable;
|
||||
VkClearValue ClearValue;
|
||||
uint32_t BackBufferCount;
|
||||
VkImage BackBuffer[16];
|
||||
VkImageView BackBufferView[16];
|
||||
VkFramebuffer Framebuffer[16];
|
||||
uint32_t FrameIndex;
|
||||
ImGui_ImplVulkanH_FrameData Frames[IMGUI_VK_QUEUED_FRAMES];
|
||||
uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)
|
||||
uint32_t ImageCount; // Number of simultaneous in-flight frames (returned by vkGetSwapchainImagesKHR, usually derived from min_image_count)
|
||||
uint32_t SemaphoreIndex; // Current set of swapchain wait semaphores we're using (needs to be distinct from per frame data)
|
||||
ImGui_ImplVulkanH_Frame* Frames;
|
||||
ImGui_ImplVulkanH_FrameSemaphores* FrameSemaphores;
|
||||
|
||||
IMGUI_IMPL_API ImGui_ImplVulkanH_WindowData();
|
||||
ImGui_ImplVulkanH_Window()
|
||||
{
|
||||
memset(this, 0, sizeof(*this));
|
||||
PresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
|
||||
ClearEnable = true;
|
||||
}
|
||||
};
|
||||
|
||||
|
62
imgui.cpp
62
imgui.cpp
@ -37,9 +37,14 @@ DOCUMENTATION
|
||||
- Using gamepad/keyboard navigation controls.
|
||||
- API BREAKING CHANGES (read me when you update!)
|
||||
- FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
||||
- Where is the documentation?
|
||||
- Which version should I get?
|
||||
- Who uses Dear ImGui?
|
||||
- Why the odd dual naming, "Dear ImGui" vs "ImGui"?
|
||||
- How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
|
||||
- How can I display an image? What is ImTextureID, how does it works?
|
||||
- How can I have multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack.
|
||||
- Why are multiple widgets reacting when I interact with a single one? How can I have
|
||||
multiple widgets with the same label or with an empty label? A primer on labels and the ID Stack...
|
||||
- How can I use my own math types instead of ImVec2/ImVec4?
|
||||
- How can I load a different font than the default?
|
||||
- How can I easily use icons in my application?
|
||||
@ -563,6 +568,39 @@ CODE
|
||||
FREQUENTLY ASKED QUESTIONS (FAQ), TIPS
|
||||
======================================
|
||||
|
||||
Q: Where is the documentation?
|
||||
A: This library is poorly documented at the moment and expects of the user to be acquainted with C/C++.
|
||||
- Run the examples/ and explore them.
|
||||
- See demo code in imgui_demo.cpp and particularly the ImGui::ShowDemoWindow() function.
|
||||
- The demo covers most features of Dear ImGui, so you can read the code and see its output.
|
||||
- See documentation and comments at the top of imgui.cpp + effectively imgui.h.
|
||||
- Dozens of standalone example applications using e.g. OpenGL/DirectX are provided in the examples/
|
||||
folder to explain how to integrate Dear ImGui with your own engine/application.
|
||||
- Your programming IDE is your friend, find the type or function declaration to find comments
|
||||
associated to it.
|
||||
|
||||
Q: Which version should I get?
|
||||
A: I occasionally tag Releases (https://github.com/ocornut/imgui/releases) but it is generally safe
|
||||
and recommended to sync to master/latest. The library is fairly stable and regressions tend to be
|
||||
fixed fast when reported. You may also peak at the 'docking' branch which includes:
|
||||
- Docking/Merging features (https://github.com/ocornut/imgui/issues/2109)
|
||||
- Multi-viewport features (https://github.com/ocornut/imgui/issues/1542)
|
||||
Many projects are using this branch and it is kept in sync with master regularly.
|
||||
|
||||
Q: Who uses Dear ImGui?
|
||||
A: See "Quotes" (https://github.com/ocornut/imgui/wiki/Quotes) and
|
||||
"Software using Dear ImGui" (https://github.com/ocornut/imgui/wiki/Software-using-dear-imgui) Wiki pages
|
||||
for a list of games/software which are publicly known to use dear imgui. Please add yours if you can!
|
||||
|
||||
Q: Why the odd dual naming, "Dear ImGui" vs "ImGui"?
|
||||
A: The library started its life as "ImGui" due to the fact that I didn't give it a proper name when
|
||||
when I released 1.0, and had no particular expectation that it would take off. However, the term IMGUI
|
||||
(immediate-mode graphical user interface) was coined before and is being used in variety of other
|
||||
situations (e.g. Unity uses it own implementation of the IMGUI paradigm).
|
||||
To reduce the ambiguity without affecting existing code bases, I have decided on an alternate,
|
||||
longer name "Dear ImGui" that people can use to refer to this specific library.
|
||||
Please try to refer to this library as "Dear ImGui".
|
||||
|
||||
Q: How can I tell whether to dispatch mouse/keyboard to imgui or to my application?
|
||||
A: You can read the 'io.WantCaptureMouse', 'io.WantCaptureKeyboard' and 'io.WantTextInput' flags from the ImGuiIO structure (e.g. if (ImGui::GetIO().WantCaptureMouse) { ... } )
|
||||
- When 'io.WantCaptureMouse' is set, imgui wants to use your mouse state, and you may want to discard/hide the inputs from the rest of your application.
|
||||
@ -664,8 +702,8 @@ CODE
|
||||
|
||||
Finally, you may call ImGui::ShowMetricsWindow() to explore/visualize/understand how the ImDrawList are generated.
|
||||
|
||||
Q: Why are multiple widgets reacting when I interact with a single one?
|
||||
Q: How can I have multiple widgets with the same label or with an empty label?
|
||||
Q: I have multiple widgets with the same label, and only the first one works. Why is that?
|
||||
A: A primer on labels and the ID Stack...
|
||||
|
||||
Dear ImGui internally need to uniquely identify UI elements.
|
||||
@ -1344,7 +1382,7 @@ void ImStrncpy(char* dst, const char* src, size_t count)
|
||||
char* ImStrdup(const char* str)
|
||||
{
|
||||
size_t len = strlen(str);
|
||||
void* buf = ImGui::MemAlloc(len + 1);
|
||||
void* buf = IM_ALLOC(len + 1);
|
||||
return (char*)memcpy(buf, (const void*)str, len + 1);
|
||||
}
|
||||
|
||||
@ -1354,8 +1392,8 @@ char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
|
||||
size_t src_size = strlen(src) + 1;
|
||||
if (dst_buf_size < src_size)
|
||||
{
|
||||
ImGui::MemFree(dst);
|
||||
dst = (char*)ImGui::MemAlloc(src_size);
|
||||
IM_FREE(dst);
|
||||
dst = (char*)IM_ALLOC(src_size);
|
||||
if (p_dst_size)
|
||||
*p_dst_size = src_size;
|
||||
}
|
||||
@ -1571,7 +1609,7 @@ FILE* ImFileOpen(const char* filename, const char* mode)
|
||||
}
|
||||
|
||||
// Load file content into memory
|
||||
// Memory allocated with ImGui::MemAlloc(), must be freed by user using ImGui::MemFree()
|
||||
// Memory allocated with IM_ALLOC(), must be freed by user using IM_FREE() == ImGui::MemFree()
|
||||
void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_t* out_file_size, int padding_bytes)
|
||||
{
|
||||
IM_ASSERT(filename && file_open_mode);
|
||||
@ -1590,7 +1628,7 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_
|
||||
}
|
||||
|
||||
size_t file_size = (size_t)file_size_signed;
|
||||
void* file_data = ImGui::MemAlloc(file_size + padding_bytes);
|
||||
void* file_data = IM_ALLOC(file_size + padding_bytes);
|
||||
if (file_data == NULL)
|
||||
{
|
||||
fclose(f);
|
||||
@ -1599,7 +1637,7 @@ void* ImFileLoadToMemory(const char* filename, const char* file_open_mode, size_
|
||||
if (fread(file_data, 1, file_size, f) != file_size)
|
||||
{
|
||||
fclose(f);
|
||||
ImGui::MemFree(file_data);
|
||||
IM_FREE(file_data);
|
||||
return NULL;
|
||||
}
|
||||
if (padding_bytes > 0)
|
||||
@ -3024,6 +3062,7 @@ float ImGui::CalcWrapWidthForPos(const ImVec2& pos, float wrap_pos_x)
|
||||
return ImMax(wrap_pos_x - pos.x, 1.0f);
|
||||
}
|
||||
|
||||
// IM_ALLOC() == ImGui::MemAlloc()
|
||||
void* ImGui::MemAlloc(size_t size)
|
||||
{
|
||||
if (ImGuiContext* ctx = GImGui)
|
||||
@ -3031,6 +3070,7 @@ void* ImGui::MemAlloc(size_t size)
|
||||
return GImAllocatorAllocFunc(size, GImAllocatorUserData);
|
||||
}
|
||||
|
||||
// IM_FREE() == ImGui::MemFree()
|
||||
void ImGui::MemFree(void* ptr)
|
||||
{
|
||||
if (ptr)
|
||||
@ -9790,7 +9830,7 @@ void ImGui::LoadIniSettingsFromDisk(const char* ini_filename)
|
||||
if (!file_data)
|
||||
return;
|
||||
LoadIniSettingsFromMemory(file_data, (size_t)file_data_size);
|
||||
ImGui::MemFree(file_data);
|
||||
IM_FREE(file_data);
|
||||
}
|
||||
|
||||
ImGuiSettingsHandler* ImGui::FindSettingsHandler(const char* type_name)
|
||||
@ -9814,7 +9854,7 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
|
||||
// For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
|
||||
if (ini_size == 0)
|
||||
ini_size = strlen(ini_data);
|
||||
char* buf = (char*)ImGui::MemAlloc(ini_size + 1);
|
||||
char* buf = (char*)IM_ALLOC(ini_size + 1);
|
||||
char* buf_end = buf + ini_size;
|
||||
memcpy(buf, ini_data, ini_size);
|
||||
buf[ini_size] = 0;
|
||||
@ -9861,7 +9901,7 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
|
||||
entry_handler->ReadLineFn(&g, entry_handler, entry_data, line);
|
||||
}
|
||||
}
|
||||
ImGui::MemFree(buf);
|
||||
IM_FREE(buf);
|
||||
g.SettingsLoaded = true;
|
||||
DockContextOnLoadSettings(&g);
|
||||
}
|
||||
|
33
imgui.h
33
imgui.h
@ -13,6 +13,7 @@ Index of this file:
|
||||
// Forward declarations and basic types
|
||||
// ImGui API (Dear ImGui end-user API)
|
||||
// Flags & Enumerations
|
||||
// Memory allocations macros
|
||||
// ImVector<>
|
||||
// ImGuiStyle
|
||||
// ImGuiIO
|
||||
@ -1255,6 +1256,22 @@ enum ImGuiCond_
|
||||
#endif
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helpers: Memory allocations macros
|
||||
// IM_MALLOC(), IM_FREE(), IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE()
|
||||
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
|
||||
// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ImNewDummy {};
|
||||
inline void* operator new(size_t, ImNewDummy, void* ptr) { return ptr; }
|
||||
inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symmetrical new()
|
||||
#define IM_ALLOC(_SIZE) ImGui::MemAlloc(_SIZE)
|
||||
#define IM_FREE(_PTR) ImGui::MemFree(_PTR)
|
||||
#define IM_PLACEMENT_NEW(_PTR) new(ImNewDummy(), _PTR)
|
||||
#define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE
|
||||
template<typename T> void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Helper: ImVector<>
|
||||
// Lightweight std::vector<>-like class to avoid dragging dependencies (also, some implementations of STL with debug enabled are absurdly slow, we bypass it so our code runs fast in debug).
|
||||
@ -1280,7 +1297,7 @@ struct ImVector
|
||||
inline ImVector() { Size = Capacity = 0; Data = NULL; }
|
||||
inline ImVector(const ImVector<T>& src) { Size = Capacity = 0; Data = NULL; operator=(src); }
|
||||
inline ImVector<T>& operator=(const ImVector<T>& src) { clear(); resize(src.Size); memcpy(Data, src.Data, (size_t)Size * sizeof(T)); return *this; }
|
||||
inline ~ImVector() { if (Data) ImGui::MemFree(Data); }
|
||||
inline ~ImVector() { if (Data) IM_FREE(Data); }
|
||||
|
||||
inline bool empty() const { return Size == 0; }
|
||||
inline int size() const { return Size; }
|
||||
@ -1289,7 +1306,7 @@ struct ImVector
|
||||
inline T& operator[](int i) { IM_ASSERT(i < Size); return Data[i]; }
|
||||
inline const T& operator[](int i) const { IM_ASSERT(i < Size); return Data[i]; }
|
||||
|
||||
inline void clear() { if (Data) { Size = Capacity = 0; ImGui::MemFree(Data); Data = NULL; } }
|
||||
inline void clear() { if (Data) { Size = Capacity = 0; IM_FREE(Data); Data = NULL; } }
|
||||
inline T* begin() { return Data; }
|
||||
inline const T* begin() const { return Data; }
|
||||
inline T* end() { return Data + Size; }
|
||||
@ -1303,7 +1320,7 @@ struct ImVector
|
||||
inline int _grow_capacity(int sz) const { int new_capacity = Capacity ? (Capacity + Capacity/2) : 8; return new_capacity > sz ? new_capacity : sz; }
|
||||
inline void resize(int new_size) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); Size = new_size; }
|
||||
inline void resize(int new_size, const T& v) { if (new_size > Capacity) reserve(_grow_capacity(new_size)); if (new_size > Size) for (int n = Size; n < new_size; n++) memcpy(&Data[n], &v, sizeof(v)); Size = new_size; }
|
||||
inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)ImGui::MemAlloc((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); ImGui::MemFree(Data); } Data = new_data; Capacity = new_capacity; }
|
||||
inline void reserve(int new_capacity) { if (new_capacity <= Capacity) return; T* new_data = (T*)IM_ALLOC((size_t)new_capacity * sizeof(T)); if (Data) { memcpy(new_data, Data, (size_t)Size * sizeof(T)); IM_FREE(Data); } Data = new_data; Capacity = new_capacity; }
|
||||
|
||||
// NB: It is illegal to call push_back/push_front/insert with a reference pointing inside the ImVector data itself! e.g. v.push_back(v[10]) is forbidden.
|
||||
inline void push_back(const T& v) { if (Size == Capacity) reserve(_grow_capacity(Size + 1)); memcpy(&Data[Size], &v, sizeof(v)); Size++; }
|
||||
@ -1639,16 +1656,6 @@ typedef ImGuiInputTextCallbackData ImGuiTextEditCallbackData;
|
||||
// Helpers
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Helper: IM_NEW(), IM_PLACEMENT_NEW(), IM_DELETE() macros to call MemAlloc + Placement New, Placement Delete + MemFree
|
||||
// We call C++ constructor on own allocated memory via the placement "new(ptr) Type()" syntax.
|
||||
// Defining a custom placement new() with a dummy parameter allows us to bypass including <new> which on some platforms complains when user has disabled exceptions.
|
||||
struct ImNewDummy {};
|
||||
inline void* operator new(size_t, ImNewDummy, void* ptr) { return ptr; }
|
||||
inline void operator delete(void*, ImNewDummy, void*) {} // This is only required so we can use the symmetrical new()
|
||||
#define IM_PLACEMENT_NEW(_PTR) new(ImNewDummy(), _PTR)
|
||||
#define IM_NEW(_TYPE) new(ImNewDummy(), ImGui::MemAlloc(sizeof(_TYPE))) _TYPE
|
||||
template<typename T> void IM_DELETE(T* p) { if (p) { p->~T(); ImGui::MemFree(p); } }
|
||||
|
||||
// Helper: Execute a block of code at maximum once a frame. Convenient if you want to quickly create an UI within deep-nested code that runs multiple times every frame.
|
||||
// Usage: static ImGuiOnceUponAFrame oaf; if (oaf) ImGui::Text("This will be called only once per frame");
|
||||
struct ImGuiOnceUponAFrame
|
||||
|
@ -130,8 +130,8 @@ namespace IMGUI_STB_NAMESPACE
|
||||
|
||||
#ifndef STB_TRUETYPE_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
|
||||
#ifndef IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION
|
||||
#define STBTT_malloc(x,u) ((void)(u), ImGui::MemAlloc(x))
|
||||
#define STBTT_free(x,u) ((void)(u), ImGui::MemFree(x))
|
||||
#define STBTT_malloc(x,u) ((void)(u), IM_ALLOC(x))
|
||||
#define STBTT_free(x,u) ((void)(u), IM_FREE(x))
|
||||
#define STBTT_assert(x) IM_ASSERT(x)
|
||||
#define STBTT_fmod(x,y) ImFmod(x,y)
|
||||
#define STBTT_sqrt(x) ImSqrt(x)
|
||||
@ -1465,7 +1465,7 @@ void ImFontAtlas::ClearInputData()
|
||||
for (int i = 0; i < ConfigData.Size; i++)
|
||||
if (ConfigData[i].FontData && ConfigData[i].FontDataOwnedByAtlas)
|
||||
{
|
||||
ImGui::MemFree(ConfigData[i].FontData);
|
||||
IM_FREE(ConfigData[i].FontData);
|
||||
ConfigData[i].FontData = NULL;
|
||||
}
|
||||
|
||||
@ -1486,9 +1486,9 @@ void ImFontAtlas::ClearTexData()
|
||||
{
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas between NewFrame() and EndFrame/Render()!");
|
||||
if (TexPixelsAlpha8)
|
||||
ImGui::MemFree(TexPixelsAlpha8);
|
||||
IM_FREE(TexPixelsAlpha8);
|
||||
if (TexPixelsRGBA32)
|
||||
ImGui::MemFree(TexPixelsRGBA32);
|
||||
IM_FREE(TexPixelsRGBA32);
|
||||
TexPixelsAlpha8 = NULL;
|
||||
TexPixelsRGBA32 = NULL;
|
||||
}
|
||||
@ -1534,7 +1534,7 @@ void ImFontAtlas::GetTexDataAsRGBA32(unsigned char** out_pixels, int* out_wid
|
||||
GetTexDataAsAlpha8(&pixels, NULL, NULL);
|
||||
if (pixels)
|
||||
{
|
||||
TexPixelsRGBA32 = (unsigned int*)ImGui::MemAlloc((size_t)TexWidth * (size_t)TexHeight * 4);
|
||||
TexPixelsRGBA32 = (unsigned int*)IM_ALLOC((size_t)TexWidth * (size_t)TexHeight * 4);
|
||||
const unsigned char* src = pixels;
|
||||
unsigned int* dst = TexPixelsRGBA32;
|
||||
for (int n = TexWidth * TexHeight; n > 0; n--)
|
||||
@ -1566,7 +1566,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg)
|
||||
new_font_cfg.DstFont = Fonts.back();
|
||||
if (!new_font_cfg.FontDataOwnedByAtlas)
|
||||
{
|
||||
new_font_cfg.FontData = ImGui::MemAlloc(new_font_cfg.FontDataSize);
|
||||
new_font_cfg.FontData = IM_ALLOC(new_font_cfg.FontDataSize);
|
||||
new_font_cfg.FontDataOwnedByAtlas = true;
|
||||
memcpy(new_font_cfg.FontData, font_cfg->FontData, (size_t)new_font_cfg.FontDataSize);
|
||||
}
|
||||
@ -1651,7 +1651,7 @@ ImFont* ImFontAtlas::AddFontFromMemoryTTF(void* ttf_data, int ttf_size, float si
|
||||
ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_data, int compressed_ttf_size, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
|
||||
{
|
||||
const unsigned int buf_decompressed_size = stb_decompress_length((const unsigned char*)compressed_ttf_data);
|
||||
unsigned char* buf_decompressed_data = (unsigned char *)ImGui::MemAlloc(buf_decompressed_size);
|
||||
unsigned char* buf_decompressed_data = (unsigned char *)IM_ALLOC(buf_decompressed_size);
|
||||
stb_decompress(buf_decompressed_data, (const unsigned char*)compressed_ttf_data, (unsigned int)compressed_ttf_size);
|
||||
|
||||
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
|
||||
@ -1663,10 +1663,10 @@ ImFont* ImFontAtlas::AddFontFromMemoryCompressedTTF(const void* compressed_ttf_d
|
||||
ImFont* ImFontAtlas::AddFontFromMemoryCompressedBase85TTF(const char* compressed_ttf_data_base85, float size_pixels, const ImFontConfig* font_cfg, const ImWchar* glyph_ranges)
|
||||
{
|
||||
int compressed_ttf_size = (((int)strlen(compressed_ttf_data_base85) + 4) / 5) * 4;
|
||||
void* compressed_ttf = ImGui::MemAlloc((size_t)compressed_ttf_size);
|
||||
void* compressed_ttf = IM_ALLOC((size_t)compressed_ttf_size);
|
||||
Decode85((const unsigned char*)compressed_ttf_data_base85, (unsigned char*)compressed_ttf);
|
||||
ImFont* font = AddFontFromMemoryCompressedTTF(compressed_ttf, compressed_ttf_size, size_pixels, font_cfg, glyph_ranges);
|
||||
ImGui::MemFree(compressed_ttf);
|
||||
IM_FREE(compressed_ttf);
|
||||
return font;
|
||||
}
|
||||
|
||||
@ -1966,7 +1966,7 @@ bool ImFontAtlasBuildWithStbTruetype(ImFontAtlas* atlas)
|
||||
// 7. Allocate texture
|
||||
atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
|
||||
atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
|
||||
atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight);
|
||||
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
|
||||
memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
|
||||
spc.pixels = atlas->TexPixelsAlpha8;
|
||||
spc.height = atlas->TexHeight;
|
||||
|
@ -3571,7 +3571,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
const int ib = state->HasSelection() ? ImMin(state->Stb.select_start, state->Stb.select_end) : 0;
|
||||
const int ie = state->HasSelection() ? ImMax(state->Stb.select_start, state->Stb.select_end) : state->CurLenW;
|
||||
const int clipboard_data_len = ImTextCountUtf8BytesFromStr(state->TextW.Data + ib, state->TextW.Data + ie) + 1;
|
||||
char* clipboard_data = (char*)MemAlloc(clipboard_data_len * sizeof(char));
|
||||
char* clipboard_data = (char*)IM_ALLOC(clipboard_data_len * sizeof(char));
|
||||
ImTextStrToUtf8(clipboard_data, clipboard_data_len, state->TextW.Data + ib, state->TextW.Data + ie);
|
||||
SetClipboardText(clipboard_data);
|
||||
MemFree(clipboard_data);
|
||||
@ -3590,7 +3590,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
// Filter pasted buffer
|
||||
const int clipboard_len = (int)strlen(clipboard);
|
||||
ImWchar* clipboard_filtered = (ImWchar*)MemAlloc((clipboard_len+1) * sizeof(ImWchar));
|
||||
ImWchar* clipboard_filtered = (ImWchar*)IM_ALLOC((clipboard_len+1) * sizeof(ImWchar));
|
||||
int clipboard_filtered_len = 0;
|
||||
for (const char* s = clipboard; *s; )
|
||||
{
|
||||
|
@ -398,7 +398,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024;
|
||||
int buf_bitmap_current_used_bytes = 0;
|
||||
ImVector<unsigned char*> buf_bitmap_buffers;
|
||||
buf_bitmap_buffers.push_back((unsigned char*)ImGui::MemAlloc(BITMAP_BUFFERS_CHUNK_SIZE));
|
||||
buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
|
||||
|
||||
// 4. Gather glyphs sizes so we can pack them in our virtual canvas.
|
||||
// 8. Render/rasterize font characters into the texture
|
||||
@ -440,7 +440,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE)
|
||||
{
|
||||
buf_bitmap_current_used_bytes = 0;
|
||||
buf_bitmap_buffers.push_back((unsigned char*)ImGui::MemAlloc(BITMAP_BUFFERS_CHUNK_SIZE));
|
||||
buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
|
||||
}
|
||||
|
||||
// Blit rasterized pixels to our temporary buffer and keep a pointer to it.
|
||||
@ -493,7 +493,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
// 7. Allocate texture
|
||||
atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight);
|
||||
atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
|
||||
atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight);
|
||||
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
|
||||
memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
|
||||
|
||||
// 8. Copy rasterized font characters back into the main texture
|
||||
@ -557,7 +557,7 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
|
||||
// Cleanup
|
||||
for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
|
||||
ImGui::MemFree(buf_bitmap_buffers[buf_i]);
|
||||
IM_FREE(buf_bitmap_buffers[buf_i]);
|
||||
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
|
||||
src_tmp_array[src_i].~ImFontBuildSrcDataFT();
|
||||
|
||||
@ -567,8 +567,8 @@ bool ImFontAtlasBuildWithFreeType(FT_Library ft_library, ImFontAtlas* atlas, uns
|
||||
}
|
||||
|
||||
// Default memory allocators
|
||||
static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return ImGui::MemAlloc(size); }
|
||||
static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); ImGui::MemFree(ptr); }
|
||||
static void* ImFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); }
|
||||
static void ImFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); }
|
||||
|
||||
// Current memory allocators
|
||||
static void* (*GImFreeTypeAllocFunc)(size_t size, void* user_data) = ImFreeTypeDefaultAllocFunc;
|
||||
|
@ -29,7 +29,7 @@ namespace ImGuiFreeType
|
||||
|
||||
IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0);
|
||||
|
||||
// By default ImGuiFreeType will use ImGui::MemAlloc()/MemFree().
|
||||
// By default ImGuiFreeType will use IM_ALLOC()/IM_FREE().
|
||||
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired:
|
||||
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user