@ -210,6 +210,7 @@ VKDevice::VKDevice(VkInstance instance_, u32 instance_version_, vk::PhysicalDevi
VkSurfaceKHR surface , const vk : : InstanceDispatch & dld_ )
: instance { instance_ } , dld { dld_ } , physical { physical_ } , properties { physical . GetProperties ( ) } ,
instance_version { instance_version_ } , format_properties { GetFormatProperties ( physical , dld ) } {
CheckSuitability ( ) ;
SetupFamilies ( surface ) ;
SetupFeatures ( ) ;
@ -548,64 +549,41 @@ bool VKDevice::IsFormatSupported(VkFormat wanted_format, VkFormatFeatureFlags wa
return ( supported_usage & wanted_usage ) = = wanted_usage ;
}
bool VKDevice : : IsSuitable ( vk : : PhysicalDevice physical , VkSurfaceKHR surface ) {
bool is_suitable = true ;
void VKDevice : : CheckSuitability ( ) const {
std : : bitset < REQUIRED_EXTENSIONS . size ( ) > available_extensions ;
for ( const auto & prop : physical . EnumerateDeviceExtensionProperties ( ) ) {
for ( const VkExtensionProperties & property : physical . EnumerateDeviceExtensionProperties ( ) ) {
for ( std : : size_t i = 0 ; i < REQUIRED_EXTENSIONS . size ( ) ; + + i ) {
if ( available_extensions [ i ] ) {
continue ;
}
const std : : string_view name { prop . extensionName } ;
const std : : string_view name { prop erty . extensionName } ;
available_extensions [ i ] = name = = REQUIRED_EXTENSIONS [ i ] ;
}
}
if ( ! available_extensions . all ( ) ) {
for ( std : : size_t i = 0 ; i < REQUIRED_EXTENSIONS . size ( ) ; + + i ) {
if ( available_extensions [ i ] ) {
continue ;
}
LOG_ERROR ( Render_Vulkan , " Missing required extension: {} " , REQUIRED_EXTENSIONS [ i ] ) ;
is_suitable = false ;
}
}
bool has_graphics { } , has_present { } ;
const std : : vector queue_family_properties = physical . GetQueueFamilyProperties ( ) ;
for ( u32 i = 0 ; i < static_cast < u32 > ( queue_family_properties . size ( ) ) ; + + i ) {
const auto & family = queue_family_properties [ i ] ;
if ( family . queueCount = = 0 ) {
for ( size_t i = 0 ; i < REQUIRED_EXTENSIONS . size ( ) ; + + i ) {
if ( available_extensions [ i ] ) {
continue ;
}
has_graphics | = family . queueFlags & VK_QUEUE_GRAPHICS_BIT ;
has_present | = physical . GetSurfaceSupportKHR ( i , surface ) ;
LOG_ERROR ( Render_Vulkan , " Missing required extension: {} " , REQUIRED_EXTENSIONS [ i ] ) ;
throw vk : : Exception ( VK_ERROR_EXTENSION_NOT_PRESENT ) ;
}
if ( ! has_graphics | | ! has_present ) {
LOG_ERROR ( Render_Vulkan , " Device lacks a graphics and present queue " ) ;
is_suitable = false ;
}
// TODO(Rodrigo): Check if the device matches all requeriments.
const auto properties { physical . GetProperties ( ) } ;
const auto & limits { properties . limits } ;
const VkPhysicalDeviceLimits & limits { properties . limits } ;
constexpr u32 required_ubo_size = 65536 ;
if ( limits . maxUniformBufferRange < required_ubo_size ) {
LOG_ERROR ( Render_Vulkan , " Device UBO size {} is too small, {} is required " ,
limits . maxUniformBufferRange , required_ubo_size ) ;
is_suitable = false ;
throw vk : : Exception ( VK_ERROR_FEATURE_NOT_PRESENT ) ;
}
constexpr u32 required_num_viewports = 16 ;
if ( limits . maxViewports < required_num_viewports ) {
LOG_INFO ( Render_Vulkan , " Device number of viewports {} is too small, {} is required " ,
limits . maxViewports , required_num_viewports ) ;
is_suitable = false ;
throw vk : : Exception ( VK_ERROR_FEATURE_NOT_PRESENT ) ;
}
const auto features { physical . GetFeatures ( ) } ;
const std : : array feature_report = {
const VkPhysicalDeviceFeatures features { physical . GetFeatures ( ) } ;
const std : : array feature_report {
std : : make_pair ( features . vertexPipelineStoresAndAtomics , " vertexPipelineStoresAndAtomics " ) ,
std : : make_pair ( features . imageCubeArray , " imageCubeArray " ) ,
std : : make_pair ( features . independentBlend , " independentBlend " ) ,
@ -623,19 +601,13 @@ bool VKDevice::IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface) {
std : : make_pair ( features . shaderStorageImageWriteWithoutFormat ,
" shaderStorageImageWriteWithoutFormat " ) ,
} ;
for ( const auto & [ supported, name ] : feature_report ) {
if ( supported) {
for ( const auto & [ is_ supported, name ] : feature_report ) {
if ( is_ supported) {
continue ;
}
LOG_ERROR ( Render_Vulkan , " Missing required feature: {} " , name ) ;
is_suitable = false ;
throw vk : : Exception ( VK_ERROR_FEATURE_NOT_PRESENT ) ;
}
if ( ! is_suitable ) {
LOG_ERROR ( Render_Vulkan , " {} is not suitable " , properties . deviceName ) ;
}
return is_suitable ;
}
std : : vector < const char * > VKDevice : : LoadExtensions ( ) {
@ -794,28 +766,34 @@ std::vector<const char*> VKDevice::LoadExtensions() {
}
void VKDevice : : SetupFamilies ( VkSurfaceKHR surface ) {
std : : optional < u32 > graphics_family_ , present_family_ ;
const std : : vector queue_family_properties = physical . GetQueueFamilyProperties ( ) ;
for ( u32 i = 0 ; i < static_cast < u32 > ( queue_family_properties . size ( ) ) ; + + i ) {
if ( graphics_family_ & & present_family_ )
std : : optional < u32 > graphics ;
std : : optional < u32 > present ;
for ( u32 index = 0 ; index < static_cast < u32 > ( queue_family_properties . size ( ) ) ; + + index ) {
if ( graphics & & present ) {
break ;
const auto & queue_family = queue_family_properties [ i ] ;
if ( queue_family . queueCount = = 0 )
continue ;
if ( queue_family . queueFlags & VK_QUEUE_GRAPHICS_BIT ) {
graphics_family_ = i ;
}
if ( physical . GetSurfaceSupportKHR ( i , surface ) ) {
present_family_ = i ;
const VkQueueFamilyProperties & queue_family = queue_family_properties [ index ] ;
if ( queue_family . queueCount = = 0 ) {
continue ;
}
if ( queue_family . queueFlags & VK_QUEUE_GRAPHICS_BIT ) {
graphics = index ;
}
if ( physical . GetSurfaceSupportKHR ( index , surface ) ) {
present = index ;
}
}
ASSERT ( graphics_family_ & & present_family_ ) ;
graphics_family = * graphics_family_ ;
present_family = * present_family_ ;
if ( ! graphics ) {
LOG_ERROR ( Render_Vulkan , " Device lacks a graphics queue " ) ;
throw vk : : Exception ( VK_ERROR_FEATURE_NOT_PRESENT ) ;
}
if ( ! present ) {
LOG_ERROR ( Render_Vulkan , " Device lacks a present queue " ) ;
throw vk : : Exception ( VK_ERROR_FEATURE_NOT_PRESENT ) ;
}
graphics_family = * graphics ;
present_family = * present ;
}
void VKDevice : : SetupFeatures ( ) {