Program Listing for File SwapchainChoices.hpp

Program Listing for File SwapchainChoices.hpp#

Return to documentation for file (Src/GraphicsEngineVulkan/vulkan_base/SwapchainChoices.hpp)

#pragma once

#include <algorithm>
#include <cstdint>
#include <vector>
#include <vulkan/vulkan.hpp>

namespace Kataglyphis {

// best format is subjective, but I go with:
//  Format:           vk::Format::eR8G8B8A8Unorm (backup-format:
//  vk::Format::eB8G8R8A8Unorm) color_space:  vk::ColorSpaceKHR::eSrgbNonlinear
inline vk::SurfaceFormatKHR chooseBestSurfaceFormat(const std::vector<vk::SurfaceFormatKHR> &formats)
{
    // an empty list has no formats[0] to fall back on - use the same default
    // as the "no restrictions" case below instead of indexing past the end.
    if (formats.empty()) { return { vk::Format::eR8G8B8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear }; }

    // the condition below means all formats are available (no restrictions)
    if (formats.size() == 1 && formats[0].format == vk::Format::eUndefined) {
        return { vk::Format::eR8G8B8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear };
    }

    // if restricted, search for optimal format
    for (const auto &format : formats) {
        if ((format.format == vk::Format::eR8G8B8A8Unorm || format.format == vk::Format::eB8G8R8A8Unorm)
            && format.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear) {
            return format;
        }
    }

    // in case just return first one--- but really shouldn't be the case ....
    // (this is exactly what makes an exotic, non-capturable surface format
    // reachable at runtime - see FormatHelper.hpp's isCapturableSwapchainFormat)
    return formats[0];
}

inline vk::PresentModeKHR chooseBestPresentationMode(const std::vector<vk::PresentModeKHR> &presentation_modes)
{
    // look for mailbox presentation mode
    for (const auto &presentation_mode : presentation_modes) {
        if (presentation_mode == vk::PresentModeKHR::eMailbox) { return presentation_mode; }
    }

    // if can't find, use FIFO as Vulkan spec says it must be present
    return vk::PresentModeKHR::eFifo;
}

// Clamps a candidate extent into the surface's [min, max] image extent
// bounds. The window-query / currentExtent short-circuit stays with the
// caller since that part needs a live window, not just capability data.
inline vk::Extent2D clampSwapExtent(const vk::SurfaceCapabilitiesKHR &surface_capabilities,
  uint32_t width,
  uint32_t height)
{
    vk::Extent2D new_extent{};
    new_extent.width = width;
    new_extent.height = height;

    uint32_t const min_width = surface_capabilities.minImageExtent.width;
    uint32_t const max_width = surface_capabilities.maxImageExtent.width;
    uint32_t const min_height = surface_capabilities.minImageExtent.height;
    uint32_t const max_height = surface_capabilities.maxImageExtent.height;

    new_extent.width = std::max(min_width, std::min(max_width, new_extent.width));
    new_extent.height = std::max(min_height, std::min(max_height, new_extent.height));

    return new_extent;
}

}// namespace Kataglyphis