8#include "evan/glfw/DesktopSwapchainImage.hpp"
10#include "evan/CheckedCast.hpp"
15#include "evan/DeviceContext.hpp"
21 this->
getLogger().info() <<
"Initializing DesktopSwapchainImage...";
27 <<
"Querying swap chain support details for DesktopSwapchainImage...";
29 backend.querySwapChainSupport();
42 <<
"Desired image count exceeds maximum supported by the swap "
43 "chain capabilities. Clamping to maxImageCount.";
49 createInfo.surface =
backend.getSurface();
54 createInfo.imageExtent =
extent;
55 createInfo.imageArrayLayers = 1;
60 indices.presentFamily.value() };
64 <<
"Graphics and present queue families are different. Using "
65 "concurrent sharing mode for swapchain images.";
67 createInfo.queueFamilyIndexCount = 2;
71 <<
"Graphics and present queue families are the same. Using "
72 "exclusive sharing mode for swapchain images.";
84 <<
"Creating swapchain with the following parameters:";
89 <<
", Image Extent = (" + std::to_string(
extent.width) +
", "
90 + std::to_string(
extent.height) +
")"
91 <<
", Image Usage = " << createInfo.imageUsage <<
", Sharing Mode = "
95 <<
", Pre Transform = " << createInfo.preTransform
96 <<
", Composite Alpha = " << createInfo.compositeAlpha
97 <<
", Present Mode = " << createInfo.presentMode
98 <<
", Clipped = " << (createInfo.clipped ?
"True" :
"False")
99 <<
", Old Swapchain = "
104 <<
"Old swapchain handle provided. This indicates that the "
105 "swapchain is being recreated, likely due to a window resize or "
106 "similar event. The old swapchain will be automatically cleaned "
107 "up by the Vulkan implementation once the new swapchain is "
108 "created successfully.";
115 <<
"Failed to create swap chain for DesktopSwapchainImage!";
120 <<
"Swapchain created successfully for DesktopSwapchainImage.";
126 const ColorAttachmentMode colorAttachmentMode =
127 desktopColorAttachmentMode(msaaSamples);
131 if (colorAttachmentMode == ColorAttachmentMode::ResolveToSwapchain) {
136 colorAttachmentMode);
139evan::DesktopSwapchainImage::~DesktopSwapchainImage()
141 this->
getLogger().info() <<
"Destroying DesktopSwapchainImage...";
159void evan::DesktopSwapchainImage::cleanup()
162 <<
"Destroying swapchain image and releasing associated resources for "
163 "DesktopSwapchainImage...";
169 this->getLogger().info()
170 <<
"Destroying framebuffers for DesktopSwapchainImage...";
171 for (
auto framebuffer: _framebuffers) {
172 if (framebuffer != VK_NULL_HANDLE) {
173 vkDestroyFramebuffer(_device, framebuffer,
nullptr);
176 _framebuffers.clear();
178 this->getLogger().info()
179 <<
"Destroying image views for DesktopSwapchainImage...";
180 for (
auto imageView: _imageViews) {
181 if (imageView != VK_NULL_HANDLE) {
182 vkDestroyImageView(_device, imageView,
nullptr);
187 this->getLogger().info()
188 <<
"Destroying swapchain for DesktopSwapchainImage...";
189 if (_swapchain != VK_NULL_HANDLE) {
190 vkDestroySwapchainKHR(_device, _swapchain,
nullptr);
191 _swapchain = VK_NULL_HANDLE;
194 this->getLogger().info()
195 <<
"Destroying color resources for DesktopSwapchainImage...";
196 if (_colorView != VK_NULL_HANDLE) {
197 vkDestroyImageView(_device, _colorView,
nullptr);
198 _colorView = VK_NULL_HANDLE;
200 if (_colorImage != VK_NULL_HANDLE) {
201 vkDestroyImage(_device, _colorImage,
nullptr);
202 _colorImage = VK_NULL_HANDLE;
204 if (_colorMemory != VK_NULL_HANDLE) {
205 vkFreeMemory(_device, _colorMemory,
nullptr);
206 _colorMemory = VK_NULL_HANDLE;
209 this->getLogger().info()
210 <<
"Destroying depth resources for DesktopSwapchainImage...";
211 if (_depthView != VK_NULL_HANDLE) {
212 vkDestroyImageView(_device, _depthView,
nullptr);
213 _depthView = VK_NULL_HANDLE;
215 if (_depthImage != VK_NULL_HANDLE) {
216 vkDestroyImage(_device, _depthImage,
nullptr);
217 _depthImage = VK_NULL_HANDLE;
219 if (_depthMemory != VK_NULL_HANDLE) {
220 vkFreeMemory(_device, _depthMemory,
nullptr);
221 _depthMemory = VK_NULL_HANDLE;
240 <<
"Choosing swap surface format for DesktopSwapchainImage...";
246 for (
const auto &availableFormat: availableFormats) {
247 for (VkFormat preferredFormat: kPreferredSwapchainFormats) {
248 if (availableFormat.format == preferredFormat
249 && availableFormat.colorSpace
250 == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
251 this->getLogger().info()
252 <<
"Selected preferred swap surface format: Format = "
253 << availableFormat.format
254 <<
", Color Space = " << availableFormat.colorSpace;
255 return availableFormat;
259 this->getLogger().info()
260 <<
"No preferred swap surface format found, using default format.";
261 return availableFormats[0];
264VkPresentModeKHR evan::DesktopSwapchainImage::chooseSwapPresentMode(
265 const std::vector<VkPresentModeKHR> &availablePresentModes)
267 this->getLogger().info()
268 <<
"Choosing swap present mode for DesktopSwapchainImage...";
272 for (
const auto &availablePresentMode: availablePresentModes) {
273 if (availablePresentMode == VK_PRESENT_MODE_FIFO_KHR) {
274 this->getLogger().info() <<
"Selected preferred swap present mode: "
275 "VK_PRESENT_MODE_FIFO_KHR";
276 return availablePresentMode;
279 this->getLogger().info()
280 <<
"No preferred swap present mode found, using default mode.";
281 return VK_PRESENT_MODE_FIFO_KHR;
284VkExtent2D evan::DesktopSwapchainImage::chooseSwapExtent(
285 const VkSurfaceCapabilitiesKHR &capabilities, GLFWwindow *window)
287 this->getLogger().info()
288 <<
"Choosing swap extent for DesktopSwapchainImage...";
292 if (capabilities.currentExtent.width
293 != (std::numeric_limits<uint32_t>::max)()) {
294 this->getLogger().info() <<
"Current extent is defined by the surface "
295 "capabilities. Using current extent: ("
296 + std::to_string(capabilities.currentExtent.width) +
", "
297 + std::to_string(capabilities.currentExtent.height) +
")";
298 return capabilities.currentExtent;
301 this->getLogger().info() <<
"Current extent is undefined. Querying "
302 "framebuffer size from GLFW window...";
303 glfwGetFramebufferSize(window, &width, &height);
305 VkExtent2D actualExtent = {
static_cast<uint32_t
>(width),
306 static_cast<uint32_t
>(height) };
308 this->getLogger().info() <<
"Queried framebuffer size: ("
309 + std::to_string(actualExtent.width) +
", "
310 + std::to_string(actualExtent.height)
311 +
"). Clamping to allowed extent range defined by surface "
315 std::clamp(actualExtent.width, capabilities.minImageExtent.width,
316 capabilities.maxImageExtent.width);
317 actualExtent.height =
318 std::clamp(actualExtent.height, capabilities.minImageExtent.height,
319 capabilities.maxImageExtent.height);
321 this->getLogger().info() <<
"Final swap extent after clamping: ("
322 + std::to_string(actualExtent.width) +
", "
323 + std::to_string(actualExtent.height) +
")";
void createFramebuffers(VkDevice logicalDevice, VkRenderPass renderPass, ColorAttachmentMode mode)
Creates framebuffers for the swapchain images.
void createImageViews(const ADeviceBackend &deviceBackend)
Creates image views for the swapchain images.
void createColorResources(const ADeviceBackend &deviceBackend, VkSampleCountFlagBits msaaSamples)
Creates a multisampled color attachment and its image view.
void createDepthResources(const DeviceContext &deviceContext, VkSampleCountFlagBits msaaSamples)
Creates depth resources for the swapchain images.
void createImages(VkDevice logicalDevice, VkSwapchainKHR swapchain)
Creates the Vulkan images for the swapchain.
VkSwapchainKHR _swapchain
void destroy(VkDevice device) override
Destroys the swapchain image and releases associated resources.
void fillPresentInfo(VkPresentInfoKHR &presentInfo) const override
Fills the VkPresentInfoKHR structure with the necessary information for presenting the swapchain imag...
DesktopSwapchainImage(const DeviceContext &deviceContext, GLFWwindow *window, VkRenderPass renderpass, VkSwapchainKHR oldSwapchain=VK_NULL_HANDLE)
Constructs a DesktopSwapchainImage instance for a given device context, GLFW window,...
Represents the device context for the engine, managing Vulkan-related resources and operations.
VkSampleCountFlagBits getMsaaSamples() const
Retrieves the number of MSAA samples used by this device context.
std::shared_ptr< ADeviceBackend > getDeviceBackend() const
Retrieves a shared pointer to the ADeviceBackend instance associated with this device context.
A structure to represent Vulkan queue family indices.
Small result wrapper used by helpers that must return both a status and a value (e....
Struct to encapsulate details about swap chain support.