diff --git a/examples/imgui_impl_glfw.cpp b/examples/imgui_impl_glfw.cpp index aebdf26f5..f5fce96c2 100644 --- a/examples/imgui_impl_glfw.cpp +++ b/examples/imgui_impl_glfw.cpp @@ -176,6 +176,7 @@ static void ImGui_ImplGlfw_UpdateMouse() io.MouseHoveredViewport = 0; // Update buttons + ImGuiIO& io = ImGui::GetIO(); for (int i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) { // If a mouse press event came, always pass it as "mouse held this frame", so we don't miss click-release events that are shorter than 1 frame. diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 312bb486f..2e4ca7af3 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -11,7 +11,8 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2018-XX-XX: Vulkan: Offset projection matrix and clipping rectangle by io.DisplayPos (which will be non-zero for multi-viewport applications). +// 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-16: Misc: Obsoleted the io.RenderDrawListsFn callback, ImGui_ImplVulkan_Render() calls ImGui_ImplVulkan_RenderDrawData() itself. // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. // 2017-05-15: Vulkan: Fix scissor offset being negative. Fix new Vulkan validation warnings. Set required depth member for buffer image copy. @@ -23,13 +24,13 @@ #include "imgui_impl_vulkan.h" // Vulkan data -static VkAllocationCallbacks* g_Allocator = NULL; -static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; -static VkDevice g_Device = VK_NULL_HANDLE; -static VkRenderPass g_RenderPass = VK_NULL_HANDLE; -static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; -static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; -static void (*g_CheckVkResult)(VkResult err) = NULL; +static const VkAllocationCallbacks* g_Allocator = NULL; +static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; +static VkDevice g_Device = VK_NULL_HANDLE; +static VkRenderPass g_RenderPass = VK_NULL_HANDLE; +static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; +static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; +static void (*g_CheckVkResult)(VkResult err) = NULL; static VkCommandBuffer g_CommandBuffer = VK_NULL_HANDLE; static VkDeviceSize g_BufferMemoryAlignment = 256; @@ -133,7 +134,7 @@ static uint32_t __glsl_shader_frag_spv[] = static uint32_t ImGui_ImplVulkan_MemoryType(VkMemoryPropertyFlags properties, uint32_t type_bits) { VkPhysicalDeviceMemoryProperties prop; - vkGetPhysicalDeviceMemoryProperties(g_Gpu, &prop); + vkGetPhysicalDeviceMemoryProperties(g_PhysicalDevice, &prop); for (uint32_t i = 0; i < prop.memoryTypeCount; i++) if ((prop.memoryTypes[i].propertyFlags & properties) == properties && type_bits & (1<allocator; - g_Gpu = init_data->gpu; - g_Device = init_data->device; - g_RenderPass = init_data->render_pass; - g_PipelineCache = init_data->pipeline_cache; - g_DescriptorPool = init_data->descriptor_pool; - g_CheckVkResult = init_data->check_vk_result; + g_Allocator = init_data->Allocator; + g_PhysicalDevice = init_data->PhysicalDevice; + g_Device = init_data->Device; + g_RenderPass = init_data->RenderPass; + g_PipelineCache = init_data->PipelineCache; + g_DescriptorPool = init_data->DescriptorPool; + g_CheckVkResult = init_data->CheckVkResultFn; ImGui_ImplVulkan_CreateDeviceObjects(); return true; @@ -719,3 +720,73 @@ void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer) g_CommandBuffer = VK_NULL_HANDLE; g_FrameIndex = (g_FrameIndex + 1) % IMGUI_VK_QUEUED_FRAMES; } + +//------------------------------------------------------------------------- +// Miscellaneous Vulkan Helpers +// (Those are currently not strictly needed by the binding, but will be once if we support multi-viewports) +//------------------------------------------------------------------------- + +#include // malloc + +VkSurfaceFormatKHR ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space) +{ + IM_ASSERT(request_formats != NULL); + IM_ASSERT(request_formats_count > 0); + + // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation + // Assuming that the default behavior is without setting this bit, there is no need for separate Swapchain image and image view format + // Additionally several new color spaces were introduced with Vulkan Spec v1.0.40, + // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used. + uint32_t avail_count; + vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, NULL); + ImVector avail_format; + avail_format.resize((int)avail_count); + vkGetPhysicalDeviceSurfaceFormatsKHR(physical_device, surface, &avail_count, avail_format.Data); + + // First check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available + if (avail_count == 1) + { + if (avail_format[0].format == VK_FORMAT_UNDEFINED) + { + VkSurfaceFormatKHR ret; + ret.format = request_formats[0]; + ret.colorSpace = request_color_space; + return ret; + } + else + { + // No point in searching another format + return avail_format[0]; + } + } + else + { + // Request several formats, the first found will be used + for (int request_i = 0; request_i < request_formats_count; request_i++) + for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++) + if (avail_format[avail_i].format == request_formats[request_i] && avail_format[avail_i].colorSpace == request_color_space) + return avail_format[avail_i]; + + // If none of the requested image formats could be found, use the first available + return avail_format[0]; + } +} + +VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count) +{ + IM_ASSERT(request_modes != NULL); + IM_ASSERT(request_modes_count > 0); + + // Request a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory + uint32_t avail_count = 0; + vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, NULL); + ImVector avail_modes; + avail_modes.resize((int)avail_count); + vkGetPhysicalDeviceSurfacePresentModesKHR(physical_device, surface, &avail_count, avail_modes.Data); + for (int request_i = 0; request_i < request_modes_count; request_i++) + for (uint32_t avail_i = 0; avail_i < avail_count; avail_i++) + if (request_modes[request_i] == avail_modes[avail_i]) + return request_modes[request_i]; + + return VK_PRESENT_MODE_FIFO_KHR; // Always available +} diff --git a/examples/imgui_impl_vulkan.h b/examples/imgui_impl_vulkan.h index c27c11eeb..188f0e111 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -13,18 +13,18 @@ #define IMGUI_VK_QUEUED_FRAMES 2 -struct ImGui_ImplVulkan_InitData +struct ImGui_ImplVulkan_InitInfo { - VkAllocationCallbacks* allocator; - VkPhysicalDevice gpu; - VkDevice device; - VkRenderPass render_pass; - VkPipelineCache pipeline_cache; - VkDescriptorPool descriptor_pool; - void (*check_vk_result)(VkResult err); + const VkAllocationCallbacks* Allocator; + VkPhysicalDevice PhysicalDevice; + VkDevice Device; + VkRenderPass RenderPass; + VkPipelineCache PipelineCache; + VkDescriptorPool DescriptorPool; + void (*CheckVkResultFn)(VkResult err); }; -IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitData *init_data); +IMGUI_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo *init_data); IMGUI_API void ImGui_ImplVulkan_Shutdown(); IMGUI_API void ImGui_ImplVulkan_NewFrame(); IMGUI_API void ImGui_ImplVulkan_Render(VkCommandBuffer command_buffer); @@ -34,3 +34,7 @@ IMGUI_API void ImGui_ImplVulkan_InvalidateFontUploadObjects(); IMGUI_API void ImGui_ImplVulkan_InvalidateDeviceObjects(); IMGUI_API bool ImGui_ImplVulkan_CreateFontsTexture(VkCommandBuffer command_buffer); IMGUI_API bool ImGui_ImplVulkan_CreateDeviceObjects(); + +// Miscellaneous Vulkan Helpers +IMGUI_API VkSurfaceFormatKHR ImGui_ImplVulkan_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); +IMGUI_API VkPresentModeKHR ImGui_ImplVulkan_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); diff --git a/examples/opengl3_example/main.cpp b/examples/opengl3_example/main.cpp index 2cb6af1b8..cfdfb0c0d 100644 --- a/examples/opengl3_example/main.cpp +++ b/examples/opengl3_example/main.cpp @@ -38,6 +38,7 @@ int main(int, char**) io.ConfigFlags |= ImGuiConfigFlags_MultiViewports; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls //io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls + ImGui_ImplGlfw_Init(window, true); ImGui_ImplOpenGL3_Init(); diff --git a/examples/sdl_vulkan_example/main.cpp b/examples/sdl_vulkan_example/main.cpp index 2f869de1c..42d6c349a 100644 --- a/examples/sdl_vulkan_example/main.cpp +++ b/examples/sdl_vulkan_example/main.cpp @@ -9,25 +9,25 @@ #include #include +// FIXME-VULKAN: Resizing with IMGUI_UNLIMITED_FRAME_RATE triggers errors from the validation layer. #define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 #define IMGUI_UNLIMITED_FRAME_RATE -//#ifdef _DEBUG -//#define IMGUI_VULKAN_DEBUG_REPORT -//#endif +#ifdef _DEBUG +#define IMGUI_VULKAN_DEBUG_REPORT +#endif static VkAllocationCallbacks* g_Allocator = NULL; static VkInstance g_Instance = VK_NULL_HANDLE; static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; -static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; static VkDevice g_Device = VK_NULL_HANDLE; static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; static VkRenderPass g_RenderPass = VK_NULL_HANDLE; -static uint32_t g_QueueFamily = 0; +static uint32_t g_QueueFamily = (uint32_t)-1; static VkQueue g_Queue = VK_NULL_HANDLE; -static VkDebugReportCallbackEXT g_Debug_Report = VK_NULL_HANDLE; +static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE; static VkSurfaceFormatKHR g_SurfaceFormat; -static VkImageSubresourceRange g_ImageRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; static VkPresentModeKHR g_PresentMode; static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; @@ -57,24 +57,25 @@ static void check_vk_result(VkResult err) abort(); } -static void resize_vulkan(SDL_Window*, int w, int h) +static void CreateOrResizeSwapChainAndFrameBuffer(int w, int h) { VkResult err; VkSwapchainKHR old_swapchain = g_Swapchain; err = vkDeviceWaitIdle(g_Device); check_vk_result(err); - // Destroy old Framebuffer: + // Destroy old Framebuffer for (uint32_t i = 0; i < g_BackBufferCount; i++) + { if (g_BackBufferView[i]) vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator); - for (uint32_t i = 0; i < g_BackBufferCount; i++) if (g_Framebuffer[i]) vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator); + } if (g_RenderPass) vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator); - // Create Swapchain: + // Create Swapchain { VkSwapchainCreateInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; @@ -82,15 +83,15 @@ static void resize_vulkan(SDL_Window*, int w, int h) info.imageFormat = g_SurfaceFormat.format; info.imageColorSpace = g_SurfaceFormat.colorSpace; info.imageArrayLayers = 1; - info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; info.presentMode = g_PresentMode; info.clipped = VK_TRUE; info.oldSwapchain = old_swapchain; VkSurfaceCapabilitiesKHR cap; - err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_Gpu, g_Surface, &cap); + err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_PhysicalDevice, g_Surface, &cap); check_vk_result(err); if (cap.maxImageCount > 0) info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount; @@ -99,17 +100,13 @@ static void resize_vulkan(SDL_Window*, int w, int h) if (cap.currentExtent.width == 0xffffffff) { - fb_width = w; - fb_height = h; - info.imageExtent.width = fb_width; - info.imageExtent.height = fb_height; + info.imageExtent.width = fb_width = w; + info.imageExtent.height = fb_height = h; } else { - fb_width = cap.currentExtent.width; - fb_height = cap.currentExtent.height; - info.imageExtent.width = fb_width; - info.imageExtent.height = fb_height; + info.imageExtent.width = fb_width = cap.currentExtent.width; + info.imageExtent.height = fb_height = cap.currentExtent.height; } err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain); check_vk_result(err); @@ -121,7 +118,7 @@ static void resize_vulkan(SDL_Window*, int w, int h) if (old_swapchain) vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator); - // Create the Render Pass: + // Create the Render Pass { VkAttachmentDescription attachment = {}; attachment.format = g_SurfaceFormat.format; @@ -159,7 +156,8 @@ static void resize_vulkan(SDL_Window*, int w, int h) info.components.g = VK_COMPONENT_SWIZZLE_G; info.components.b = VK_COMPONENT_SWIZZLE_B; info.components.a = VK_COMPONENT_SWIZZLE_A; - info.subresourceRange = g_ImageRange; + VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + info.subresourceRange = image_range; for (uint32_t i = 0; i < g_BackBufferCount; i++) { info.image = g_BackBuffer[i]; @@ -168,7 +166,7 @@ static void resize_vulkan(SDL_Window*, int w, int h) } } - // Create Framebuffer: + // Create Framebuffer { VkImageView attachment[1]; VkFramebufferCreateInfo info = {}; @@ -189,9 +187,9 @@ static void resize_vulkan(SDL_Window*, int w, int h) } #ifdef IMGUI_VULKAN_DEBUG_REPORT -static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report( - VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) { + (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguemnts printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); return VK_FALSE; } @@ -209,38 +207,36 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e create_info.ppEnabledExtensionNames = extensions; #ifdef IMGUI_VULKAN_DEBUG_REPORT - // enabling multiple validation layers grouped as lunarg standard validation + // Enabling multiple validation layers grouped as LunarG standard validation const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; - // need additional storage for char pointer to debug report extension - const char** extensions = (const char**)malloc(sizeof(const char*) * (extensions_count + 1)); - for (size_t i = 0; i < extensions_count; i++) - extensions[i] = extensions[i]; - extensions[extensions_count] = "VK_EXT_debug_report"; + // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it) + const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1)); + memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*)); + extensions_ext[extensions_count] = "VK_EXT_debug_report"; create_info.enabledExtensionCount = extensions_count + 1; - create_info.ppEnabledExtensionNames = extensions; + create_info.ppEnabledExtensionNames = extensions_ext; #endif // IMGUI_VULKAN_DEBUG_REPORT err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); check_vk_result(err); #ifdef IMGUI_VULKAN_DEBUG_REPORT - free(extensions); + free(extensions_ext); - // create the debug report callback + // Get the function pointer (required for any extensions) + auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); + IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL); + + // Setup the debug report callback VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; debug_report_ci.pfnCallback = debug_report; debug_report_ci.pUserData = NULL; - - // get the proc address of the function pointer, required for used extensions - PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = - (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); - - err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_Debug_Report); + err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); check_vk_result(err); #endif // IMGUI_VULKAN_DEBUG_REPORT } @@ -255,7 +251,7 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e } } - // Get GPU + // Select GPU { uint32_t gpu_count; err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL); @@ -268,31 +264,30 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e // If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose // e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc. // for sake of simplicity we'll just take the first one, assuming it has a graphics queue family. - g_Gpu = gpus[0]; + g_PhysicalDevice = gpus[0]; free(gpus); } - // Get queue + // Select graphics queue family { uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, NULL); + vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL); VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, queues); + vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); for (uint32_t i = 0; i < count; i++) - { if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { g_QueueFamily = i; break; } - } free(queues); + IM_ASSERT(g_QueueFamily != -1); } // Check for WSI support { VkBool32 res; - vkGetPhysicalDeviceSurfaceSupportKHR(g_Gpu, g_QueueFamily, g_Surface, &res); + vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, g_Surface, &res); if (res != VK_TRUE) { fprintf(stderr, "Error no WSI support on physical device 0\n"); @@ -302,93 +297,32 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e // Get Surface Format { - // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation - // Assuming that the default behavior is without setting this bit, there is no need for separate Spawchain image and image view format - // additionally several new color spaces were introduced with Vulkan Spec v1.0.40 - // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used - uint32_t count; - vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, NULL); - VkSurfaceFormatKHR *formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count); - vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, formats); - - // first check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available - if (count == 1) - { - if (formats[0].format == VK_FORMAT_UNDEFINED) - { - g_SurfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM; - g_SurfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - } - else - { // no point in searching another format - g_SurfaceFormat = formats[0]; - } - } - else - { - // request several formats, the first found will be used - VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; - VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - bool requestedFound = false; - for (size_t i = 0; i < sizeof(requestSurfaceImageFormat) / sizeof(requestSurfaceImageFormat[0]); i++) - { - if (requestedFound) - break; - for (uint32_t j = 0; j < count; j++) - { - if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace) - { - g_SurfaceFormat = formats[j]; - requestedFound = true; - } - } - } - - // if none of the requested image formats could be found, use the first available - if (!requestedFound) - g_SurfaceFormat = formats[0]; - } - free(formats); + 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; + g_SurfaceFormat = ImGui_ImplVulkan_SelectSurfaceFormat(g_PhysicalDevice, g_Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); } // Get Present Mode { - // Requst a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory #ifdef IMGUI_UNLIMITED_FRAME_RATE - g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; #else - g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; + VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; #endif - uint32_t count = 0; - vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, NULL); - VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, presentModes); - bool presentModeAvailable = false; - for (size_t i = 0; i < count; i++) - { - if (presentModes[i] == g_PresentMode) - { - presentModeAvailable = true; - break; - } - } - if (!presentModeAvailable) - g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // always available + g_PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, g_Surface, &present_mode, 1); } - // Create Logical Device + // Create Logical Device (with 1 queue) { int device_extension_count = 1; const char* device_extensions[] = { "VK_KHR_swapchain" }; - const uint32_t queue_index = 0; - const uint32_t queue_count = 1; const float queue_priority[] = { 1.0f }; VkDeviceQueueCreateInfo queue_info[1] = {}; queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info[0].queueFamilyIndex = g_QueueFamily; - queue_info[0].queueCount = queue_count; + queue_info[0].queueCount = 1; queue_info[0].pQueuePriorities = queue_priority; VkDeviceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -396,18 +330,20 @@ static void setup_vulkan(SDL_Window* window, const char** extensions, uint32_t e create_info.pQueueCreateInfos = queue_info; create_info.enabledExtensionCount = device_extension_count; create_info.ppEnabledExtensionNames = device_extensions; - err = vkCreateDevice(g_Gpu, &create_info, g_Allocator, &g_Device); + err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device); check_vk_result(err); - vkGetDeviceQueue(g_Device, g_QueueFamily, queue_index, &g_Queue); + vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); } + // Create Framebuffers { int w, h; SDL_GetWindowSize(window, &w, &h); - resize_vulkan(window, w, h); + CreateOrResizeSwapChainAndFrameBuffer(w, h); } + // Create Command Buffers for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { @@ -493,9 +429,9 @@ static void cleanup_vulkan() vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator); #ifdef IMGUI_VULKAN_DEBUG_REPORT - // get the proc address of the function pointer, required for used extensions + // Remove the debug report callback auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); - vkDestroyDebugReportCallbackEXT(g_Instance, g_Debug_Report, g_Allocator); + vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); #endif // IMGUI_VULKAN_DEBUG_REPORT vkDestroyDevice(g_Device, g_Allocator); @@ -613,18 +549,18 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); - ImGui_ImplVulkan_InitData init_data = {}; - init_data.allocator = g_Allocator; - init_data.gpu = g_Gpu; - init_data.device = g_Device; - init_data.render_pass = g_RenderPass; - init_data.pipeline_cache = g_PipelineCache; - init_data.descriptor_pool = g_DescriptorPool; - init_data.check_vk_result = check_vk_result; + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Allocator = g_Allocator; + init_info.PhysicalDevice = g_PhysicalDevice; + init_info.Device = g_Device; + init_info.RenderPass = g_RenderPass; + init_info.PipelineCache = g_PipelineCache; + init_info.DescriptorPool = g_DescriptorPool; + init_info.CheckVkResultFn = check_vk_result; ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - ImGui_ImplVulkan_Init(&init_data); + ImGui_ImplVulkan_Init(&init_info); ImGui_ImplSDL2_Init(window, NULL); // Setup style @@ -703,6 +639,8 @@ int main(int, char**) ImGui_ImplSDL2_ProcessEvent(&event); if (event.type == SDL_QUIT) done = true; + if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window)) + CreateOrResizeSwapChainAndFrameBuffer((int)event.window.data1, (int)event.window.data2); } ImGui_ImplVulkan_NewFrame(); ImGui_ImplSDL2_NewFrame(window); diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index 9c1b07963..4cfc49acb 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -12,25 +12,25 @@ #include #include +// FIXME-VULKAN: Resizing with IMGUI_UNLIMITED_FRAME_RATE triggers errors from the validation layer. #define IMGUI_MAX_POSSIBLE_BACK_BUFFERS 16 #define IMGUI_UNLIMITED_FRAME_RATE -//#ifdef _DEBUG -//#define IMGUI_VULKAN_DEBUG_REPORT -//#endif +#ifdef _DEBUG +#define IMGUI_VULKAN_DEBUG_REPORT +#endif static VkAllocationCallbacks* g_Allocator = NULL; static VkInstance g_Instance = VK_NULL_HANDLE; static VkSurfaceKHR g_Surface = VK_NULL_HANDLE; -static VkPhysicalDevice g_Gpu = VK_NULL_HANDLE; +static VkPhysicalDevice g_PhysicalDevice = VK_NULL_HANDLE; static VkDevice g_Device = VK_NULL_HANDLE; static VkSwapchainKHR g_Swapchain = VK_NULL_HANDLE; static VkRenderPass g_RenderPass = VK_NULL_HANDLE; -static uint32_t g_QueueFamily = 0; +static uint32_t g_QueueFamily = (uint32_t)-1; static VkQueue g_Queue = VK_NULL_HANDLE; -static VkDebugReportCallbackEXT g_Debug_Report = VK_NULL_HANDLE; +static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE; static VkSurfaceFormatKHR g_SurfaceFormat; -static VkImageSubresourceRange g_ImageRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; static VkPresentModeKHR g_PresentMode; static VkPipelineCache g_PipelineCache = VK_NULL_HANDLE; @@ -60,24 +60,25 @@ static void check_vk_result(VkResult err) abort(); } -static void resize_vulkan(GLFWwindow*, int w, int h) +static void CreateOrResizeSwapChainAndFrameBuffer(int w, int h) { VkResult err; VkSwapchainKHR old_swapchain = g_Swapchain; err = vkDeviceWaitIdle(g_Device); check_vk_result(err); - // Destroy old Framebuffer: + // Destroy old Framebuffer for (uint32_t i = 0; i < g_BackBufferCount; i++) + { if (g_BackBufferView[i]) vkDestroyImageView(g_Device, g_BackBufferView[i], g_Allocator); - for (uint32_t i = 0; i < g_BackBufferCount; i++) if (g_Framebuffer[i]) vkDestroyFramebuffer(g_Device, g_Framebuffer[i], g_Allocator); + } if (g_RenderPass) vkDestroyRenderPass(g_Device, g_RenderPass, g_Allocator); - // Create Swapchain: + // Create Swapchain { VkSwapchainCreateInfoKHR info = {}; info.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; @@ -85,15 +86,15 @@ static void resize_vulkan(GLFWwindow*, int w, int h) info.imageFormat = g_SurfaceFormat.format; info.imageColorSpace = g_SurfaceFormat.colorSpace; info.imageArrayLayers = 1; - info.imageUsage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family info.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; info.presentMode = g_PresentMode; info.clipped = VK_TRUE; info.oldSwapchain = old_swapchain; VkSurfaceCapabilitiesKHR cap; - err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_Gpu, g_Surface, &cap); + err = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_PhysicalDevice, g_Surface, &cap); check_vk_result(err); if (cap.maxImageCount > 0) info.minImageCount = (cap.minImageCount + 2 < cap.maxImageCount) ? (cap.minImageCount + 2) : cap.maxImageCount; @@ -102,17 +103,13 @@ static void resize_vulkan(GLFWwindow*, int w, int h) if (cap.currentExtent.width == 0xffffffff) { - fb_width = w; - fb_height = h; - info.imageExtent.width = fb_width; - info.imageExtent.height = fb_height; + info.imageExtent.width = fb_width = w; + info.imageExtent.height = fb_height = h; } else { - fb_width = cap.currentExtent.width; - fb_height = cap.currentExtent.height; - info.imageExtent.width = fb_width; - info.imageExtent.height = fb_height; + info.imageExtent.width = fb_width = cap.currentExtent.width; + info.imageExtent.height = fb_height = cap.currentExtent.height; } err = vkCreateSwapchainKHR(g_Device, &info, g_Allocator, &g_Swapchain); check_vk_result(err); @@ -124,7 +121,7 @@ static void resize_vulkan(GLFWwindow*, int w, int h) if (old_swapchain) vkDestroySwapchainKHR(g_Device, old_swapchain, g_Allocator); - // Create the Render Pass: + // Create the Render Pass { VkAttachmentDescription attachment = {}; attachment.format = g_SurfaceFormat.format; @@ -162,7 +159,8 @@ static void resize_vulkan(GLFWwindow*, int w, int h) info.components.g = VK_COMPONENT_SWIZZLE_G; info.components.b = VK_COMPONENT_SWIZZLE_B; info.components.a = VK_COMPONENT_SWIZZLE_A; - info.subresourceRange = g_ImageRange; + VkImageSubresourceRange image_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; + info.subresourceRange = image_range; for (uint32_t i = 0; i < g_BackBufferCount; i++) { info.image = g_BackBuffer[i]; @@ -171,7 +169,7 @@ static void resize_vulkan(GLFWwindow*, int w, int h) } } - // Create Framebuffer: + // Create Framebuffer { VkImageView attachment[1]; VkFramebufferCreateInfo info = {}; @@ -191,10 +189,15 @@ static void resize_vulkan(GLFWwindow*, int w, int h) } } -#ifdef IMGUI_VULKAN_DEBUG_REPORT -static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report( - VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) +static void GlfwResizeCallback(GLFWwindow*, int w, int h) { + CreateOrResizeSwapChainAndFrameBuffer(w, h); +} + +#ifdef IMGUI_VULKAN_DEBUG_REPORT +static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) +{ + (void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguemnts printf("[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage); return VK_FALSE; } @@ -212,38 +215,36 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e create_info.ppEnabledExtensionNames = extensions; #ifdef IMGUI_VULKAN_DEBUG_REPORT - // enabling multiple validation layers grouped as lunarg standard validation + // Enabling multiple validation layers grouped as LunarG standard validation const char* layers[] = { "VK_LAYER_LUNARG_standard_validation" }; create_info.enabledLayerCount = 1; create_info.ppEnabledLayerNames = layers; - // need additional storage for char pointer to debug report extension - const char** extensions = (const char**)malloc(sizeof(const char*) * (extensions_count + 1)); - for (size_t i = 0; i < extensions_count; i++) - extensions[i] = extensions[i]; - extensions[extensions_count] = "VK_EXT_debug_report"; + // Enable debug report extension (we need additional storage, so we duplicate the user array to add our new extension to it) + const char** extensions_ext = (const char**)malloc(sizeof(const char*) * (extensions_count + 1)); + memcpy(extensions_ext, extensions, extensions_count * sizeof(const char*)); + extensions_ext[extensions_count] = "VK_EXT_debug_report"; create_info.enabledExtensionCount = extensions_count + 1; - create_info.ppEnabledExtensionNames = extensions; + create_info.ppEnabledExtensionNames = extensions_ext; #endif // IMGUI_VULKAN_DEBUG_REPORT err = vkCreateInstance(&create_info, g_Allocator, &g_Instance); check_vk_result(err); #ifdef IMGUI_VULKAN_DEBUG_REPORT - free(extensions); + free(extensions_ext); - // create the debug report callback + // Get the function pointer (required for any extensions) + auto vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); + IM_ASSERT(vkCreateDebugReportCallbackEXT != NULL); + + // Setup the debug report callback VkDebugReportCallbackCreateInfoEXT debug_report_ci = {}; debug_report_ci.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; debug_report_ci.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT; debug_report_ci.pfnCallback = debug_report; debug_report_ci.pUserData = NULL; - - // get the proc address of the function pointer, required for used extensions - PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = - (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkCreateDebugReportCallbackEXT"); - - err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_Debug_Report); + err = vkCreateDebugReportCallbackEXT(g_Instance, &debug_report_ci, g_Allocator, &g_DebugReport); check_vk_result(err); #endif // IMGUI_VULKAN_DEBUG_REPORT } @@ -254,7 +255,7 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e check_vk_result(err); } - // Get GPU + // Select GPU { uint32_t gpu_count; err = vkEnumeratePhysicalDevices(g_Instance, &gpu_count, NULL); @@ -267,31 +268,30 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e // If a number >1 of GPUs got reported, you should find the best fit GPU for your purpose // e.g. VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU if available, or with the greatest memory available, etc. // for sake of simplicity we'll just take the first one, assuming it has a graphics queue family. - g_Gpu = gpus[0]; + g_PhysicalDevice = gpus[0]; free(gpus); } - // Get queue + // Select graphics queue family { uint32_t count; - vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, NULL); + vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, NULL); VkQueueFamilyProperties* queues = (VkQueueFamilyProperties*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceQueueFamilyProperties(g_Gpu, &count, queues); + vkGetPhysicalDeviceQueueFamilyProperties(g_PhysicalDevice, &count, queues); for (uint32_t i = 0; i < count; i++) - { if (queues[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { g_QueueFamily = i; break; } - } free(queues); + IM_ASSERT(g_QueueFamily != -1); } // Check for WSI support { VkBool32 res; - vkGetPhysicalDeviceSurfaceSupportKHR(g_Gpu, g_QueueFamily, g_Surface, &res); + vkGetPhysicalDeviceSurfaceSupportKHR(g_PhysicalDevice, g_QueueFamily, g_Surface, &res); if (res != VK_TRUE) { fprintf(stderr, "Error no WSI support on physical device 0\n"); @@ -299,95 +299,35 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e } } + // Get Surface Format { - // Per Spec Format and View Format are expected to be the same unless VK_IMAGE_CREATE_MUTABLE_BIT was set at image creation - // Assuming that the default behavior is without setting this bit, there is no need for separate Spawchain image and image view format - // additionally several new color spaces were introduced with Vulkan Spec v1.0.40 - // hence we must make sure that a format with the mostly available color space, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR, is found and used - uint32_t count; - vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, NULL); - VkSurfaceFormatKHR *formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count); - vkGetPhysicalDeviceSurfaceFormatsKHR(g_Gpu, g_Surface, &count, formats); - - // first check if only one format, VK_FORMAT_UNDEFINED, is available, which would imply that any format is available - if (count == 1) - { - if (formats[0].format == VK_FORMAT_UNDEFINED) - { - g_SurfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM; - g_SurfaceFormat.colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - } - else - { // no point in searching another format - g_SurfaceFormat = formats[0]; - } - } - else - { - // request several formats, the first found will be used - VkFormat requestSurfaceImageFormat[] = { VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8_UNORM, VK_FORMAT_R8G8B8_UNORM }; - VkColorSpaceKHR requestSurfaceColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; - bool requestedFound = false; - for (size_t i = 0; i < sizeof(requestSurfaceImageFormat) / sizeof(requestSurfaceImageFormat[0]); i++) - { - if (requestedFound) - break; - for (uint32_t j = 0; j < count; j++) - { - if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace) - { - g_SurfaceFormat = formats[j]; - requestedFound = true; - } - } - } - - // if none of the requested image formats could be found, use the first available - if (!requestedFound) - g_SurfaceFormat = formats[0]; - } - free(formats); + 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; + g_SurfaceFormat = ImGui_ImplVulkan_SelectSurfaceFormat(g_PhysicalDevice, g_Surface, requestSurfaceImageFormat, (size_t)IM_ARRAYSIZE(requestSurfaceImageFormat), requestSurfaceColorSpace); } // Get Present Mode { - // Requst a certain mode and confirm that it is available. If not use VK_PRESENT_MODE_FIFO_KHR which is mandatory #ifdef IMGUI_UNLIMITED_FRAME_RATE - g_PresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + VkPresentModeKHR present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR; #else - g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; + VkPresentModeKHR present_mode = VK_PRESENT_MODE_FIFO_KHR; #endif - uint32_t count = 0; - vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, NULL); - VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceSurfacePresentModesKHR(g_Gpu, g_Surface, &count, presentModes); - bool presentModeAvailable = false; - for (size_t i = 0; i < count; i++) - { - if (presentModes[i] == g_PresentMode) - { - presentModeAvailable = true; - break; - } - } - if (!presentModeAvailable) - g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // always available + g_PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, g_Surface, &present_mode, 1); } - // Create Logical Device + // Create Logical Device (with 1 queue) { int device_extension_count = 1; const char* device_extensions[] = { "VK_KHR_swapchain" }; - const uint32_t queue_index = 0; - const uint32_t queue_count = 1; const float queue_priority[] = { 1.0f }; VkDeviceQueueCreateInfo queue_info[1] = {}; queue_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_info[0].queueFamilyIndex = g_QueueFamily; - queue_info[0].queueCount = queue_count; + queue_info[0].queueCount = 1; queue_info[0].pQueuePriorities = queue_priority; VkDeviceCreateInfo create_info = {}; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; @@ -395,19 +335,21 @@ static void setup_vulkan(GLFWwindow* window, const char** extensions, uint32_t e create_info.pQueueCreateInfos = queue_info; create_info.enabledExtensionCount = device_extension_count; create_info.ppEnabledExtensionNames = device_extensions; - err = vkCreateDevice(g_Gpu, &create_info, g_Allocator, &g_Device); + err = vkCreateDevice(g_PhysicalDevice, &create_info, g_Allocator, &g_Device); check_vk_result(err); - vkGetDeviceQueue(g_Device, g_QueueFamily, queue_index, &g_Queue); + vkGetDeviceQueue(g_Device, g_QueueFamily, 0, &g_Queue); } + // Create Framebuffers { int w, h; glfwGetFramebufferSize(window, &w, &h); - resize_vulkan(window, w, h); - glfwSetFramebufferSizeCallback(window, resize_vulkan); + CreateOrResizeSwapChainAndFrameBuffer(w, h); + glfwSetFramebufferSizeCallback(window, GlfwResizeCallback); } + // Create Command Buffers for (int i = 0; i < IMGUI_VK_QUEUED_FRAMES; i++) { @@ -493,9 +435,9 @@ static void cleanup_vulkan() vkDestroySurfaceKHR(g_Instance, g_Surface, g_Allocator); #ifdef IMGUI_VULKAN_DEBUG_REPORT - // get the proc address of the function pointer, required for used extensions + // Remove the debug report callback auto vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(g_Instance, "vkDestroyDebugReportCallbackEXT"); - vkDestroyDebugReportCallbackEXT(g_Instance, g_Debug_Report, g_Allocator); + vkDestroyDebugReportCallbackEXT(g_Instance, g_DebugReport, g_Allocator); #endif // IMGUI_VULKAN_DEBUG_REPORT vkDestroyDevice(g_Device, g_Allocator); @@ -616,18 +558,19 @@ int main(int, char**) // Setup ImGui binding ImGui::CreateContext(); - ImGui_ImplVulkan_InitData init_data = {}; - init_data.allocator = g_Allocator; - init_data.gpu = g_Gpu; - init_data.device = g_Device; - init_data.render_pass = g_RenderPass; - init_data.pipeline_cache = g_PipelineCache; - init_data.descriptor_pool = g_DescriptorPool; - init_data.check_vk_result = check_vk_result; + ImGui_ImplVulkan_InitInfo init_info = {}; + init_info.Allocator = g_Allocator; + init_info.PhysicalDevice = g_PhysicalDevice; + init_info.Device = g_Device; + init_info.RenderPass = g_RenderPass; + init_info.PipelineCache = g_PipelineCache; + init_info.DescriptorPool = g_DescriptorPool; + init_info.CheckVkResultFn = check_vk_result; ImGuiIO& io = ImGui::GetIO(); (void)io; //io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls - ImGui_ImplVulkan_Init(&init_data); + + ImGui_ImplVulkan_Init(&init_info); ImGui_ImplGlfw_Init(window, true); // Setup style