Baffling Vulkan error - The device can't render to the surface, no surface formats found

Hi all
I am really stuck with this issue and wondered whether anyone has come across it before? It is related to Xplane 11 which is a flight simulator - and even the developer is stumped.

The device can’t render to the surface, no surface formats found. Make sure that your GPU is attached to the monitor and that your drivers are up-to-date

My drivers are upto date and on a clean install - my GPU is connected to monitor and not the Mobo, I have turned off integrated gpu in BIOS etc.

It does say in the log that NVIDIA optimus vulkan layer active and as i am using a desktop, should this be the case and could that be causing the error?

Many thanks
Adam

Hello there!

One characteristic of Vulkan API is that you must check everything before using it.
This includes checking your prefered color format is supported on the target machine.
I would suggest to have a “wishlist” of supported color formats (here accepted_formats) and then to check which ones are supported. In case VK_FORMAT_B8G8R8A8_UNORM is not available select the first available color format:

std::optional<VkSurfaceFormatKHR> VulkanSettingsDecisionMaker::decide_which_surface_color_format_in_swapchain_to_use(
	VkPhysicalDevice graphics_card, VkSurfaceKHR surface) {
	assert(graphics_card);
	assert(surface);

	spdlog::debug("Deciding automatically which surface color format in swapchain to use.");

	std::uint32_t number_of_available_surface_formats = 0;

	// First check how many surface formats are available.
	if (vkGetPhysicalDeviceSurfaceFormatsKHR(graphics_card, surface, &number_of_available_surface_formats, nullptr) !=
		VK_SUCCESS) {
		throw std::runtime_error("Error: vkGetPhysicalDeviceSurfaceFormatsKHR failed!");
	}

	if (number_of_available_surface_formats == 0) {
		throw std::runtime_error("Error: No surface formats could be found by fpGetPhysicalDeviceSurfaceFormatsKHR!");
	}

	// Preallocate memory for available surface formats.
	std::vector<VkSurfaceFormatKHR> available_surface_formats(number_of_available_surface_formats);

	// Get information about all surface formats available.
	if (vkGetPhysicalDeviceSurfaceFormatsKHR(graphics_card, surface, &number_of_available_surface_formats,
											 available_surface_formats.data()) != VK_SUCCESS) {
		throw std::runtime_error("Error: vkGetPhysicalDeviceSurfaceFormatsKHR failed!");
	}

	VkSurfaceFormatKHR accepted_color_format{};

	// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
	// there is no preferred format, so we assume VK_FORMAT_B8G8R8A8_UNORM.
	if (number_of_available_surface_formats == 1 && available_surface_formats[0].format == VK_FORMAT_UNDEFINED) {
		accepted_color_format.format = VK_FORMAT_B8G8R8A8_UNORM;
		accepted_color_format.colorSpace = available_surface_formats[0].colorSpace;
	} else {
		// This vector contais all the formats that we can accept.
		// Currently we use VK_FORMAT_B8G8R8A8_UNORM only, since it's the norm.
		std::vector<VkFormat> accepted_formats = {
			VK_FORMAT_B8G8R8A8_UNORM
			// Add more accepted formats here..
		};

		bool found_acceptable_format = false;

		// Loop through the list of available surface formats and compare with the list of acceptable formats.
		for (auto &&surface_format : available_surface_formats) {
			for (auto &accepted_format : accepted_formats) {
				if (surface_format.format == accepted_format) {
					accepted_color_format.format = surface_format.format;
					accepted_color_format.colorSpace = surface_format.colorSpace;

					found_acceptable_format = true;

					return accepted_color_format;
				}
			}
		}

		// In case VK_FORMAT_B8G8R8A8_UNORM is not available select the first available color format.
		if (!found_acceptable_format) {
			if (!available_surface_formats.empty()) {
				accepted_color_format.format = available_surface_formats[0].format;
				accepted_color_format.colorSpace = available_surface_formats[0].colorSpace;

				return accepted_color_format;
			}
			return std::nullopt;
		}
	}

	return accepted_color_format;
}

This code is very extensive in error checking. It even checks for errors which should not occur according to the standard.

If no color format could be found, std::nullopt will be returned (C++17).

best regards,
Johannes