diff --git a/src/util/vulkan_swap_chain.cpp b/src/util/vulkan_swap_chain.cpp index c35f556c5..23502b5b7 100644 --- a/src/util/vulkan_swap_chain.cpp +++ b/src/util/vulkan_swap_chain.cpp @@ -20,27 +20,6 @@ LOG_CHANNEL(GPUDevice); -static VkFormat GetLinearFormat(VkFormat format) -{ - switch (format) - { - case VK_FORMAT_R8_SRGB: - return VK_FORMAT_R8_UNORM; - case VK_FORMAT_R8G8_SRGB: - return VK_FORMAT_R8G8_UNORM; - case VK_FORMAT_R8G8B8_SRGB: - return VK_FORMAT_R8G8B8_UNORM; - case VK_FORMAT_R8G8B8A8_SRGB: - return VK_FORMAT_R8G8B8A8_UNORM; - case VK_FORMAT_B8G8R8_SRGB: - return VK_FORMAT_B8G8R8_UNORM; - case VK_FORMAT_B8G8R8A8_SRGB: - return VK_FORMAT_B8G8R8A8_UNORM; - default: - return format; - } -} - static const char* PresentModeToString(VkPresentModeKHR mode) { switch (mode) @@ -219,23 +198,31 @@ std::optional VulkanSwapChain::SelectSurfaceFormat(VkPhysica std::vector surface_formats(format_count); res = vkGetPhysicalDeviceSurfaceFormatsKHR(physdev, m_surface, &format_count, surface_formats.data()); - Assert(res == VK_SUCCESS); + if (res != VK_SUCCESS) + { + Vulkan::SetErrorObject(error, "vkGetPhysicalDeviceSurfaceFormatsKHR failed: ", res); + return std::nullopt; + } + surface_formats.resize(format_count); // If there is a single undefined surface format, the device doesn't care, so we'll just use RGBA - const auto has_format = [&surface_formats](VkFormat fmt) { - return std::any_of(surface_formats.begin(), surface_formats.end(), [fmt](const VkSurfaceFormatKHR& sf) { - return (sf.format == fmt || GetLinearFormat(sf.format) == fmt); - }); - }; - if (has_format(VK_FORMAT_UNDEFINED)) - return VkSurfaceFormatKHR{VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; + // NOTE: This is prehistoric shit, Vulkan 1.1+ drivers not allowed to return UNDEFINED. + if (surface_formats.size() == 1 && surface_formats[0].format == VK_FORMAT_UNDEFINED) + return VkSurfaceFormatKHR{VK_FORMAT_R8G8B8A8_UNORM, surface_formats[0].colorSpace}; - // Prefer 8-bit formats. - for (VkFormat format : {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R5G6B5_UNORM_PACK16, - VK_FORMAT_R5G5B5A1_UNORM_PACK16}) + // Prefer 8-bit formats. Fall back to an advertised sRGB counterpart when no preferred linear format is available. + for (const VkFormat format : {VK_FORMAT_R8G8B8A8_UNORM, VK_FORMAT_B8G8R8A8_UNORM, VK_FORMAT_R5G6B5_UNORM_PACK16, + VK_FORMAT_R5G5B5A1_UNORM_PACK16, VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_B8G8R8A8_SRGB}) { - if (has_format(format)) - return VkSurfaceFormatKHR{format, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}; + const auto it = + std::ranges::find_if(surface_formats, [format](const VkSurfaceFormatKHR& sf) { return sf.format == format; }); + if (it != surface_formats.end()) + { + if (format == VK_FORMAT_R8G8B8A8_SRGB || format == VK_FORMAT_B8G8R8A8_SRGB) [[unlikely]] + WARNING_LOG("Using SRGB output format {}", static_cast(format)); + + return *it; + } } SmallString errormsg("Failed to find a suitable format for swap chain buffers. Available formats were:");