Examples: Vulkan: Further refactor.

This commit is contained in:
omar 2018-03-03 00:29:17 +01:00
parent e0cbfd74d7
commit cab41d954e
4 changed files with 238 additions and 276 deletions

View File

@ -11,6 +11,7 @@
// CHANGELOG // CHANGELOG
// (minor and older changes stripped away, please see git history for details) // (minor and older changes stripped away, please see git history for details)
// 2018-03-03: Vulkan: Various refactor, created a couple of ImGui_ImplVulkanH_XXX helper that the example can use and that viewport support will use.
// 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology. // 2018-03-01: Vulkan: Renamed ImGui_ImplVulkan_Init_Info to ImGui_ImplVulkan_InitInfo and fields to match more closely Vulkan terminology.
// 2018-02-18: Vulkan: Offset projection matrix and clipping rectangle by io.DisplayPos (which will be non-zero for multi-viewport applications). // 2018-02-18: Vulkan: Offset projection matrix and clipping rectangle by io.DisplayPos (which will be non-zero for multi-viewport applications).
// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself. // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself.
@ -720,7 +721,6 @@ void ImGui_ImplVulkan_NewFrame()
void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer) void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer)
{ {
ImGui::Render();
ImGui_ImplVulkan_RenderDrawData(command_buffer, ImGui::GetDrawData()); ImGui_ImplVulkan_RenderDrawData(command_buffer, ImGui::GetDrawData());
g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
} }
@ -821,10 +821,53 @@ VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_d
return VK_PRESENT_MODE_FIFO_KHR; // Always available return VK_PRESENT_MODE_FIFO_KHR; // Always available
} }
void ImGui_ImplVulkanH_CreateOrResizeWindowData(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h) void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator)
{ {
IM_ASSERT(physical_device != NULL && device != NULL); IM_ASSERT(physical_device != NULL && device != NULL);
(void)allocator;
// Create Command Buffers
VkResult err;
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
{
VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.queueFamilyIndex = queue_family;
err = vkCreateCommandPool(device, &info, allocator, &fd->CommandPool);
check_vk_result(err);
}
{
VkCommandBufferAllocateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.commandPool = fd->CommandPool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
err = vkAllocateCommandBuffers(device, &info, &fd->CommandBuffer);
check_vk_result(err);
}
{
VkFenceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
err = vkCreateFence(device, &info, allocator, &fd->Fence);
check_vk_result(err);
}
{
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
err = vkCreateSemaphore(device, &info, allocator, &fd->PresentCompleteSemaphore);
check_vk_result(err);
err = vkCreateSemaphore(device, &info, allocator, &fd->RenderCompleteSemaphore);
check_vk_result(err);
}
}
}
void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h)
{
VkResult err; VkResult err;
VkSwapchainKHR old_swapchain = wd->Swapchain; VkSwapchainKHR old_swapchain = wd->Swapchain;
err = vkDeviceWaitIdle(device); err = vkDeviceWaitIdle(device);
@ -972,6 +1015,7 @@ void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, I
vkDestroyRenderPass(device, wd->RenderPass, allocator); vkDestroyRenderPass(device, wd->RenderPass, allocator);
vkDestroySwapchainKHR(device, wd->Swapchain, allocator); vkDestroySwapchainKHR(device, wd->Swapchain, allocator);
vkDestroySurfaceKHR(instance, wd->Surface, allocator); vkDestroySurfaceKHR(instance, wd->Surface, allocator);
*wd = ImGui_ImplVulkan_WindowData();
} }
//-------------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------------

View File

