Program Listing for File swapChain.cpp
↰ Return to documentation for file (PrismEngine/src/swapChain.cpp)
#include "swapChain.h"
#include "algorithm"
#include "logger.h"
#include "deviceChecker.h"
#include "deviceWrapper.h"
#include "resourcesCreater.h"
void prism::PGC::SwapChain::init(PGC::utils::Context* context, PGC::utils::Settings* settings)
{
this->context = context;
this->settings = settings;
create();
createImageViews();
}
prism::PGC::SwapChain::~SwapChain()
{
}
void prism::PGC::SwapChain::cleanup()
{
vkDestroyImageView(context->device, context->depthImageView, nullptr);
vkDestroyImage(context->device, context->depthImage, nullptr);
vkFreeMemory(context->device, context->depthImageMemory, nullptr);
vkDestroyImageView(context->device, context->colorImageView, nullptr);
vkDestroyImage(context->device, context->colorImage, nullptr);
vkFreeMemory(context->device, context->colorImageMemory, nullptr);
for (auto framebuffer : context->swapChainFramebuffers) {
vkDestroyFramebuffer(context->device, framebuffer, nullptr);
}
for (auto imageView : context->swapChainImageViews) {
vkDestroyImageView(context->device, imageView, nullptr);
}
vkDestroySwapchainKHR(context->device, context->vkSwapChain, nullptr);
}
void prism::PGC::SwapChain::awaitRenderingCompletion()
{
vkDeviceWaitIdle(context->device);
}
void prism::PGC::SwapChain::recreate()
{
awaitRenderingCompletion();
cleanup();
create();
createImageViews();
PGC::ResourcesCreater::createColorResources(context, settings);
PGC::ResourcesCreater::createDepthResources(context, settings);
PGC::ResourcesCreater::createFramebuffers(context, settings);
awaitRenderingCompletion();
}
void prism::PGC::SwapChain::create()
{
PGC::utils::SwapChainSupportDetails swapChainSupport = PGC::DeviceWrapper::querySwapChainSupport(context->physicalDevice, context->surface);
VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats);
VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes);
VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities);
uint32_t imageCount = getImageCount(swapChainSupport);
VkSwapchainCreateInfoKHR createInfo{};
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
createInfo.surface = context->surface;
createInfo.minImageCount = imageCount;
createInfo.imageFormat = surfaceFormat.format;
createInfo.imageColorSpace = surfaceFormat.colorSpace;
createInfo.imageExtent = extent;
createInfo.imageArrayLayers = 1;
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
PGC::utils::QueueFamilyIndices indices = PGC::DeviceWrapper::findQueueFamilies(context->physicalDevice, context->surface);
uint32_t queueFamilyIndices[] = { indices.graphicsFamily.value(), indices.presentFamily.value() };
if (indices.graphicsFamily != indices.presentFamily) {
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
createInfo.queueFamilyIndexCount = 2;
createInfo.pQueueFamilyIndices = queueFamilyIndices;
}
else {
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
createInfo.queueFamilyIndexCount = 0; // Optional
createInfo.pQueueFamilyIndices = nullptr; // Optional
}
createInfo.preTransform = swapChainSupport.capabilities.currentTransform;
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; //PL
createInfo.presentMode = presentMode;
createInfo.clipped = VK_TRUE;
createInfo.oldSwapchain = VK_NULL_HANDLE;
if (vkCreateSwapchainKHR(context->device, &createInfo, nullptr, &context->vkSwapChain) != VK_SUCCESS) {
logger::logError(logger::Error::VULKAN_SWAP_CHAIN_FAILED, "prism::PGC::SwapChain class");
}
vkGetSwapchainImagesKHR(context->device, context->vkSwapChain, &imageCount, nullptr);
context->swapChainImages.resize(imageCount);
vkGetSwapchainImagesKHR(context->device, context->vkSwapChain, &imageCount, context->swapChainImages.data());
context->swapChainImageFormat = surfaceFormat.format;
context->swapChainExtent = extent;
// Логируем выбранный режим
const char* presentModeStr = "";
switch (presentMode) {
case VK_PRESENT_MODE_FIFO_KHR: presentModeStr = "FIFO (VSync)"; break;
case VK_PRESENT_MODE_MAILBOX_KHR: presentModeStr = "MAILBOX (Triple Buffering)"; break;
case VK_PRESENT_MODE_IMMEDIATE_KHR: presentModeStr = "IMMEDIATE (No VSync)"; break;
}
logger::info("Swapchain Present Mode: " + std::to_string(*presentModeStr));
logger::info("Swapchain Image Count: " + std::to_string(swapChainSupport.capabilities.minImageCount + 1));
}
void prism::PGC::SwapChain::createImageViews()
{
context->swapChainImageViews.resize(context->swapChainImages.size());
for (uint32_t i = 0; i < context->swapChainImages.size(); i++) {
context->swapChainImageViews[i] = ResourcesCreater::createImageView(context->device, context->swapChainImages[i], context->swapChainImageFormat, VK_IMAGE_ASPECT_COLOR_BIT, 1);
}
}
VkSurfaceFormatKHR prism::PGC::SwapChain::chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>& availableFormats)
{
for (const auto& availableFormat : availableFormats) {
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
return availableFormat;
}
}
return availableFormats[0];
}
VkPresentModeKHR prism::PGC::SwapChain::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes)
{
if (settings->swapChain.enableTripleBuffering) {
for (const auto& availablePresentMode : availablePresentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
return availablePresentMode;
}
}
}
return settings->swapChain.enableVSync ? VK_PRESENT_MODE_FIFO_KHR : VK_PRESENT_MODE_IMMEDIATE_KHR;
}
VkExtent2D prism::PGC::SwapChain::chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities)
{
if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
return capabilities.currentExtent;
}
else {
int width, height;
SDL_GetWindowSizeInPixels(settings->window, &width, &height);
VkExtent2D actualExtent = {
static_cast<uint32_t>(width),
static_cast<uint32_t>(height)
};
actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
return actualExtent;
}
}
uint32_t prism::PGC::SwapChain::getImageCount(PGC::utils::SwapChainSupportDetails swapChainSupport)
{
uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1;
if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) {
imageCount = swapChainSupport.capabilities.maxImageCount;
}
return imageCount;
}