bool check_physical_device_properties(VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index, const std::vector<const char *> &device_extensions) { uint32_t extensions_count = 0; if ((vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extensions_count, nullptr) != VK_SUCCESS) || (extensions_count == 0)) { SET_ERROR (LOG_TYPE, "Error occurred during physical device %d extensions enumeration!", physical_device); return false; } std::vector<VkExtensionProperties> available_extensions(extensions_count); if (vkEnumerateDeviceExtensionProperties(physical_device, nullptr, &extensions_count, &available_extensions[0]) != VK_SUCCESS) { SET_ERROR (LOG_TYPE, "Error occurred during physical device %d extensions enumeration!", physical_device); return false; } for (size_t i = 0; i < device_extensions.size(); ++i) { if (!utils::check_extension(device_extensions[i], available_extensions)) { SET_ERROR (LOG_TYPE, "Physical device %d doesn't support extension named \"%s\"!", physical_device, device_extensions[i]); return false; } } VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties(physical_device, &device_properties); vkGetPhysicalDeviceFeatures(physical_device, &device_features); uint32_t major_version = VK_VERSION_MAJOR(device_properties.apiVersion); if ((major_version < 1) && (device_properties.limits.maxImageDimension2D < 4096)) { SET_ERROR (LOG_TYPE, "Physical device %d doesn't support required parameters!", physical_device); return false; } uint32_t queue_families_count = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr); if (queue_families_count == 0) { SET_ERROR (LOG_TYPE, "Physical device %d doesn't have any handle families!", physical_device); return false; } std::vector<VkQueueFamilyProperties> queue_family_properties(queue_families_count); std::vector<VkBool32> queue_present_support(queue_families_count); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, &queue_family_properties[0]); uint32_t graphics_queue_family_index = UINT32_MAX; uint32_t present_queue_family_index = UINT32_MAX; for (uint32_t i = 0; i < queue_families_count; ++i) { vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, vk_globals::surface, &queue_present_support[i]); if ((queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) { // Select first handle that supports graphics if (graphics_queue_family_index == UINT32_MAX) { graphics_queue_family_index = i; } // If there is handle that supports both graphics and present - prefer it if (queue_present_support[i]) { selected_graphics_queue_family_index = i; selected_present_queue_family_index = i; return true; } } } // We don't have handle that supports both graphics and present so we have to use separate queues for (uint32_t i = 0; i < queue_families_count; ++i) { if (queue_present_support[i]) { present_queue_family_index = i; break; } } // If this device doesn't support queues with graphics and present capabilities don't use it if ((graphics_queue_family_index == UINT32_MAX) || (present_queue_family_index == UINT32_MAX)) { SET_ERROR (LOG_TYPE, "Could not find handle families with required properties on physical device %d!", physical_device); return false; } selected_graphics_queue_family_index = graphics_queue_family_index; selected_present_queue_family_index = present_queue_family_index; return true; }
bool vulkan_check_physical_device(IWindow* window, VkPhysicalDevice physical_device, VkSurfaceKHR presentationSurface, const std::vector<const char*>& extensions, uint32_t& queue_family_index, uint32_t& selected_present_queue_family_index) { Assert(window != nullptr); vulkan_device_check_extensions(extensions, physical_device); VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties(physical_device, &device_properties); vkGetPhysicalDeviceFeatures(physical_device, &device_features); Assert(device_properties.apiVersion >= VK_MAKE_VERSION(1, 0, 0)); Assert(device_properties.limits.maxImageDimension2D >= 4096); Assert(device_features.shaderClipDistance == VK_TRUE); // This is just checked, not enabled uint32_t queue_families_count = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, nullptr); Assert(queue_families_count > 0, "device doesn't have any queue families"); if (queue_families_count == 0) return false; std::vector<VkQueueFamilyProperties> queue_family_properties(queue_families_count); std::vector<VkBool32> queue_present_support(queue_families_count); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_families_count, &queue_family_properties[0]); uint32_t graphics_queue_family_index = UINT32_MAX; uint32_t present_queue_family_index = UINT32_MAX; for (uint32_t i = 0; i < queue_families_count; ++i) { Assert(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, presentationSurface, &queue_present_support[i]) == VK_SUCCESS); if ((queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)) { // Select first queue that supports graphics if (graphics_queue_family_index == UINT32_MAX) graphics_queue_family_index = i; Assert(vulkan_queue_family_has_presentation_support(physical_device, i, window) == (queue_present_support[i] == VK_TRUE), "Queue family presentation support mismatch."); // If there is queue that supports both graphics and present - prefer it if (queue_present_support[i]) { queue_family_index = i; selected_present_queue_family_index = i; return true; } } } // We don't have queue that supports both graphics and present so we have to use separate queues for (uint32_t i = 0; i < queue_families_count; ++i) { if (queue_present_support[i] == VK_TRUE) { present_queue_family_index = i; break; } } Assert(graphics_queue_family_index != UINT32_MAX); Assert(present_queue_family_index != UINT32_MAX); queue_family_index = graphics_queue_family_index; selected_present_queue_family_index = present_queue_family_index; return true; }
bool VulkanCommon::CheckPhysicalDeviceProperties( VkPhysicalDevice physical_device, uint32_t &selected_graphics_queue_family_index, uint32_t &selected_present_queue_family_index ) { uint32_t extensions_count = 0; if( (vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, nullptr ) != VK_SUCCESS) || (extensions_count == 0) ) { std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return false; } std::vector<VkExtensionProperties> available_extensions( extensions_count ); if( vkEnumerateDeviceExtensionProperties( physical_device, nullptr, &extensions_count, &available_extensions[0] ) != VK_SUCCESS ) { std::cout << "Error occurred during physical device " << physical_device << " extensions enumeration!" << std::endl; return false; } std::vector<const char*> device_extensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; for( size_t i = 0; i < device_extensions.size(); ++i ) { if( !CheckExtensionAvailability( device_extensions[i], available_extensions ) ) { std::cout << "Physical device " << physical_device << " doesn't support extension named \"" << device_extensions[i] << "\"!" << std::endl; return false; } } VkPhysicalDeviceProperties device_properties; VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceProperties( physical_device, &device_properties ); vkGetPhysicalDeviceFeatures( physical_device, &device_features ); uint32_t major_version = VK_VERSION_MAJOR( device_properties.apiVersion ); if( (major_version < 1) && (device_properties.limits.maxImageDimension2D < 4096) ) { std::cout << "Physical device " << physical_device << " doesn't support required parameters!" << std::endl; return false; } uint32_t queue_families_count = 0; vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, nullptr ); if( queue_families_count == 0 ) { std::cout << "Physical device " << physical_device << " doesn't have any queue families!" << std::endl; return false; } std::vector<VkQueueFamilyProperties> queue_family_properties( queue_families_count ); std::vector<VkBool32> queue_present_support( queue_families_count ); vkGetPhysicalDeviceQueueFamilyProperties( physical_device, &queue_families_count, &queue_family_properties[0] ); uint32_t graphics_queue_family_index = UINT32_MAX; uint32_t present_queue_family_index = UINT32_MAX; for( uint32_t i = 0; i < queue_families_count; ++i ) { vkGetPhysicalDeviceSurfaceSupportKHR( physical_device, i, Vulkan.PresentationSurface, &queue_present_support[i] ); if( (queue_family_properties[i].queueCount > 0) && (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) ) { // Select first queue that supports graphics if( graphics_queue_family_index == UINT32_MAX ) { graphics_queue_family_index = i; } // If there is queue that supports both graphics and present - prefer it if( queue_present_support[i] ) { selected_graphics_queue_family_index = i; selected_present_queue_family_index = i; return true; } } } // We don't have queue that supports both graphics and present so we have to use separate queues for( uint32_t i = 0; i < queue_families_count; ++i ) { if( queue_present_support[i] ) { present_queue_family_index = i; break; } } // If this device doesn't support queues with graphics and present capabilities don't use it if( (graphics_queue_family_index == UINT32_MAX) || (present_queue_family_index == UINT32_MAX) ) { std::cout << "Could not find queue families with required properties on physical device " << physical_device << "!" << std::endl; return false; } selected_graphics_queue_family_index = graphics_queue_family_index; selected_present_queue_family_index = present_queue_family_index; return true; }