@ -47,12 +47,12 @@ IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects();
struct ImGui_ImplVulkan_FrameData; struct ImGui_ImplVulkan_FrameData;
struct ImGui_ImplVulkan_WindowData; struct ImGui_ImplVulkan_WindowData;
struct ImGui_ImplVulkan_WindowDataCreateInfo;
IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, uint32_t queue_family, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
IMGUI_API void ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h);
IMGUI_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space);
IMGUI_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); IMGUI_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count);
IMGUI_API void ImGui_ImplVulkanH_CreateOrResizeWindowData(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator, int w, int h);
IMGUI_API void ImGui_ImplVulkanH_DestroyWindowData(VkInstance instance, VkDevice device, ImGui_ImplVulkan_WindowData* wd, const VkAllocationCallbacks* allocator);
struct ImGui_ImplVulkan_FrameData struct ImGui_ImplVulkan_FrameData
{ {
@ -68,7 +68,8 @@ struct ImGui_ImplVulkan_FrameData
struct ImGui_ImplVulkan_WindowData struct ImGui_ImplVulkan_WindowData
{ {
int Width, Height; int Width;
int Height;
VkSwapchainKHR Swapchain; VkSwapchainKHR Swapchain;
VkSurfaceKHR Surface; VkSurfaceKHR Surface;
VkSurfaceFormatKHR SurfaceFormat; VkSurfaceFormatKHR SurfaceFormat;

View File

@ -44,10 +44,12 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags,
} }
#endif // IMGUI_VULKAN_DEBUG_REPORT #endif // IMGUI_VULKAN_DEBUG_REPORT
static void CreateVulkanInstance(const char** extensions, uint32_t extensions_count) static void SetupVulkan(const char** extensions, uint32_t extensions_count)
{ {
VkResult err; VkResult err;
// Create Vulkan Instance
{
VkInstanceCreateInfo create_info = {}; VkInstanceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.enabledExtensionCount = extensions_count; create_info.enabledExtensionCount = extensions_count;
@ -88,13 +90,7 @@ static void CreateVulkanInstance(const char** extensions, uint32_t extensions_co
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err); check_vk_result(err);
#endif #endif
} }
static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
{
IM_ASSERT(wd->Surface != NULL);
VkResult err;
// Select GPU // Select GPU
{ {
@ -129,34 +125,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
IM_ASSERT(g_QueueFamily != -1); IM_ASSERT(g_QueueFamily != -1);
} }
// Check for WSI support
{
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
exit(-1);
}
}
// Get Surface Format
{
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
}
// Get Present Mode
{
#ifdef IMGUI_UNLIMITED_FRAME_RATE
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
#else
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
}
// Create Logical Device (with 1 queue) // Create Logical Device (with 1 queue)
{ {
int device_extension_count = 1; int device_extension_count = 1;
@ -178,44 +146,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
} }
// Create Command Buffers
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
{
VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.queueFamilyIndex = g_QueueFamily;
err = vkCreateCommandPool(g_Device, &info, g_Allocator, &fd->CommandPool);
check_vk_result(err);
}
{
VkCommandBufferAllocateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.commandPool = fd->CommandPool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer);
check_vk_result(err);
}
{
VkFenceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence);
check_vk_result(err);
}
{
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->PresentCompleteSemaphore);
check_vk_result(err);
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->RenderCompleteSemaphore);
check_vk_result(err);
}
}
// Create Descriptor Pool // Create Descriptor Pool
{ {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
@ -243,11 +173,42 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
} }
} }
static void cleanup_vulkan() static void SetupVulkanWindowData(ImGui_ImplVulkan_WindowData* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
exit(-1);
}
// Get Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Get Present Mode
#ifdef IMGUI_UNLIMITED_FRAME_RATE
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
#else
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
// Create SwapChain, RenderPass, Framebuffer, etc.
ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
}
static void CleanupVulkan()
{ {
ImGui_ImplVulkan_WindowData* wd = &g_WindowData; ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator); ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef IMGUI_VULKAN_DEBUG_REPORT
// Remove the debug report callback // Remove the debug report callback
@ -259,7 +220,7 @@ static void cleanup_vulkan()
vkDestroyInstance(g_Instance, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator);
} }
static void frame_begin(ImGui_ImplVulkan_WindowData* wd) static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
{ {
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex]; ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkResult err; VkResult err;
@ -296,7 +257,7 @@ static void frame_begin(ImGui_ImplVulkan_WindowData* wd)
} }
} }
static void frame_end(ImGui_ImplVulkan_WindowData* wd) static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
{ {
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex]; ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkResult err; VkResult err;
@ -322,14 +283,14 @@ static void frame_end(ImGui_ImplVulkan_WindowData* wd)
} }
} }
static void frame_present(ImGui_ImplVulkan_WindowData* wd) static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
{ {
VkResult err; VkResult err;
// If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame // If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame
#ifdef IMGUI_UNLIMITED_FRAME_RATE #ifdef IMGUI_UNLIMITED_FRAME_RATE
uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES; uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES;
#else #else
uint32_t PresentIndex = g_FrameIndex; uint32_t PresentIndex = wd->FrameIndex;
#endif // IMGUI_UNLIMITED_FRAME_RATE #endif // IMGUI_UNLIMITED_FRAME_RATE
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex]; ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex];
@ -359,34 +320,29 @@ int main(int, char**)
SDL_Window* window = SDL_CreateWindow("ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_VULKAN|SDL_WINDOW_RESIZABLE); SDL_Window* window = SDL_CreateWindow("ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, SDL_WINDOW_VULKAN|SDL_WINDOW_RESIZABLE);
// Setup Vulkan // Setup Vulkan
uint32_t sdl_extensions_count; uint32_t extensions_count = 0;
SDL_Vulkan_GetInstanceExtensions(window, &sdl_extensions_count, NULL); SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, NULL);
const char** sdl_extensions = new const char*[sdl_extensions_count]; const char** extensions = new const char*[extensions_count];
SDL_Vulkan_GetInstanceExtensions(window, &sdl_extensions_count, sdl_extensions); SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, extensions);
CreateVulkanInstance(sdl_extensions, sdl_extensions_count); SetupVulkan(extensions, extensions_count);
delete[] sdl_extensions; delete[] extensions;
// Create Window Surface // Create Window Surface
ImGui_ImplVulkan_WindowData* wd = &g_WindowData; VkSurfaceKHR surface;
SDL_bool result = SDL_Vulkan_CreateSurface(window, g_Instance, &wd->Surface); if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
if (result == 0)
{ {
printf("Failed to create Vulkan surface.\n"); printf("Failed to create Vulkan surface.\n");
return 1; return 1;
} }
SetupVulkan(wd);
// Create Framebuffers // Create Framebuffers
{
int w, h; int w, h;
SDL_GetWindowSize(window, &w, &h); SDL_GetWindowSize(window, &w, &h);
ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, wd, g_Allocator, w, h); ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
} SetupVulkanWindowData(wd, surface, w, h);
// Setup ImGui binding // Setup ImGui binding
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_MultiViewports; io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
@ -399,8 +355,8 @@ int main(int, char**)
init_info.DescriptorPool = g_DescriptorPool; init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator; init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result; init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
ImGui_ImplSDL2_Init(window, NULL); ImGui_ImplSDL2_Init(window, NULL);
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
// Setup style // Setup style
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
@ -473,7 +429,7 @@ int main(int, char**)
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
done = true; done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window)) if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2); ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, (int)event.window.data1, (int)event.window.data2);
} }
ImGui_ImplVulkan_NewFrame(); ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame(window); ImGui_ImplSDL2_NewFrame(window);
@ -516,10 +472,11 @@ int main(int, char**)
} }
// Rendering // Rendering
ImGui::Render();
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
frame_begin(wd); FrameBegin(wd);
ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer); ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
frame_end(wd); FrameEnd(wd);
ImGui::RenderAdditionalViewports(); ImGui::RenderAdditionalViewports();
@ -527,9 +484,9 @@ int main(int, char**)
// When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before. // When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before.
// Hence we must render once and increase the FrameIndex without presenting. // Hence we must render once and increase the FrameIndex without presenting.
if (swap_chain_has_at_least_one_image) if (swap_chain_has_at_least_one_image)
frame_present(wd); FramePresent(wd);
#else #else
frame_present(wd); FramePresent(wd);
#endif #endif
swap_chain_has_at_least_one_image = true; swap_chain_has_at_least_one_image = true;
wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
@ -542,7 +499,7 @@ int main(int, char**)
ImGui_ImplSDL2_Shutdown(); ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
cleanup_vulkan(); CleanupVulkan();
SDL_Quit(); SDL_Quit();
return 0; return 0;

