16{
19
21
23 ? window_config.surface_format.value()
25
27
29 ? window_config.present_mode.value()
30 : surface_info.present_mode;
31
32 uint32_t desired_image_count = surface_info.image_count;
33
36
37 SwapchainSupportDetails support =
query_support(physical_device, surface);
38
39 if (!support.is_adequate()) {
41 "Swapchain support inadequate (formats: {}, modes: {})",
42 support.formats.size(), support.present_modes.size());
43 return false;
44 }
45
46 vk::SurfaceFormatKHR surface_format;
47
48 if (surface_info.enable_hdr) {
50
51 if (hdr_format.has_value()) {
52 surface_format = hdr_format.value();
53 } else {
55 "HDR requested but no HDR-capable format/colorspace supported by device/surface. Falling back to default.");
56
58 }
59
60 } else {
62 }
63
65 "Chosen swapchain format: {}, color space: {}",
66 vk::to_string(surface_format.format),
67 vk::to_string(surface_format.colorSpace));
68
70 support.present_modes, desired_present_mode);
71 vk::Extent2D extent =
choose_extent(support.capabilities, window_config.width, window_config.height);
72
73 uint32_t image_count = std::max(desired_image_count, support.capabilities.minImageCount);
74 if (support.capabilities.maxImageCount > 0) {
75 image_count = std::min(image_count, support.capabilities.maxImageCount);
76 }
77
78 vk::SwapchainCreateInfoKHR create_info {};
79 create_info.surface = surface;
80 create_info.minImageCount = image_count;
81 create_info.imageFormat = surface_format.format;
82 create_info.imageColorSpace = surface_format.colorSpace;
83 create_info.imageExtent = extent;
84 create_info.imageArrayLayers = 1;
85 create_info.imageUsage = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst;
86
87 if (support.capabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferSrc) {
88 create_info.imageUsage |= vk::ImageUsageFlagBits::eTransferSrc;
89 } else {
91 "Surface does not support eTransferSrc; frame capture will be unavailable");
92 }
93
95
96 std::vector<uint32_t> unique_families;
97 for (uint32_t f : sharing_families) {
98 if (std::ranges::find(unique_families, f) == unique_families.end())
99 unique_families.push_back(f);
100 }
101
102 if (unique_families.size() > 1) {
103 create_info.imageSharingMode = vk::SharingMode::eConcurrent;
104 create_info.queueFamilyIndexCount = static_cast<uint32_t>(unique_families.size());
105 create_info.pQueueFamilyIndices = unique_families.data();
106 } else {
107 create_info.imageSharingMode = vk::SharingMode::eExclusive;
108 create_info.queueFamilyIndexCount = 0;
109 create_info.pQueueFamilyIndices = nullptr;
110 }
111
112 create_info.preTransform = support.capabilities.currentTransform;
113 create_info.compositeAlpha = vk::CompositeAlphaFlagBitsKHR::eOpaque;
114 create_info.presentMode = present_mode;
115 create_info.clipped = VK_TRUE;
116 create_info.oldSwapchain = nullptr;
117
118 try {
120 } catch (const vk::SystemError& e) {
122 "Failed to create swapchain: {}", e.what());
123 return false;
124 }
125
127
130
132
135 return false;
136 }
137
139 "Swapchain created: {}x{}, {} images, format {}",
140 extent.width, extent.height,
m_images.size(),
141 vk::to_string(surface_format.format));
142
143 return true;
144}
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
#define MF_WARN(comp, ctx,...)
vk::PhysicalDevice device
vk::Device get_device() const
Get logical device.
const GraphicsSurfaceInfo & get_surface_info() const
Get graphics surface info.
vk::PhysicalDevice get_physical_device() const
Get physical device.
vk::Extent2D choose_extent(const vk::SurfaceCapabilitiesKHR &capabilities, uint32_t width, uint32_t height) const
Choose swap extent based on capabilities.
vk::PresentModeKHR choose_present_mode(const std::vector< vk::PresentModeKHR > &available_modes, GraphicsSurfaceInfo::PresentMode desired_mode) const
Choose best present mode from available modes based on config.
bool create_image_views()
Create image views for swapchain images.
vk::Format m_image_format
static SwapchainSupportDetails query_support(vk::PhysicalDevice physical_device, vk::SurfaceKHR surface)
Query swapchain support details for a device.
std::optional< vk::SurfaceFormatKHR > find_hdr_format(const std::vector< vk::SurfaceFormatKHR > &available_formats) const
Find an HDR-capable format from available formats.
vk::SurfaceFormatKHR choose_surface_format(const std::vector< vk::SurfaceFormatKHR > &available_formats, GraphicsSurfaceInfo::SurfaceFormat desired_format, GraphicsSurfaceInfo::ColorSpace desired_color_space) const
Choose best surface format from available formats based on config.
void cleanup_swapchain()
Cleanup old swapchain during recreation.
std::vector< vk::Image > m_images
std::vector< uint32_t > m_sharing_families
const WindowCreateInfo * m_window_config
vk::SwapchainKHR m_swapchain
@ GraphicsBackend
Graphics/visual rendering backend (Vulkan, OpenGL)
@ Core
Core engine, backend, subsystems.
ColorSpace
Default color space for window surfaces.
SurfaceFormat
Default pixel format for window surfaces (Vulkan-compatible)
PresentMode
Frame presentation strategy.
SurfaceFormat format
Default surface format for new windows.