Added defer_surface_initialization which allows skipping checking if a device and surface work together

This commit is contained in:
Charles Giessen 2020-03-07 23:26:46 -07:00
parent 3097f46074
commit 40488fc7cd
2 changed files with 56 additions and 43 deletions

View File

@ -487,42 +487,6 @@ InstanceBuilder& InstanceBuilder::set_allocation_callbacks (VkAllocationCallback
namespace detail { namespace detail {
struct SurfaceSupportDetails {
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> present_modes;
};
enum class SurfaceSupportError {
surface_handle_null,
failed_get_surface_capabilities,
failed_enumerate_surface_formats,
failed_enumerate_present_modes
};
Expected<SurfaceSupportDetails, detail::Error<SurfaceSupportError>> query_surface_support_details (
VkPhysicalDevice phys_device, VkSurfaceKHR surface) {
if (surface == VK_NULL_HANDLE)
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::surface_handle_null };
VkSurfaceCapabilitiesKHR capabilities;
VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (phys_device, surface, &capabilities);
if (res != VK_SUCCESS) {
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::failed_get_surface_capabilities, res };
}
auto formats = detail::get_vector<VkSurfaceFormatKHR> (
vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface);
if (!formats.has_value ())
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::failed_enumerate_surface_formats,
formats.error () };
auto present_modes = detail::get_vector<VkPresentModeKHR> (
vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface);
if (!present_modes.has_value ())
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::failed_enumerate_present_modes,
formats.error () };
return SurfaceSupportDetails{ capabilities, formats.value (), present_modes.value () };
}
std::vector<const char*> check_device_extension_support ( std::vector<const char*> check_device_extension_support (
VkPhysicalDevice device, std::vector<const char*> desired_extensions) { VkPhysicalDevice device, std::vector<const char*> desired_extensions) {
auto available_extensions = auto available_extensions =
@ -720,13 +684,17 @@ PhysicalDeviceSelector::Suitable PhysicalDeviceSelector::is_device_suitable (Phy
bool swapChainAdequate = false; bool swapChainAdequate = false;
if (!system_info.headless) { if (criteria.defer_surface_initialization) {
auto swapChainSupport_ret = swapChainAdequate = true;
detail::query_surface_support_details (pd.phys_device, system_info.surface); } else if (!system_info.headless) {
if (swapChainSupport_ret.has_value ()) {
auto swapchain_support = swapChainSupport_ret.value (); auto formats = detail::get_vector<VkSurfaceFormatKHR> (
swapChainAdequate = vkGetPhysicalDeviceSurfaceFormatsKHR, pd.phys_device, system_info.surface);
!swapchain_support.formats.empty () && !swapchain_support.present_modes.empty (); auto present_modes = detail::get_vector<VkPresentModeKHR> (
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; if (criteria.require_present && !swapChainAdequate) suitable = Suitable::no;
@ -892,6 +860,10 @@ PhysicalDeviceSelector& PhysicalDeviceSelector::set_required_features (VkPhysica
criteria.required_features = features; criteria.required_features = features;
return *this; return *this;
} }
PhysicalDeviceSelector& PhysicalDeviceSelector::defer_surface_initialization () {
criteria.defer_surface_initialization = true;
return *this;
}
PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditionally (bool unconditionally) { PhysicalDeviceSelector& PhysicalDeviceSelector::select_first_device_unconditionally (bool unconditionally) {
criteria.use_first_gpu_unconditionally = unconditionally; criteria.use_first_gpu_unconditionally = unconditionally;
return *this; return *this;
@ -1045,6 +1017,42 @@ DeviceBuilder& DeviceBuilder::set_allocation_callbacks (VkAllocationCallbacks* c
} }
namespace detail { namespace detail {
struct SurfaceSupportDetails {
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> present_modes;
};
enum class SurfaceSupportError {
surface_handle_null,
failed_get_surface_capabilities,
failed_enumerate_surface_formats,
failed_enumerate_present_modes
};
Expected<SurfaceSupportDetails, detail::Error<SurfaceSupportError>> query_surface_support_details (
VkPhysicalDevice phys_device, VkSurfaceKHR surface) {
if (surface == VK_NULL_HANDLE)
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::surface_handle_null };
VkSurfaceCapabilitiesKHR capabilities;
VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR (phys_device, surface, &capabilities);
if (res != VK_SUCCESS) {
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::failed_get_surface_capabilities, res };
}
auto formats = detail::get_vector<VkSurfaceFormatKHR> (
vkGetPhysicalDeviceSurfaceFormatsKHR, phys_device, surface);
if (!formats.has_value ())
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::failed_enumerate_surface_formats,
formats.error () };
auto present_modes = detail::get_vector<VkPresentModeKHR> (
vkGetPhysicalDeviceSurfacePresentModesKHR, phys_device, surface);
if (!present_modes.has_value ())
return detail::Error<SurfaceSupportError>{ SurfaceSupportError::failed_enumerate_present_modes,
formats.error () };
return SurfaceSupportDetails{ capabilities, formats.value (), present_modes.value () };
}
VkSurfaceFormatKHR find_surface_format (std::vector<VkSurfaceFormatKHR> const& available_formats, VkSurfaceFormatKHR find_surface_format (std::vector<VkSurfaceFormatKHR> const& available_formats,
std::vector<VkSurfaceFormatKHR> const& desired_formats) { std::vector<VkSurfaceFormatKHR> const& desired_formats) {
for (auto const& desired_format : desired_formats) { for (auto const& desired_format : desired_formats) {

View File

@ -364,6 +364,10 @@ class PhysicalDeviceSelector {
// Require a physical device which supports the features in VkPhysicalDeviceFeatures. // Require a physical device which supports the features in VkPhysicalDeviceFeatures.
PhysicalDeviceSelector& set_required_features (VkPhysicalDeviceFeatures features); 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. // 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. // 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); PhysicalDeviceSelector& select_first_device_unconditionally (bool unconditionally = true);
@ -404,6 +408,7 @@ class PhysicalDeviceSelector {
VkPhysicalDeviceFeatures required_features{}; VkPhysicalDeviceFeatures required_features{};
bool defer_surface_initialization = false;
bool use_first_gpu_unconditionally = false; bool use_first_gpu_unconditionally = false;
} criteria; } criteria;