View File

@ -47,10 +47,12 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags,
} }
#endif // IMGUI_VULKAN_DEBUG_REPORT #endif // IMGUI_VULKAN_DEBUG_REPORT
static void CreateVulkanInstance(const char** extensions, uint32_t extensions_count) static void SetupVulkan(const char** extensions, uint32_t extensions_count)
{ {
VkResult err; VkResult err;
// Create Vulkan Instance
{
VkInstanceCreateInfo create_info = {}; VkInstanceCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
create_info.enabledExtensionCount = extensions_count; create_info.enabledExtensionCount = extensions_count;
@ -91,13 +93,7 @@ static void CreateVulkanInstance(const char** extensions, uint32_t extensions_co
err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); err = vkCreateInstance(&create_info, g_Allocator, &g_Instance);
check_vk_result(err); check_vk_result(err);
#endif #endif
} }
static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
{
IM_ASSERT(wd->Surface != NULL);
VkResult err;
// Select GPU // Select GPU
{ {
@ -132,34 +128,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
IM_ASSERT(g_QueueFamily != -1); IM_ASSERT(g_QueueFamily != -1);
} }
// Check for WSI support
{
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
exit(-1);
}
}
// Get Surface Format
{
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
}
// Get Present Mode
{
#ifdef IMGUI_UNLIMITED_FRAME_RATE
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
#else
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
}
// Create Logical Device (with 1 queue) // Create Logical Device (with 1 queue)
{ {
int device_extension_count = 1; int device_extension_count = 1;
@ -181,44 +149,6 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue);
} }
// Create Command Buffers
for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++)
{
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[i];
{
VkCommandPoolCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
info.queueFamilyIndex = g_QueueFamily;
err = vkCreateCommandPool(g_Device, &info, g_Allocator, &fd->CommandPool);
check_vk_result(err);
}
{
VkCommandBufferAllocateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
info.commandPool = fd->CommandPool;
info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
info.commandBufferCount = 1;
err = vkAllocateCommandBuffers(g_Device, &info, &fd->CommandBuffer);
check_vk_result(err);
}
{
VkFenceCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
info.flags = VK_FENCE_CREATE_SIGNALED_BIT;
err = vkCreateFence(g_Device, &info, g_Allocator, &fd->Fence);
check_vk_result(err);
}
{
VkSemaphoreCreateInfo info = {};
info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->PresentCompleteSemaphore);
check_vk_result(err);
err = vkCreateSemaphore(g_Device, &info, g_Allocator, &fd->RenderCompleteSemaphore);
check_vk_result(err);
}
}
// Create Descriptor Pool // Create Descriptor Pool
{ {
VkDescriptorPoolSize pool_sizes[] = VkDescriptorPoolSize pool_sizes[] =
@ -246,11 +176,42 @@ static void SetupVulkan(ImGui_ImplVulkan_WindowData* wd)
} }
} }
static void cleanup_vulkan() static void SetupVulkanWindowData(ImGui_ImplVulkan_WindowData* wd, VkSurfaceKHR surface, int width, int height)
{
wd->Surface = surface;
// Check for WSI support
VkBool32 res;
vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, wd->Surface, &res);
if (res != VK_TRUE)
{
fprintf(stderr, "Error no WSI support on physical device 0\n");
exit(-1);
}
// Get Surface Format
const VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM };
const VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
wd->SurfaceFormat = ImGui_ImplVulkanH_SelectSurfaceFormat(g_PhysicalDevice, wd->Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace);
// Get Present Mode
#ifdef IMGUI_UNLIMITED_FRAME_RATE
VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
#else
VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR;
#endif
wd->PresentMode = ImGui_ImplVulkanH_SelectPresentMode(g_PhysicalDevice, wd->Surface, &present_mode, 1);
// Create SwapChain, RenderPass, Framebuffer, etc.
ImGui_ImplVulkanH_CreateWindowDataCommandBuffers(g_PhysicalDevice, g_Device, g_QueueFamily, wd, g_Allocator);
ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, wd, g_Allocator, width, height);
}
static void CleanupVulkan()
{ {
ImGui_ImplVulkan_WindowData* wd = &g_WindowData; ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator); ImGui_ImplVulkanH_DestroyWindowData(g_Instance, g_Device, wd, g_Allocator);
vkDestroyDescriptorPool(g_Device, g_DescriptorPool, g_Allocator);
#ifdef IMGUI_VULKAN_DEBUG_REPORT #ifdef IMGUI_VULKAN_DEBUG_REPORT
// Remove the debug report callback // Remove the debug report callback
@ -262,7 +223,7 @@ static void cleanup_vulkan()
vkDestroyInstance(g_Instance, g_Allocator); vkDestroyInstance(g_Instance, g_Allocator);
} }
static void frame_begin(ImGui_ImplVulkan_WindowData* wd) static void FrameBegin(ImGui_ImplVulkan_WindowData* wd)
{ {
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex]; ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkResult err; VkResult err;
@ -299,7 +260,7 @@ static void frame_begin(ImGui_ImplVulkan_WindowData* wd)
} }
} }
static void frame_end(ImGui_ImplVulkan_WindowData* wd) static void FrameEnd(ImGui_ImplVulkan_WindowData* wd)
{ {
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex]; ImGui_ImplVulkan_FrameData* fd = &wd->Frames[wd->FrameIndex];
VkResult err; VkResult err;
@ -325,14 +286,14 @@ static void frame_end(ImGui_ImplVulkan_WindowData* wd)
} }
} }
static void frame_present(ImGui_ImplVulkan_WindowData* wd) static void FramePresent(ImGui_ImplVulkan_WindowData* wd)
{ {
VkResult err; VkResult err;
// If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame // If IMGUI_UNLIMITED_FRAME_RATE is defined we present the latest but one frame. Otherwise we present the latest rendered frame
#ifdef IMGUI_UNLIMITED_FRAME_RATE #ifdef IMGUI_UNLIMITED_FRAME_RATE
uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES; uint32_t PresentIndex = (wd->FrameIndex + IMGUI_VK_QUEUED_FRAMES - 1) % IMGUI_VK_QUEUED_FRAMES;
#else #else
uint32_t PresentIndex = g_FrameIndex; uint32_t PresentIndex = wd->FrameIndex;
#endif // IMGUI_UNLIMITED_FRAME_RATE #endif // IMGUI_UNLIMITED_FRAME_RATE
ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex]; ImGui_ImplVulkan_FrameData* fd = &wd->Frames[PresentIndex];
@ -354,7 +315,7 @@ static void glfw_error_callback(int error, const char* description)
static void glfw_resize_callback(GLFWwindow*, int w, int h) static void glfw_resize_callback(GLFWwindow*, int w, int h)
{ {
ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, w, h); ImGui_ImplVulkanH_CreateWindowDataSwapChainAndFramebuffer(g_PhysicalDevice, g_Device, &g_WindowData, g_Allocator, w, h);
} }
int main(int, char**) int main(int, char**)
@ -373,26 +334,24 @@ int main(int, char**)
printf("GLFW: Vulkan Not Supported\n"); printf("GLFW: Vulkan Not Supported\n");
return 1; return 1;
} }
uint32_t glfw_extensions_count = 0; uint32_t extensions_count = 0;
const char** glfw_extensions = glfwGetRequiredInstanceExtensions(&glfw_extensions_count); const char** extensions = glfwGetRequiredInstanceExtensions(&extensions_count);
CreateVulkanInstance(glfw_extensions, glfw_extensions_count); SetupVulkan(extensions, extensions_count);
// Create Window Surface // Create Window Surface
ImGui_ImplVulkan_WindowData* wd = &g_WindowData; VkSurfaceKHR surface;
VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &wd->Surface); VkResult err = glfwCreateWindowSurface(g_Instance, window, g_Allocator, &surface);
check_vk_result(err); check_vk_result(err);
SetupVulkan(wd);
// Create Framebuffers // Create Framebuffers
int w, h; int w, h;
glfwGetFramebufferSize(window, &w, &h); glfwGetFramebufferSize(window, &w, &h);
ImGui_ImplVulkanH_CreateOrResizeWindowData(g_PhysicalDevice, g_Device, wd, g_Allocator, w, h);
glfwSetFramebufferSizeCallback(window, glfw_resize_callback); glfwSetFramebufferSizeCallback(window, glfw_resize_callback);
ImGui_ImplVulkan_WindowData* wd = &g_WindowData;
SetupVulkanWindowData(wd, surface, w, h);
// Setup ImGui binding // Setup ImGui binding
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io; ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_MultiViewports; io.ConfigFlags |= ImGuiConfigFlags_MultiViewports;
//io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
@ -405,8 +364,8 @@ int main(int, char**)
init_info.DescriptorPool = g_DescriptorPool; init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator; init_info.Allocator = g_Allocator;
init_info.CheckVkResultFn = check_vk_result; init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
ImGui_ImplGlfw_InitForVulkan(window, true); ImGui_ImplGlfw_InitForVulkan(window, true);
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
// Setup style // Setup style
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
@ -513,10 +472,11 @@ int main(int, char**)
} }
// Rendering // Rendering
ImGui::Render();
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float)); memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
frame_begin(wd); FrameBegin(wd);
ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer); ImGui_ImplVulkan_Render(wd->Frames[wd->FrameIndex].CommandBuffer);
frame_end(wd); FrameEnd(wd);
ImGui::RenderAdditionalViewports(); ImGui::RenderAdditionalViewports();
@ -524,9 +484,9 @@ int main(int, char**)
// When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before. // When IMGUI_UNLIMITED_FRAME_RATE is defined we render into latest image acquired from the swapchain but we display the image which was rendered before.
// Hence we must render once and increase the FrameIndex without presenting. // Hence we must render once and increase the FrameIndex without presenting.
if (swap_chain_has_at_least_one_image) if (swap_chain_has_at_least_one_image)
frame_present(wd); FramePresent(wd);
#else #else
frame_present(wd); FramePresent(wd);
#endif #endif
swap_chain_has_at_least_one_image = true; swap_chain_has_at_least_one_image = true;
wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; wd->FrameIndex = (wd->FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES;
@ -538,7 +498,7 @@ int main(int, char**)
ImGui_ImplVulkan_Shutdown(); ImGui_ImplVulkan_Shutdown();
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext(); ImGui::DestroyContext();
cleanup_vulkan(); CleanupVulkan();
glfwTerminate(); glfwTerminate();
return 0; return 0;