aboutsummaryrefslogtreecommitdiff
path: root/3rdparty/imgui/backend/imgui_impl_vulkan.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-02-19 13:30:03 -0800
committerrtk0c <[email protected]>2022-02-19 13:30:03 -0800
commit9dcdcf68f6a60741cbdd287e7eda23b4a21a080e (patch)
treef5ff4c569607e1f63de9dd87bb7442e021b1f620 /3rdparty/imgui/backend/imgui_impl_vulkan.cpp
parent2599909052ef552efd5622bf73b60913e815b498 (diff)
Fix build errors and update all dependencies to latest version
- Fixed doctest executable not compiling - Fixed class accessibility error in Workflow_Main.cpp - Fixed selection of OpenGL loader in imgui OpenGL 2 & 3 backends - All loading is handled in our code now, the imgui_*_backend.cpp files are instructed to do nothing
Diffstat (limited to '3rdparty/imgui/backend/imgui_impl_vulkan.cpp')
-rw-r--r--3rdparty/imgui/backend/imgui_impl_vulkan.cpp412
1 files changed, 251 insertions, 161 deletions
diff --git a/3rdparty/imgui/backend/imgui_impl_vulkan.cpp b/3rdparty/imgui/backend/imgui_impl_vulkan.cpp
index 167687e..dbd8b18 100644
--- a/3rdparty/imgui/backend/imgui_impl_vulkan.cpp
+++ b/3rdparty/imgui/backend/imgui_impl_vulkan.cpp
@@ -3,10 +3,18 @@
// Implemented features:
// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bit indices.
-// Missing features:
-// [ ] Renderer: User texture binding. Changes of ImTextureID aren't supported by this backend! See https://github.com/ocornut/imgui/pull/914
+// [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions.
-// You can copy and use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'.
+// This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*.
+// To build this on 32-bit systems and support texture changes:
+// - [Solution 1] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'ImTextureID=ImU64' (this is what we do in our .vcxproj files)
+// - [Solution 2] IDE/msbuild: in "Properties/C++/Preprocessor Definitions" add 'IMGUI_USER_CONFIG="my_imgui_config.h"' and inside 'my_imgui_config.h' add '#define ImTextureID ImU64' and as many other options as you like.
+// - [Solution 3] IDE/msbuild: edit imconfig.h and add '#define ImTextureID ImU64' (prefer solution 2 to create your own config file!)
+// - [Solution 4] command-line: add '/D ImTextureID=ImU64' to your cl.exe command-line (this is what we do in our batch files)
+
+// You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
+// Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
// If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
// Read online: https://github.com/ocornut/imgui/tree/master/docs
@@ -22,6 +30,8 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
+// 2021-10-15: Vulkan: Call vkCmdSetScissor() at the end of render a full-viewport to reduce likehood of issues with people using VK_DYNAMIC_STATE_SCISSOR in their app without calling vkCmdSetScissor() explicitly every frame.
+// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-03-22: Vulkan: Fix mapped memory validation error when buffer sizes are not multiple of VkPhysicalDeviceLimits::nonCoherentAtomSize.
// 2021-02-18: Vulkan: Change blending equation to preserve alpha in output buffer.
// 2021-01-27: Vulkan: Added support for custom function load and IMGUI_IMPL_VULKAN_NO_PROTOTYPES by using ImGui_ImplVulkan_LoadFunctions().
@@ -54,6 +64,11 @@
#include "imgui_impl_vulkan.h"
#include <stdio.h>
+// Visual Studio warnings
+#ifdef _MSC_VER
+#pragma warning (disable: 4127) // condition expression is constant
+#endif
+
// Reusable buffers used for rendering 1 current in-flight frame, for ImGui_ImplVulkan_RenderDrawData()
// [Please zero-clear before use!]
struct ImGui_ImplVulkanH_FrameRenderBuffers
@@ -76,33 +91,37 @@ struct ImGui_ImplVulkanH_WindowRenderBuffers
};
// 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;
-static uint32_t g_Subpass = 0;
-static VkShaderModule g_ShaderModuleVert;
-static VkShaderModule g_ShaderModuleFrag;
-#ifdef VK_NO_PROTOTYPES
-static bool g_FunctionsLoaded = false;
-#else
-static bool g_FunctionsLoaded = true;
-#endif
+struct ImGui_ImplVulkan_Data
+{
+ ImGui_ImplVulkan_InitInfo VulkanInitInfo;
+ VkRenderPass RenderPass;
+ VkDeviceSize BufferMemoryAlignment;
+ VkPipelineCreateFlags PipelineCreateFlags;
+ VkDescriptorSetLayout DescriptorSetLayout;
+ VkPipelineLayout PipelineLayout;
+ VkPipeline Pipeline;
+ uint32_t Subpass;
+ VkShaderModule ShaderModuleVert;
+ VkShaderModule ShaderModuleFrag;
-// 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;
+ // Font data
+ VkSampler FontSampler;
+ VkDeviceMemory FontMemory;
+ VkImage FontImage;
+ VkImageView FontView;
+ VkDescriptorSet FontDescriptorSet;
+ VkDeviceMemory UploadBufferMemory;
+ VkBuffer UploadBuffer;
-// Render buffers
-static ImGui_ImplVulkanH_WindowRenderBuffers g_MainWindowRenderBuffers;
+ // Render buffers
+ ImGui_ImplVulkanH_WindowRenderBuffers MainWindowRenderBuffers;
+
+ ImGui_ImplVulkan_Data()
+ {
+ memset(this, 0, sizeof(*this));
+ BufferMemoryAlignment = 256;
+ }
+};
// Forward Declarations
bool ImGui_ImplVulkan_CreateDeviceObjects();
@@ -117,6 +136,11 @@ void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_devi
// Vulkan prototypes for use with custom loaders
// (see description of IMGUI_IMPL_VULKAN_NO_PROTOTYPES in imgui_impl_vulkan.h
#ifdef VK_NO_PROTOTYPES
+static bool g_FunctionsLoaded = false;
+#else
+static bool g_FunctionsLoaded = true;
+#endif
+#ifdef VK_NO_PROTOTYPES
#define IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_MAP_MACRO) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateCommandBuffers) \
IMGUI_VULKAN_FUNC_MAP_MACRO(vkAllocateDescriptorSets) \
@@ -296,9 +320,18 @@ static uint32_t __glsl_shader_frag_spv[] =
// FUNCTIONS
//-----------------------------------------------------------------------------
+// Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
+// It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
+// FIXME: multi-context support is not tested and probably dysfunctional in this backend.
+static ImGui_ImplVulkan_Data* ImGui_ImplVulkan_GetBackendData()
+{
+ return ImGui::GetCurrentContext() ? (ImGui_ImplVulkan_Data*)ImGui::GetIO().BackendRendererUserData : NULL;
+}
+
static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits)
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkPhysicalDeviceMemoryProperties prop;
vkGetPhysicalDeviceMemoryProperties(v->PhysicalDevice, &prop);
for (uint32_t i = 0; i < prop.memoryTypeCount; i++)
@@ -309,21 +342,25 @@ static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, ui
static void check_vk_result(VkResult err)
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (!bd)
+ return;
+ ImGui_ImplVulkan_InitInfo* v = &bd->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;
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;
if (buffer != VK_NULL_HANDLE)
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;
+ VkDeviceSize vertex_buffer_size_aligned = ((new_size - 1) / bd->BufferMemoryAlignment + 1) * bd->BufferMemoryAlignment;
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = vertex_buffer_size_aligned;
@@ -334,7 +371,7 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
VkMemoryRequirements req;
vkGetBufferMemoryRequirements(v->Device, buffer, &req);
- g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
+ bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->BufferMemoryAlignment : req.alignment;
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = req.size;
@@ -349,11 +386,11 @@ static void CreateOrResizeBuffer(VkBuffer& buffer, VkDeviceMemory& buffer_memory
static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline pipeline, VkCommandBuffer command_buffer, ImGui_ImplVulkanH_FrameRenderBuffers* rb, int fb_width, int fb_height)
{
- // Bind pipeline and descriptor sets:
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+
+ // Bind pipeline:
{
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
- VkDescriptorSet desc_set[1] = { g_DescriptorSet };
- vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_PipelineLayout, 0, 1, desc_set, 0, NULL);
}
// Bind Vertex And Index Buffer:
@@ -386,8 +423,8 @@ static void ImGui_ImplVulkan_SetupRenderState(ImDrawData* draw_data, VkPipeline
float translate[2];
translate[0] = -1.0f - draw_data->DisplayPos.x * scale[0];
translate[1] = -1.0f - draw_data->DisplayPos.y * scale[1];
- vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
- vkCmdPushConstants(command_buffer, g_PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 0, sizeof(float) * 2, scale);
+ vkCmdPushConstants(command_buffer, bd->PipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(float) * 2, sizeof(float) * 2, translate);
}
}
@@ -400,12 +437,13 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
if (fb_width <= 0 || fb_height <= 0)
return;
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
if (pipeline == VK_NULL_HANDLE)
- pipeline = g_Pipeline;
+ pipeline = bd->Pipeline;
// Allocate array to store enough vertex/index buffers
- ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &g_MainWindowRenderBuffers;
+ ImGui_ImplVulkanH_WindowRenderBuffers* wrb = &bd->MainWindowRenderBuffers;
if (wrb->FrameRenderBuffers == NULL)
{
wrb->Index = 0;
@@ -484,42 +522,59 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm
else
{
// Project scissor/clipping rectangles into framebuffer space
- ImVec4 clip_rect;
- clip_rect.x = (pcmd->ClipRect.x - clip_off.x) * clip_scale.x;
- clip_rect.y = (pcmd->ClipRect.y - clip_off.y) * clip_scale.y;
- clip_rect.z = (pcmd->ClipRect.z - clip_off.x) * clip_scale.x;
- clip_rect.w = (pcmd->ClipRect.w - clip_off.y) * clip_scale.y;
+ ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
+ ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
- if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)
- {
- // Negative offsets are illegal for vkCmdSetScissor
- if (clip_rect.x < 0.0f)
- clip_rect.x = 0.0f;
- if (clip_rect.y < 0.0f)
- clip_rect.y = 0.0f;
+ // Clamp to viewport as vkCmdSetScissor() won't accept values that are off bounds
+ if (clip_min.x < 0.0f) { clip_min.x = 0.0f; }
+ if (clip_min.y < 0.0f) { clip_min.y = 0.0f; }
+ if (clip_max.x > fb_width) { clip_max.x = (float)fb_width; }
+ if (clip_max.y > fb_height) { clip_max.y = (float)fb_height; }
+ if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
+ continue;
- // Apply scissor/clipping rectangle
- VkRect2D scissor;
- scissor.offset.x = (int32_t)(clip_rect.x);
- scissor.offset.y = (int32_t)(clip_rect.y);
- scissor.extent.width = (uint32_t)(clip_rect.z - clip_rect.x);
- scissor.extent.height = (uint32_t)(clip_rect.w - clip_rect.y);
- vkCmdSetScissor(command_buffer, 0, 1, &scissor);
+ // Apply scissor/clipping rectangle
+ VkRect2D scissor;
+ scissor.offset.x = (int32_t)(clip_min.x);
+ scissor.offset.y = (int32_t)(clip_min.y);
+ scissor.extent.width = (uint32_t)(clip_max.x - clip_min.x);
+ scissor.extent.height = (uint32_t)(clip_max.y - clip_min.y);
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
- // Draw
- vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
+ // Bind DescriptorSet with font or user texture
+ VkDescriptorSet desc_set[1] = { (VkDescriptorSet)pcmd->TextureId };
+ if (sizeof(ImTextureID) < sizeof(ImU64))
+ {
+ // We don't support texture switches if ImTextureID hasn't been redefined to be 64-bit. Do a flaky check that other textures haven't been used.
+ IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->FontDescriptorSet);
+ desc_set[0] = bd->FontDescriptorSet;
}
+ vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, bd->PipelineLayout, 0, 1, desc_set, 0, NULL);
+
+ // Draw
+ vkCmdDrawIndexed(command_buffer, pcmd->ElemCount, 1, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset, 0);
}
}
global_idx_offset += cmd_list->IdxBuffer.Size;
global_vtx_offset += cmd_list->VtxBuffer.Size;
}
+
+ // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called.
+ // Our last values will leak into user/application rendering IF:
+ // - Your app uses a pipeline with VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR dynamic state
+ // - And you forgot to call vkCmdSetViewport() and vkCmdSetScissor() yourself to explicitely set that state.
+ // If you use VK_DYNAMIC_STATE_VIEWPORT or VK_DYNAMIC_STATE_SCISSOR you are responsible for setting the values before rendering.
+ // In theory we should aim to backup/restore those values but I am not sure this is possible.
+ // We perform a call to vkCmdSetScissor() to set back a full viewport which is likely to fix things for 99% users but technically this is not perfect. (See github #4644)
+ VkRect2D scissor = { { 0, 0 }, { (uint32_t)fb_width, (uint32_t)fb_height } };
+ vkCmdSetScissor(command_buffer, 0, 1, &scissor);
}
bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
ImGuiIO& io = ImGui::GetIO();
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
unsigned char* pixels;
int width, height;
@@ -544,17 +599,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(v->Device, &info, v->Allocator, &g_FontImage);
+ err = vkCreateImage(v->Device, &info, v->Allocator, &bd->FontImage);
check_vk_result(err);
VkMemoryRequirements req;
- vkGetImageMemoryRequirements(v->Device, g_FontImage, &req);
+ vkGetImageMemoryRequirements(v->Device, bd->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(v->Device, &alloc_info, v->Allocator, &g_FontMemory);
+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->FontMemory);
check_vk_result(err);
- err = vkBindImageMemory(v->Device, g_FontImage, g_FontMemory, 0);
+ err = vkBindImageMemory(v->Device, bd->FontImage, bd->FontMemory, 0);
check_vk_result(err);
}
@@ -562,30 +617,18 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
{
VkImageViewCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
- info.image = g_FontImage;
+ info.image = bd->FontImage;
info.viewType = VK_IMAGE_VIEW_TYPE_2D;
info.format = VK_FORMAT_R8G8B8A8_UNORM;
info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
info.subresourceRange.levelCount = 1;
info.subresourceRange.layerCount = 1;
- err = vkCreateImageView(v->Device, &info, v->Allocator, &g_FontView);
+ err = vkCreateImageView(v->Device, &info, v->Allocator, &bd->FontView);
check_vk_result(err);
}
- // Update the Descriptor Set:
- {
- VkDescriptorImageInfo desc_image[1] = {};
- desc_image[0].sampler = g_FontSampler;
- desc_image[0].imageView = g_FontView;
- desc_image[0].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- VkWriteDescriptorSet write_desc[1] = {};
- write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- write_desc[0].dstSet = g_DescriptorSet;
- write_desc[0].descriptorCount = 1;
- write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
- write_desc[0].pImageInfo = desc_image;
- vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
- }
+ // Create the Descriptor Set:
+ bd->FontDescriptorSet = (VkDescriptorSet)ImGui_ImplVulkan_AddTexture(bd->FontSampler, bd->FontView, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
// Create the Upload Buffer:
{
@@ -594,34 +637,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(v->Device, &buffer_info, v->Allocator, &g_UploadBuffer);
+ err = vkCreateBuffer(v->Device, &buffer_info, v->Allocator, &bd->UploadBuffer);
check_vk_result(err);
VkMemoryRequirements req;
- vkGetBufferMemoryRequirements(v->Device, g_UploadBuffer, &req);
- g_BufferMemoryAlignment = (g_BufferMemoryAlignment > req.alignment) ? g_BufferMemoryAlignment : req.alignment;
+ vkGetBufferMemoryRequirements(v->Device, bd->UploadBuffer, &req);
+ bd->BufferMemoryAlignment = (bd->BufferMemoryAlignment > req.alignment) ? bd->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(v->Device, &alloc_info, v->Allocator, &g_UploadBufferMemory);
+ err = vkAllocateMemory(v->Device, &alloc_info, v->Allocator, &bd->UploadBufferMemory);
check_vk_result(err);
- err = vkBindBufferMemory(v->Device, g_UploadBuffer, g_UploadBufferMemory, 0);
+ err = vkBindBufferMemory(v->Device, bd->UploadBuffer, bd->UploadBufferMemory, 0);
check_vk_result(err);
}
// Upload to Buffer:
{
char* map = NULL;
- err = vkMapMemory(v->Device, g_UploadBufferMemory, 0, upload_size, 0, (void**)(&map));
+ err = vkMapMemory(v->Device, bd->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].memory = bd->UploadBufferMemory;
range[0].size = upload_size;
err = vkFlushMappedMemoryRanges(v->Device, 1, range);
check_vk_result(err);
- vkUnmapMemory(v->Device, g_UploadBufferMemory);
+ vkUnmapMemory(v->Device, bd->UploadBufferMemory);
}
// Copy to Image:
@@ -633,7 +676,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
copy_barrier[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
copy_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
copy_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- copy_barrier[0].image = g_FontImage;
+ copy_barrier[0].image = bd->FontImage;
copy_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
copy_barrier[0].subresourceRange.levelCount = 1;
copy_barrier[0].subresourceRange.layerCount = 1;
@@ -645,7 +688,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
region.imageExtent.width = width;
region.imageExtent.height = height;
region.imageExtent.depth = 1;
- vkCmdCopyBufferToImage(command_buffer, g_UploadBuffer, g_FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
+ vkCmdCopyBufferToImage(command_buffer, bd->UploadBuffer, bd->FontImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &region);
VkImageMemoryBarrier use_barrier[1] = {};
use_barrier[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
@@ -655,7 +698,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
use_barrier[0].newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
use_barrier[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
use_barrier[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- use_barrier[0].image = g_FontImage;
+ use_barrier[0].image = bd->FontImage;
use_barrier[0].subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
use_barrier[0].subresourceRange.levelCount = 1;
use_barrier[0].subresourceRange.layerCount = 1;
@@ -663,7 +706,7 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
}
// Store our identifier
- io.Fonts->SetTexID((ImTextureID)(intptr_t)g_FontImage);
+ io.Fonts->SetTexID((ImTextureID)bd->FontDescriptorSet);
return true;
}
@@ -671,29 +714,31 @@ bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer)
static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator)
{
// Create the shader modules
- if (g_ShaderModuleVert == NULL)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->ShaderModuleVert == VK_NULL_HANDLE)
{
VkShaderModuleCreateInfo vert_info = {};
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;
- VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &g_ShaderModuleVert);
+ VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert);
check_vk_result(err);
}
- if (g_ShaderModuleFrag == NULL)
+ if (bd->ShaderModuleFrag == VK_NULL_HANDLE)
{
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;
- VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &g_ShaderModuleFrag);
+ VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag);
check_vk_result(err);
}
}
static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocationCallbacks* allocator)
{
- if (g_FontSampler)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->FontSampler)
return;
VkSamplerCreateInfo info = {};
@@ -707,17 +752,18 @@ static void ImGui_ImplVulkan_CreateFontSampler(VkDevice device, const VkAllocati
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
- VkResult err = vkCreateSampler(device, &info, allocator, &g_FontSampler);
+ VkResult err = vkCreateSampler(device, &info, allocator, &bd->FontSampler);
check_vk_result(err);
}
static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const VkAllocationCallbacks* allocator)
{
- if (g_DescriptorSetLayout)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->DescriptorSetLayout)
return;
ImGui_ImplVulkan_CreateFontSampler(device, allocator);
- VkSampler sampler[1] = { g_FontSampler };
+ VkSampler sampler[1] = { bd->FontSampler };
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
@@ -727,13 +773,14 @@ static void ImGui_ImplVulkan_CreateDescriptorSetLayout(VkDevice device, const Vk
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
- VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &g_DescriptorSetLayout);
+ VkResult err = vkCreateDescriptorSetLayout(device, &info, allocator, &bd->DescriptorSetLayout);
check_vk_result(err);
}
static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAllocationCallbacks* allocator)
{
- if (g_PipelineLayout)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ if (bd->PipelineLayout)
return;
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
@@ -742,29 +789,30 @@ static void ImGui_ImplVulkan_CreatePipelineLayout(VkDevice device, const VkAlloc
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
- VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout };
+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants;
- VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &g_PipelineLayout);
+ VkResult err = vkCreatePipelineLayout(device, &layout_info, allocator, &bd->PipelineLayout);
check_vk_result(err);
}
static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, VkPipeline* pipeline, uint32_t subpass)
{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
ImGui_ImplVulkan_CreateShaderModules(device, allocator);
VkPipelineShaderStageCreateInfo stage[2] = {};
stage[0].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
- stage[0].module = g_ShaderModuleVert;
+ stage[0].module = bd->ShaderModuleVert;
stage[0].pName = "main";
stage[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
stage[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
- stage[1].module = g_ShaderModuleFrag;
+ stage[1].module = bd->ShaderModuleFrag;
stage[1].pName = "main";
VkVertexInputBindingDescription binding_desc[1] = {};
@@ -840,7 +888,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
VkGraphicsPipelineCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- info.flags = g_PipelineCreateFlags;
+ info.flags = bd->PipelineCreateFlags;
info.stageCount = 2;
info.pStages = stage;
info.pVertexInputState = &vertex_info;
@@ -851,7 +899,7 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
info.pDepthStencilState = &depth_info;
info.pColorBlendState = &blend_info;
info.pDynamicState = &dynamic_state;
- info.layout = g_PipelineLayout;
+ info.layout = bd->PipelineLayout;
info.renderPass = renderPass;
info.subpass = subpass;
VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline);
@@ -860,10 +908,11 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC
bool ImGui_ImplVulkan_CreateDeviceObjects()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
VkResult err;
- if (!g_FontSampler)
+ if (!bd->FontSampler)
{
VkSamplerCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
@@ -876,13 +925,13 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
info.minLod = -1000;
info.maxLod = 1000;
info.maxAnisotropy = 1.0f;
- err = vkCreateSampler(v->Device, &info, v->Allocator, &g_FontSampler);
+ err = vkCreateSampler(v->Device, &info, v->Allocator, &bd->FontSampler);
check_vk_result(err);
}
- if (!g_DescriptorSetLayout)
+ if (!bd->DescriptorSetLayout)
{
- VkSampler sampler[1] = {g_FontSampler};
+ VkSampler sampler[1] = {bd->FontSampler};
VkDescriptorSetLayoutBinding binding[1] = {};
binding[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
binding[0].descriptorCount = 1;
@@ -892,74 +941,65 @@ bool ImGui_ImplVulkan_CreateDeviceObjects()
info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
info.bindingCount = 1;
info.pBindings = binding;
- err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &g_DescriptorSetLayout);
+ err = vkCreateDescriptorSetLayout(v->Device, &info, v->Allocator, &bd->DescriptorSetLayout);
check_vk_result(err);
}
- // Create Descriptor Set:
- {
- VkDescriptorSetAllocateInfo alloc_info = {};
- alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- alloc_info.descriptorPool = v->DescriptorPool;
- alloc_info.descriptorSetCount = 1;
- alloc_info.pSetLayouts = &g_DescriptorSetLayout;
- err = vkAllocateDescriptorSets(v->Device, &alloc_info, &g_DescriptorSet);
- check_vk_result(err);
- }
-
- if (!g_PipelineLayout)
+ if (!bd->PipelineLayout)
{
// Constants: we are using 'vec2 offset' and 'vec2 scale' instead of a full 3d projection matrix
VkPushConstantRange push_constants[1] = {};
push_constants[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
push_constants[0].offset = sizeof(float) * 0;
push_constants[0].size = sizeof(float) * 4;
- VkDescriptorSetLayout set_layout[1] = { g_DescriptorSetLayout };
+ VkDescriptorSetLayout set_layout[1] = { bd->DescriptorSetLayout };
VkPipelineLayoutCreateInfo layout_info = {};
layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
layout_info.setLayoutCount = 1;
layout_info.pSetLayouts = set_layout;
layout_info.pushConstantRangeCount = 1;
layout_info.pPushConstantRanges = push_constants;
- err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &g_PipelineLayout);
+ err = vkCreatePipelineLayout(v->Device, &layout_info, v->Allocator, &bd->PipelineLayout);
check_vk_result(err);
}
- ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, g_RenderPass, v->MSAASamples, &g_Pipeline, g_Subpass);
+ ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, bd->RenderPass, v->MSAASamples, &bd->Pipeline, bd->Subpass);
return true;
}
void ImGui_ImplVulkan_DestroyFontUploadObjects()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- if (g_UploadBuffer)
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ if (bd->UploadBuffer)
{
- vkDestroyBuffer(v->Device, g_UploadBuffer, v->Allocator);
- g_UploadBuffer = VK_NULL_HANDLE;
+ vkDestroyBuffer(v->Device, bd->UploadBuffer, v->Allocator);
+ bd->UploadBuffer = VK_NULL_HANDLE;
}
- if (g_UploadBufferMemory)
+ if (bd->UploadBufferMemory)
{
- vkFreeMemory(v->Device, g_UploadBufferMemory, v->Allocator);
- g_UploadBufferMemory = VK_NULL_HANDLE;
+ vkFreeMemory(v->Device, bd->UploadBufferMemory, v->Allocator);
+ bd->UploadBufferMemory = VK_NULL_HANDLE;
}
}
void ImGui_ImplVulkan_DestroyDeviceObjects()
{
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
- ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &g_MainWindowRenderBuffers, v->Allocator);
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+ ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator);
ImGui_ImplVulkan_DestroyFontUploadObjects();
- if (g_ShaderModuleVert) { vkDestroyShaderModule(v->Device, g_ShaderModuleVert, v->Allocator); g_ShaderModuleVert = VK_NULL_HANDLE; }
- if (g_ShaderModuleFrag) { vkDestroyShaderModule(v->Device, g_ShaderModuleFrag, v->Allocator); g_ShaderModuleFrag = 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; }
+ if (bd->ShaderModuleVert) { vkDestroyShaderModule(v->Device, bd->ShaderModuleVert, v->Allocator); bd->ShaderModuleVert = VK_NULL_HANDLE; }
+ if (bd->ShaderModuleFrag) { vkDestroyShaderModule(v->Device, bd->ShaderModuleFrag, v->Allocator); bd->ShaderModuleFrag = VK_NULL_HANDLE; }
+ if (bd->FontView) { vkDestroyImageView(v->Device, bd->FontView, v->Allocator); bd->FontView = VK_NULL_HANDLE; }
+ if (bd->FontImage) { vkDestroyImage(v->Device, bd->FontImage, v->Allocator); bd->FontImage = VK_NULL_HANDLE; }
+ if (bd->FontMemory) { vkFreeMemory(v->Device, bd->FontMemory, v->Allocator); bd->FontMemory = VK_NULL_HANDLE; }
+ if (bd->FontSampler) { vkDestroySampler(v->Device, bd->FontSampler, v->Allocator); bd->FontSampler = VK_NULL_HANDLE; }
+ if (bd->DescriptorSetLayout) { vkDestroyDescriptorSetLayout(v->Device, bd->DescriptorSetLayout, v->Allocator); bd->DescriptorSetLayout = VK_NULL_HANDLE; }
+ if (bd->PipelineLayout) { vkDestroyPipelineLayout(v->Device, bd->PipelineLayout, v->Allocator); bd->PipelineLayout = VK_NULL_HANDLE; }
+ if (bd->Pipeline) { vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; }
}
bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
@@ -987,8 +1027,12 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
{
IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!");
- // Setup backend capabilities flags
ImGuiIO& io = ImGui::GetIO();
+ IM_ASSERT(io.BackendRendererUserData == NULL && "Already initialized a renderer backend!");
+
+ // Setup backend capabilities flags
+ ImGui_ImplVulkan_Data* bd = IM_NEW(ImGui_ImplVulkan_Data)();
+ io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_vulkan";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
@@ -1001,9 +1045,9 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
IM_ASSERT(info->ImageCount >= info->MinImageCount);
IM_ASSERT(render_pass != VK_NULL_HANDLE);
- g_VulkanInitInfo = *info;
- g_RenderPass = render_pass;
- g_Subpass = info->Subpass;
+ bd->VulkanInitInfo = *info;
+ bd->RenderPass = render_pass;
+ bd->Subpass = info->Subpass;
ImGui_ImplVulkan_CreateDeviceObjects();
@@ -1012,26 +1056,72 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend
void ImGui_ImplVulkan_Shutdown()
{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ IM_ASSERT(bd != NULL && "No renderer backend to shutdown, or already shutdown?");
+ ImGuiIO& io = ImGui::GetIO();
+
ImGui_ImplVulkan_DestroyDeviceObjects();
+ io.BackendRendererName = NULL;
+ io.BackendRendererUserData = NULL;
+ IM_DELETE(bd);
}
void ImGui_ImplVulkan_NewFrame()
{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ IM_ASSERT(bd != NULL && "Did you call ImGui_ImplVulkan_Init()?");
+ IM_UNUSED(bd);
}
void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count)
{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
IM_ASSERT(min_image_count >= 2);
- if (g_VulkanInitInfo.MinImageCount == min_image_count)
+ if (bd->VulkanInitInfo.MinImageCount == min_image_count)
return;
- ImGui_ImplVulkan_InitInfo* v = &g_VulkanInitInfo;
+ ImGui_ImplVulkan_InitInfo* v = &bd->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;
+ ImGui_ImplVulkanH_DestroyWindowRenderBuffers(v->Device, &bd->MainWindowRenderBuffers, v->Allocator);
+ bd->VulkanInitInfo.MinImageCount = min_image_count;
}
+// Register a texture
+// FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem, please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions.
+VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout)
+{
+ ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData();
+ ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo;
+
+ // Create Descriptor Set:
+ VkDescriptorSet descriptor_set;
+ {
+ VkDescriptorSetAllocateInfo alloc_info = {};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorPool = v->DescriptorPool;
+ alloc_info.descriptorSetCount = 1;
+ alloc_info.pSetLayouts = &bd->DescriptorSetLayout;
+ VkResult err = vkAllocateDescriptorSets(v->Device, &alloc_info, &descriptor_set);
+ check_vk_result(err);
+ }
+
+ // Update the Descriptor Set:
+ {
+ VkDescriptorImageInfo desc_image[1] = {};
+ desc_image[0].sampler = sampler;
+ desc_image[0].imageView = image_view;
+ desc_image[0].imageLayout = image_layout;
+ VkWriteDescriptorSet write_desc[1] = {};
+ write_desc[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_desc[0].dstSet = descriptor_set;
+ write_desc[0].descriptorCount = 1;
+ write_desc[0].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ write_desc[0].pImageInfo = desc_image;
+ vkUpdateDescriptorSets(v->Device, 1, write_desc, 0, NULL);
+ }
+ return descriptor_set;
+}
//-------------------------------------------------------------------------
// Internal / Miscellaneous Vulkan Helpers
@@ -1181,7 +1271,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
{
VkResult err;
VkSwapchainKHR old_swapchain = wd->Swapchain;
- wd->Swapchain = NULL;
+ wd->Swapchain = VK_NULL_HANDLE;
err = vkDeviceWaitIdle(device);
check_vk_result(err);
@@ -1299,7 +1389,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V
// We do not create a pipeline by default as this is also used by examples' main.cpp,
// but secondary viewport in multi-viewport mode may want to create one with:
- //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, g_Subpass);
+ //ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, bd->Subpass);
}
// Create The Image Views
@@ -1356,7 +1446,7 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
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);
+ //vkQueueWaitIdle(bd->Queue);
for (uint32_t i = 0; i < wd->ImageCount; i++)
{