diff --git a/src/VkBootstrap.cpp b/src/VkBootstrap.cpp index e0beb4b..98bc7b2 100644 --- a/src/VkBootstrap.cpp +++ b/src/VkBootstrap.cpp @@ -487,42 +487,6 @@ InstanceBuilder& InstanceBuilder::set_allocation_callbacks (VkAllocationCallback namespace detail { -struct SurfaceSupportDetails { - VkSurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector present_modes; -}; - -enum class SurfaceSupportError { - surface_handle_null, - failed_get_surface_capabilities, - failed_enumerate_surface_formats, - failed_enumerate_present_modes -}; - -Expected> query_surface_support_details ( - VkPhysicalDevice phys_device, VkSurfaceKHR surface) { - if (surface == VK_NULL_HANDLE) - return detail::Error{ SurfaceSupportError::surface_handle_null }; - - VkSurfaceCapabilitiesKHR capabilities; - VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (phys_device, surface, &capabilities); - if (res != VK_SUCCESS) { - return detail::Error{ SurfaceSupportError::failed_get_surface_capabilities, res }; - } - auto formats = detail::get_vector ( - vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface); - if (!formats.has_value ()) - return detail::Error{ SurfaceSupportError::failed_enumerate_surface_formats, - formats.error () }; - auto present_modes = detail::get_vector ( - vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface); - if (!present_modes.has_value ()) - return detail::Error{ SurfaceSupportError::failed_enumerate_present_modes, - formats.error () }; - return SurfaceSupportDetails{ capabilities, formats.value (), present_modes.value () }; -} - std::vector check_device_extension_support ( VkPhysicalDevice device, std::vector desired_extensions) { auto available_extensions = @@ -720,13 +684,17 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (Phy bool swapChainAdequate = false; - if (!system_info.headless) { - auto swapChainSupport_ret = - detail::query_surface_support_details (pd.phys_device, system_info.surface); - if (swapChainSupport_ret.has_value ()) { - auto swapchain_support = swapChainSupport_ret.value (); - swapChainAdequate = - !swapchain_support.formats.empty () && !swapchain_support.present_modes.empty (); + if (criteria.defer_surface_initialization) { + swapChainAdequate = true; + } else if (!system_info.headless) { + + auto formats = detail::get_vector ( + vkGetPhysicalDeviceSurfaceFormatsKHR, pd.phys_device, system_info.surface); + auto present_modes = detail::get_vector ( + vkGetPhysicalDeviceSurfacePresentModesKHR, pd.phys_device, system_info.surface); + + if (formats.has_value () && present_modes.has_value ()) { + swapChainAdequate = !formats.value ().empty () && !present_modes.value ().empty (); } } if (criteria.require_present && !swapChainAdequate) suitable = Suitable::no; @@ -892,6 +860,10 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features (VkPhysica criteria.required_features = features; return *this; } +PhysicalDeviceSelector& PhysicalDeviceSelector::defer_surface_initialization () { + criteria.defer_surface_initialization = true; + return *this; +} PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditionally (bool unconditionally) { criteria.use_first_gpu_unconditionally = unconditionally; return *this; @@ -1045,6 +1017,42 @@ DeviceBuilder& DeviceBuilder::set_allocation_callbacks (VkAllocationCallbacks* c } namespace detail { +struct SurfaceSupportDetails { + VkSurfaceCapabilitiesKHR capabilities; + std::vector formats; + std::vector present_modes; +}; + +enum class SurfaceSupportError { + surface_handle_null, + failed_get_surface_capabilities, + failed_enumerate_surface_formats, + failed_enumerate_present_modes +}; + +Expected> query_surface_support_details ( + VkPhysicalDevice phys_device, VkSurfaceKHR surface) { + if (surface == VK_NULL_HANDLE) + return detail::Error{ SurfaceSupportError::surface_handle_null }; + + VkSurfaceCapabilitiesKHR capabilities; + VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (phys_device, surface, &capabilities); + if (res != VK_SUCCESS) { + return detail::Error{ SurfaceSupportError::failed_get_surface_capabilities, res }; + } + auto formats = detail::get_vector ( + vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface); + if (!formats.has_value ()) + return detail::Error{ SurfaceSupportError::failed_enumerate_surface_formats, + formats.error () }; + auto present_modes = detail::get_vector ( + vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface); + if (!present_modes.has_value ()) + return detail::Error{ SurfaceSupportError::failed_enumerate_present_modes, + formats.error () }; + return SurfaceSupportDetails{ capabilities, formats.value (), present_modes.value () }; +} + VkSurfaceFormatKHR find_surface_format (std::vector const& available_formats, std::vector const& desired_formats) { for (auto const& desired_format : desired_formats) { diff --git a/src/VkBootstrap.h b/src/VkBootstrap.h index 1f52864..73c043f 100644 --- a/src/VkBootstrap.h +++ b/src/VkBootstrap.h @@ -364,6 +364,10 @@ class PhysicalDeviceSelector { // Require a physical device which supports the features in VkPhysicalDeviceFeatures. PhysicalDeviceSelector& set_required_features (VkPhysicalDeviceFeatures features); + // Used when surface creation happens after physical device selection. + // Warning: This disables checking if the physical device supports a given surface. + PhysicalDeviceSelector& defer_surface_initialization (); + // Ignore all criteria and choose the first physical device that is available. // Only use when: The first gpu in the list may be set by global user preferences and an application may wish to respect it. PhysicalDeviceSelector& select_first_device_unconditionally (bool unconditionally = true); @@ -404,6 +408,7 @@ class PhysicalDeviceSelector { VkPhysicalDeviceFeatures required_features{}; + bool defer_surface_initialization = false; bool use_first_gpu_unconditionally = false; } criteria;