27 const std::vector<VkSurfaceFormatKHR>& availableFormats)
30 for (
const auto& availableFormat : availableFormats) {
31 if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB
32 && availableFormat.colorSpace
33 == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
34 return availableFormat;
38 return availableFormats[0];
42 const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window)
44 if (capabilities.currentExtent.width
45 != std::numeric_limits<uint32_t>::max()) {
46 return capabilities.currentExtent;
49 glfwGetFramebufferSize(window, &width, &height);
51 VkExtent2D actualExtent
52 = {
static_cast<uint32_t
>(width),
static_cast<uint32_t
>(height) };
55 = std::clamp(actualExtent.width, capabilities.minImageExtent.width,
56 capabilities.maxImageExtent.width);
57 actualExtent.height = std::clamp(actualExtent.height,
58 capabilities.minImageExtent.height,
59 capabilities.maxImageExtent.height);
66 VkPhysicalDevice device, VkSurfaceKHR surface)
69 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
73 vkGetPhysicalDeviceSurfaceFormatsKHR(
74 device, surface, &formatCount,
nullptr);
76 if (formatCount != 0) {
77 details.
formats.resize(formatCount);
78 vkGetPhysicalDeviceSurfaceFormatsKHR(
79 device, surface, &formatCount, details.
formats.data());
82 uint32_t presentModeCount;
83 vkGetPhysicalDeviceSurfacePresentModesKHR(
84 device, surface, &presentModeCount,
nullptr);
86 if (presentModeCount != 0) {
88 vkGetPhysicalDeviceSurfacePresentModesKHR(
89 device, surface, &presentModeCount, details.
presentModes.data());
110 (*device).physicalDevice, surface);
111 VkSurfaceFormatKHR surfaceFormat
113 VkPresentModeKHR presentMode
114 = this->chooseSwapPresentMode(swapChainSupport.
presentModes);
119 uint32_t imageCount = swapChainSupport.
capabilities.minImageCount + 1;
124 && imageCount > swapChainSupport.
capabilities.maxImageCount) {
125 imageCount = swapChainSupport.
capabilities.maxImageCount;
128 VkSwapchainCreateInfoKHR createInfo {};
129 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
130 createInfo.surface = surface;
131 createInfo.minImageCount = imageCount;
132 createInfo.imageFormat = surfaceFormat.format;
133 createInfo.imageColorSpace = surfaceFormat.colorSpace;
134 createInfo.imageExtent = extent;
135 createInfo.imageArrayLayers = 1;
136 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
140 uint32_t queueFamilyIndices[]
144 createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
145 createInfo.queueFamilyIndexCount = 2;
146 createInfo.pQueueFamilyIndices = queueFamilyIndices;
148 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
149 createInfo.queueFamilyIndexCount = 0;
150 createInfo.pQueueFamilyIndices =
nullptr;
152 createInfo.preTransform = swapChainSupport.
capabilities.currentTransform;
153 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
154 createInfo.presentMode = presentMode;
155 createInfo.clipped = VK_TRUE;
156 createInfo.oldSwapchain = NULL;
158 if (vkCreateSwapchainKHR(device->device, &createInfo,
nullptr, &swapChain)
160 throw std::runtime_error(
"Failed to create swap chain");
162 vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount,
nullptr);
163 swapChainImages.resize(imageCount);
164 vkGetSwapchainImagesKHR(
165 device->device, swapChain, &imageCount, swapChainImages.data());
166 swapChainImageFormat = surfaceFormat.format;
167 swapChainExtent = extent;
172 swapChainImageViews.resize(swapChainImages.size());
173 for (
size_t i = 0; i < swapChainImages.size(); i++) {
175 *device, swapChainImageFormat, swapChainImages[i]);
181 VkFormat colorFormat = swapChainImageFormat;
182 createImage(*device, swapChainExtent.width, swapChainExtent.height,
183 colorFormat, VK_IMAGE_TILING_OPTIMAL,
184 VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
185 | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
186 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &colorImage, &colorImageMemory,
187 device->msaaSamples);
195 vkDestroyImageView(device->device, colorImageView,
nullptr);
196 vkDestroyImage(device->device, colorImage,
nullptr);
197 vkFreeMemory(device->device, colorImageMemory,
nullptr);
199 for (
auto imageView : swapChainImageViews) {
200 vkDestroyImageView(device->device, imageView,
nullptr);
203 vkDestroySwapchainKHR(device->device, swapChain,
nullptr);
208 int width = 0, height = 0;
209 glfwGetFramebufferSize(window, &width, &height);
210 while (width == 0 || height == 0) {
211 glfwGetFramebufferSize(window, &width, &height);
215 vkDeviceWaitIdle(device->device);
220 createColorResources();
226 vkDeviceWaitIdle(device->device);
230 createColorResources();
234 const std::vector<VkPresentModeKHR>& availablePresentModes)
264 for (
const auto& availablePresentMode : availablePresentModes) {
265 if (availablePresentMode == this->preferredPresentMode) {
266 return availablePresentMode;
270 return VK_PRESENT_MODE_FIFO_KHR;
This initializes, manages and destroys the logical and physical devices(GPU).
void createImageViews()
Creates the image views of the swapchain images.
Chronos::Engine::Device * device
Device to which swapchain needs to be created.
VkSurfaceKHR surface
Surface to which we need to present the swapchain images.
void create()
Creates the swapchain image resources and chooses the optimal settings for given hardware.
void cleanup()
Cleans up the assets that are rendered invalid during MSAA changes or swapchain.
GLFWwindow * window
The window to present the surface to.
void recreate()
When the swapchain is rendered invalid, recreate it.
void init(Chronos::Engine::Device *device, VkSurfaceKHR surface, GLFWwindow *window)
Initilize the swapchain.
void createColorResources()
Creates the color images along with the associated objects.
VkPresentModeKHR chooseSwapPresentMode(const std::vector< VkPresentModeKHR > &availablePresentModes)
From the available present mode, this chooses the the best present mode.
void changeMsaa()
Changes the MSAA count of the swapchain images.
Contains various common functions used by other classes in the Engine namespace.
VkImageView createImageView(Chronos::Engine::Device device, VkFormat format, VkImage image)
Create a VkImageView for a given VkImage.
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities, GLFWwindow *window)
Gets the maximum extent of the swapchain images(framebuffer size).
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector< VkSurfaceFormatKHR > &availableFormats)
Chooses the best present mode among the supported modes.
void createImage(Chronos::Engine::Device device, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage *image, VkDeviceMemory *imageMemory, VkSampleCountFlagBits numSamples)
For a given image dimensons, it creates a VkImage and.
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device, VkSurfaceKHR surface)
For a given swapchain mode, it gets the capabilites, formats and present modes.
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device, VkSurfaceKHR surface)
Gets the indices of the needed queue families.
This is used to check if a given familty supports graphics and presentation.
std::optional< uint32_t > presentFamily
std::optional< uint32_t > graphicsFamily
Contains the fields to the support details of a physical device.
VkSurfaceCapabilitiesKHR capabilities
std::vector< VkSurfaceFormatKHR > formats
std::vector< VkPresentModeKHR > presentModes
Contains the swapChain class along with all the swapChain related functions.
Contains the functions for image manipulation along with the Texture class.