diff --git a/examples/imgui_impl_vulkan.cpp b/examples/imgui_impl_vulkan.cpp index 70adbf5c..2e4ca7af 100644 --- a/examples/imgui_impl_vulkan.cpp +++ b/examples/imgui_impl_vulkan.cpp @@ -720,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 04ea473e..188f0e11 100644 --- a/examples/imgui_impl_vulkan.h +++ b/examples/imgui_impl_vulkan.h @@ -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/sdl_vulkan_example/main.cpp b/examples/sdl_vulkan_example/main.cpp index 24b02216..1be9584d 100644 --- a/examples/sdl_vulkan_example/main.cpp +++ b/examples/sdl_vulkan_example/main.cpp @@ -297,69 +297,20 @@ 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 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 count; - vkGetPhysicalDeviceSurfaceFormatsKHR(g_PhysicalDevice, g_Surface, &count, NULL); - VkSurfaceFormatKHR* formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count); - vkGetPhysicalDeviceSurfaceFormatsKHR(g_PhysicalDevice, 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 found = false; - for (size_t i = 0; found == false && i < sizeof(requestSurfaceImageFormat) / sizeof(requestSurfaceImageFormat[0]); i++) - for (uint32_t j = 0; j < count; j++) - if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace) - { - g_SurfaceFormat = formats[j]; - found = true; - } - - // If none of the requested image formats could be found, use the first available - if (!found) - 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 { - // Request 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_PhysicalDevice, g_Surface, &count, nullptr); - VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceSurfacePresentModesKHR(g_PhysicalDevice, g_Surface, &count, presentModes); - bool presentModeAvailable = false; - for (size_t i = 0; i < count && !presentModeAvailable; i++) - if (presentModes[i] == g_PresentMode) - presentModeAvailable = true; - if (!presentModeAvailable) - g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // Always available + g_PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, g_Surface, &present_mode, 1); } diff --git a/examples/vulkan_example/main.cpp b/examples/vulkan_example/main.cpp index e0c0fab3..5b82f5bc 100644 --- a/examples/vulkan_example/main.cpp +++ b/examples/vulkan_example/main.cpp @@ -294,71 +294,23 @@ 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 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 count; - vkGetPhysicalDeviceSurfaceFormatsKHR(g_PhysicalDevice, g_Surface, &count, NULL); - VkSurfaceFormatKHR* formats = (VkSurfaceFormatKHR*)malloc(sizeof(VkSurfaceFormatKHR) * count); - vkGetPhysicalDeviceSurfaceFormatsKHR(g_PhysicalDevice, 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 found = false; - for (size_t i = 0; found == false && i < sizeof(requestSurfaceImageFormat) / sizeof(requestSurfaceImageFormat[0]); i++) - for (uint32_t j = 0; j < count; j++) - if (formats[j].format == requestSurfaceImageFormat[i] && formats[j].colorSpace == requestSurfaceColorSpace) - { - g_SurfaceFormat = formats[j]; - found = true; - } - - // If none of the requested image formats could be found, use the first available - if (!found) - 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 { - // Request 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_PhysicalDevice, g_Surface, &count, nullptr); - VkPresentModeKHR* presentModes = (VkPresentModeKHR*)malloc(sizeof(VkQueueFamilyProperties) * count); - vkGetPhysicalDeviceSurfacePresentModesKHR(g_PhysicalDevice, g_Surface, &count, presentModes); - bool presentModeAvailable = false; - for (size_t i = 0; i < count && !presentModeAvailable; i++) - if (presentModes[i] == g_PresentMode) - presentModeAvailable = true; - if (!presentModeAvailable) - g_PresentMode = VK_PRESENT_MODE_FIFO_KHR; // Always available + g_PresentMode = ImGui_ImplVulkan_SelectPresentMode(g_PhysicalDevice, g_Surface, &present_mode, 1); }