136 lines
5.5 KiB
C++
136 lines
5.5 KiB
C++
#include "SwapChain.hpp"
|
|
|
|
#include "shared.hpp"
|
|
|
|
using namespace render::vk;
|
|
|
|
SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(device) {
|
|
{ // Swapchain
|
|
VkPresentModeKHR presentMode = [&]() {
|
|
// MAYBE: add prefer no triple buffering options
|
|
for (const auto& availablePresentMode: info.swapDetails.presentModes) {
|
|
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
|
return availablePresentMode;
|
|
}
|
|
}
|
|
|
|
return VK_PRESENT_MODE_FIFO_KHR;
|
|
}();
|
|
|
|
uint32_t imageCount = info.swapDetails.capabilities.minImageCount + 1;
|
|
if (info.swapDetails.capabilities.maxImageCount > 0 && imageCount > info.swapDetails.capabilities.maxImageCount) {
|
|
imageCount = info.swapDetails.capabilities.maxImageCount;
|
|
}
|
|
|
|
VkSwapchainCreateInfoKHR createInfo{};
|
|
createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
createInfo.surface = info.surface;
|
|
createInfo.minImageCount = imageCount;
|
|
createInfo.imageFormat = info.surfaceFormat.format;
|
|
createInfo.imageColorSpace = info.surfaceFormat.colorSpace;
|
|
createInfo.imageExtent = info.swapDetails.capabilities.currentExtent;
|
|
createInfo.imageArrayLayers = 1;
|
|
createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; //VK_IMAGE_USAGE_TRANSFER_DST_BIT
|
|
|
|
if (info.queueIndices.graphicsFamily != info.queueIndices.presentFamily) {
|
|
uint32_t queueFamilyIndices[] = {info.queueIndices.graphicsFamily.value(), info.queueIndices.presentFamily.value()};
|
|
createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
createInfo.queueFamilyIndexCount = 2;
|
|
createInfo.pQueueFamilyIndices = queueFamilyIndices;
|
|
} else {
|
|
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
createInfo.queueFamilyIndexCount = 0;
|
|
createInfo.pQueueFamilyIndices = nullptr;
|
|
}
|
|
createInfo.preTransform = info.swapDetails.capabilities.currentTransform;
|
|
createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
createInfo.presentMode = presentMode;
|
|
createInfo.clipped = VK_TRUE;
|
|
createInfo.oldSwapchain = chain;
|
|
|
|
if (vkCreateSwapchainKHR(device, &createInfo, ALLOC, &chain) != VK_SUCCESS) {
|
|
FATAL("Failed to create swap chain!");
|
|
}
|
|
}
|
|
|
|
{ // Images
|
|
uint32_t imageCount;
|
|
vkGetSwapchainImagesKHR(device, chain, &imageCount, nullptr);
|
|
images.resize(imageCount);
|
|
vkGetSwapchainImagesKHR(device, chain, &imageCount, images.data());
|
|
|
|
imageViews.resize(images.size());
|
|
for (size_t i = 0; i < images.size(); i++) {
|
|
VkImageViewCreateInfo createInfo{};
|
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
createInfo.image = images[i];
|
|
|
|
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
createInfo.format = info.surfaceFormat.format;
|
|
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
createInfo.subresourceRange.baseMipLevel = 0;
|
|
createInfo.subresourceRange.levelCount = 1;
|
|
createInfo.subresourceRange.baseArrayLayer = 0;
|
|
createInfo.subresourceRange.layerCount = 1;
|
|
|
|
if (vkCreateImageView(device, &createInfo, ALLOC, &imageViews[i]) != VK_SUCCESS) {
|
|
FATAL("Failed to create image views!");
|
|
}
|
|
}
|
|
}
|
|
|
|
imagesInFlight.resize(imageViews.size(), VK_NULL_HANDLE);
|
|
}
|
|
SwapChain::~SwapChain() {
|
|
for (auto imageView: imageViews) {
|
|
vkDestroyImageView(device, imageView, ALLOC);
|
|
}
|
|
vkDestroySwapchainKHR(device, chain, ALLOC);
|
|
}
|
|
|
|
std::optional<uint32_t> SwapChain::acquireNextImage(VkSemaphore semaphore, VkFence fence) {
|
|
uint32_t imageIndex;
|
|
auto result = vkAcquireNextImageKHR(device, chain, UINT64_MAX, semaphore, VK_NULL_HANDLE, &imageIndex);
|
|
if (result == VK_ERROR_OUT_OF_DATE_KHR)
|
|
return {};
|
|
|
|
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) {
|
|
FATAL("Failed to acquire swap chain image!");
|
|
}
|
|
|
|
// Check if a previous frame is using this image (i.e. there is its fence to wait on)
|
|
if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) {
|
|
vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX);
|
|
}
|
|
// Mark the image as now being in use by this frame
|
|
imagesInFlight[imageIndex] = fence;
|
|
return imageIndex;
|
|
}
|
|
bool SwapChain::presentImage(uint32_t idx, VkQueue queue, VkSemaphore signalSemaphore) {
|
|
VkSemaphore signalSemaphores[] = {signalSemaphore};
|
|
|
|
VkPresentInfoKHR presentInfo{};
|
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
presentInfo.waitSemaphoreCount = 1;
|
|
presentInfo.pWaitSemaphores = signalSemaphores;
|
|
|
|
VkSwapchainKHR swapChains[] = {chain};
|
|
presentInfo.swapchainCount = 1;
|
|
presentInfo.pSwapchains = swapChains;
|
|
presentInfo.pImageIndices = &idx;
|
|
presentInfo.pResults = nullptr;
|
|
|
|
auto result = vkQueuePresentKHR(queue, &presentInfo);
|
|
|
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR) {
|
|
return false;
|
|
} else if (result != VK_SUCCESS) {
|
|
FATAL("Failed to present swap chain image!");
|
|
}
|
|
return true;
|
|
} |