Vulkan Refactoring - Implemented KRSwapchain
This commit is contained in:
@@ -28,6 +28,7 @@ add_sources(KRRenderPass.cpp)
|
|||||||
add_sources(KRSurface.cpp)
|
add_sources(KRSurface.cpp)
|
||||||
add_sources(KRSurfaceManager.cpp)
|
add_sources(KRSurfaceManager.cpp)
|
||||||
add_sources(KRStreamerThread.cpp)
|
add_sources(KRStreamerThread.cpp)
|
||||||
|
add_sources(KRSwapchain.cpp)
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
add_sources(KREngine.mm)
|
add_sources(KREngine.mm)
|
||||||
|
|
||||||
|
|||||||
@@ -234,3 +234,81 @@ VmaAllocator KRDevice::getAllocator()
|
|||||||
assert(m_allocator != VK_NULL_HANDLE);
|
assert(m_allocator != VK_NULL_HANDLE);
|
||||||
return m_allocator;
|
return m_allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KrResult KRDevice::selectSurfaceFormat(VkSurfaceKHR& surface, VkSurfaceFormatKHR& selectedFormat)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<VkSurfaceFormatKHR> surfaceFormats;
|
||||||
|
uint32_t formatCount = 0;
|
||||||
|
if (vkGetPhysicalDeviceSurfaceFormatsKHR(m_device, surface, &formatCount, nullptr) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formatCount != 0) {
|
||||||
|
surfaceFormats.resize(formatCount);
|
||||||
|
if (vkGetPhysicalDeviceSurfaceFormatsKHR(m_device, surface, &formatCount, surfaceFormats.data()) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedFormat = surfaceFormats[0];
|
||||||
|
for (const auto& availableFormat : surfaceFormats) {
|
||||||
|
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||||
|
selectedFormat = availableFormat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrResult KRDevice::selectDepthFormat(VkFormat& selectedDepthFormat)
|
||||||
|
{
|
||||||
|
selectedDepthFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
VkFormatFeatureFlags requiredFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
std::vector<VkFormat> candidateFormats;
|
||||||
|
candidateFormats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
|
||||||
|
candidateFormats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
|
||||||
|
for (VkFormat format : candidateFormats) {
|
||||||
|
VkFormatProperties props;
|
||||||
|
vkGetPhysicalDeviceFormatProperties(m_device, format, &props);
|
||||||
|
|
||||||
|
if ((props.optimalTilingFeatures & requiredFeatures) == requiredFeatures) {
|
||||||
|
selectedDepthFormat = format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedDepthFormat == VK_FORMAT_UNDEFINED) {
|
||||||
|
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
KrResult KRDevice::selectPresentMode(VkSurfaceKHR& surface, VkPresentModeKHR& selectedPresentMode)
|
||||||
|
{
|
||||||
|
// VK_PRESENT_MODE_FIFO_KHR is always available
|
||||||
|
selectedPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
|
|
||||||
|
std::vector<VkPresentModeKHR> surfacePresentModes;
|
||||||
|
|
||||||
|
uint32_t presentModeCount = 0;
|
||||||
|
if (vkGetPhysicalDeviceSurfacePresentModesKHR(m_device, surface, &presentModeCount, nullptr) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentModeCount != 0) {
|
||||||
|
surfacePresentModes.resize(presentModeCount);
|
||||||
|
if (vkGetPhysicalDeviceSurfacePresentModesKHR(m_device, surface, &presentModeCount, surfacePresentModes.data()) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to find a better mode
|
||||||
|
for (const auto& availablePresentMode : surfacePresentModes) {
|
||||||
|
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||||
|
selectedPresentMode = availablePresentMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ public:
|
|||||||
|
|
||||||
VmaAllocator getAllocator();
|
VmaAllocator getAllocator();
|
||||||
|
|
||||||
|
KrResult selectSurfaceFormat(VkSurfaceKHR& surface, VkSurfaceFormatKHR& surfaceFormat);
|
||||||
|
KrResult selectDepthFormat(VkFormat& selectedDepthFormat);
|
||||||
|
KrResult selectPresentMode(VkSurfaceKHR& surface, VkPresentModeKHR& selectedPresentMode);
|
||||||
|
|
||||||
VkPhysicalDevice m_device;
|
VkPhysicalDevice m_device;
|
||||||
VkDevice m_logicalDevice;
|
VkDevice m_logicalDevice;
|
||||||
VkPhysicalDeviceProperties m_deviceProperties;
|
VkPhysicalDeviceProperties m_deviceProperties;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include "KRDirectionalLight.h"
|
#include "KRDirectionalLight.h"
|
||||||
#include "KRSpotLight.h"
|
#include "KRSpotLight.h"
|
||||||
#include "KRPointLight.h"
|
#include "KRPointLight.h"
|
||||||
|
#include "KRSwapchain.h"
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
#include "glslang/Public/ShaderLang.h"
|
#include "glslang/Public/ShaderLang.h"
|
||||||
@@ -67,9 +68,9 @@ KRPipeline* KRPipelineManager::getPipeline(KRSurface& surface, KRRenderPass& ren
|
|||||||
std::pair<std::string, std::vector<int> > key;
|
std::pair<std::string, std::vector<int> > key;
|
||||||
key.first = shader_name;
|
key.first = shader_name;
|
||||||
key.second.push_back(surface.m_deviceHandle);
|
key.second.push_back(surface.m_deviceHandle);
|
||||||
key.second.push_back(surface.m_swapChainImageFormat);
|
key.second.push_back(surface.m_swapChain->m_imageFormat);
|
||||||
key.second.push_back(surface.m_swapChainExtent.width);
|
key.second.push_back(surface.m_swapChain->m_extent.width);
|
||||||
key.second.push_back(surface.m_swapChainExtent.height);
|
key.second.push_back(surface.m_swapChain->m_extent.height);
|
||||||
key.second.push_back(vertexAttributes);
|
key.second.push_back(vertexAttributes);
|
||||||
key.second.push_back(modelFormat);
|
key.second.push_back(modelFormat);
|
||||||
// TODO - Add renderPass unique identifier to key
|
// TODO - Add renderPass unique identifier to key
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
#include "KRPresentationThread.h"
|
#include "KRPresentationThread.h"
|
||||||
#include "KRRenderPass.h"
|
#include "KRRenderPass.h"
|
||||||
|
#include "KRSwapchain.h"
|
||||||
|
|
||||||
KRPresentationThread::KRPresentationThread(KRContext& context)
|
KRPresentationThread::KRPresentationThread(KRContext& context)
|
||||||
: KRContextObject(context)
|
: KRContextObject(context)
|
||||||
@@ -116,15 +117,15 @@ void KRPresentationThread::renderFrame()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool resized = false;
|
bool resized = false;
|
||||||
if (surface.m_swapChainExtent.width != surfaceCapabilities.currentExtent.width ||
|
if (surface.m_swapChain->m_extent.width != surfaceCapabilities.currentExtent.width ||
|
||||||
surface.m_swapChainExtent.height != surfaceCapabilities.currentExtent.height) {
|
surface.m_swapChain->m_extent.height != surfaceCapabilities.currentExtent.height) {
|
||||||
// We can't rely on VK_ERROR_OUT_OF_DATE_KHR to always signal when a resize has happend.
|
// We can't rely on VK_ERROR_OUT_OF_DATE_KHR to always signal when a resize has happend.
|
||||||
// This must also be checked for explicitly.
|
// This must also be checked for explicitly.
|
||||||
resized = true;
|
resized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t imageIndex = 0;
|
uint32_t imageIndex = 0;
|
||||||
VkResult result = vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
|
VkResult result = vkAcquireNextImageKHR(device.m_logicalDevice, surface.m_swapChain->m_swapChain, UINT64_MAX, surface.m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
|
||||||
|
|
||||||
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || resized) {
|
if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || resized) {
|
||||||
// TODO - Must explicitly detect resize and trigger swapchain re-creation as well
|
// TODO - Must explicitly detect resize and trigger swapchain re-creation as well
|
||||||
@@ -154,7 +155,7 @@ void KRPresentationThread::renderFrame()
|
|||||||
// TODO - This needs to be moved to the Render thread...
|
// TODO - This needs to be moved to the Render thread...
|
||||||
float deltaTime = 0.005; // TODO - Replace dummy value
|
float deltaTime = 0.005; // TODO - Replace dummy value
|
||||||
if (scene) {
|
if (scene) {
|
||||||
scene->renderFrame(commandBuffer, surface, 0, deltaTime, surface.m_swapChainExtent.width, surface.m_swapChainExtent.height);
|
scene->renderFrame(commandBuffer, surface, 0, deltaTime, surface.m_swapChain->m_extent.width, surface.m_swapChain->m_extent.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
if (vkEndCommandBuffer(commandBuffer) != VK_SUCCESS) {
|
||||||
@@ -187,7 +188,7 @@ void KRPresentationThread::renderFrame()
|
|||||||
presentInfo.waitSemaphoreCount = 1;
|
presentInfo.waitSemaphoreCount = 1;
|
||||||
presentInfo.pWaitSemaphores = signalSemaphores;
|
presentInfo.pWaitSemaphores = signalSemaphores;
|
||||||
presentInfo.swapchainCount = 1;
|
presentInfo.swapchainCount = 1;
|
||||||
presentInfo.pSwapchains = &surface.m_swapChain;
|
presentInfo.pSwapchains = &surface.m_swapChain->m_swapChain;
|
||||||
presentInfo.pImageIndices = &imageIndex;
|
presentInfo.pImageIndices = &imageIndex;
|
||||||
presentInfo.pResults = nullptr;
|
presentInfo.pResults = nullptr;
|
||||||
vkQueuePresentKHR(device.m_graphicsQueue, &presentInfo);
|
vkQueuePresentKHR(device.m_graphicsQueue, &presentInfo);
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "KRRenderPass.h"
|
#include "KRRenderPass.h"
|
||||||
#include "KRSurface.h""
|
#include "KRSurface.h"
|
||||||
|
#include "KRSwapchain.h"
|
||||||
|
|
||||||
KRRenderPass::KRRenderPass(KRContext& context)
|
KRRenderPass::KRRenderPass(KRContext& context)
|
||||||
: KRContextObject(context)
|
: KRContextObject(context)
|
||||||
@@ -126,9 +127,9 @@ void KRRenderPass::begin(VkCommandBuffer& commandBuffer, KRSurface& surface)
|
|||||||
VkRenderPassBeginInfo renderPassInfo{};
|
VkRenderPassBeginInfo renderPassInfo{};
|
||||||
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
|
||||||
renderPassInfo.renderPass = m_renderPass;
|
renderPassInfo.renderPass = m_renderPass;
|
||||||
renderPassInfo.framebuffer = surface.m_swapChainFramebuffers[surface.m_frameIndex % surface.m_swapChainFramebuffers.size()];
|
renderPassInfo.framebuffer = surface.m_swapChain->m_framebuffers[surface.m_frameIndex % surface.m_swapChain->m_framebuffers.size()];
|
||||||
renderPassInfo.renderArea.offset = { 0, 0 };
|
renderPassInfo.renderArea.offset = { 0, 0 };
|
||||||
renderPassInfo.renderArea.extent = surface.m_swapChainExtent;
|
renderPassInfo.renderArea.extent = surface.m_swapChain->m_extent;
|
||||||
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
|
renderPassInfo.clearValueCount = static_cast<uint32_t>(clearValues.size());
|
||||||
renderPassInfo.pClearValues = clearValues.data();
|
renderPassInfo.pClearValues = clearValues.data();
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "KRSurface.h"
|
#include "KRSurface.h"
|
||||||
|
#include "KRSwapchain.h"
|
||||||
#include "KRRenderPass.h"
|
#include "KRRenderPass.h"
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -43,18 +44,12 @@ KRSurface::KRSurface(KRContext& context)
|
|||||||
#endif
|
#endif
|
||||||
, m_deviceHandle(VK_NULL_HANDLE)
|
, m_deviceHandle(VK_NULL_HANDLE)
|
||||||
, m_surface(VK_NULL_HANDLE)
|
, m_surface(VK_NULL_HANDLE)
|
||||||
, m_swapChain(VK_NULL_HANDLE)
|
|
||||||
, m_swapChainImageFormat(VK_FORMAT_UNDEFINED)
|
|
||||||
, m_swapChainExtent({ 0, 0 })
|
|
||||||
, m_depthImageFormat(VK_FORMAT_UNDEFINED)
|
|
||||||
, m_depthImage(VK_NULL_HANDLE)
|
|
||||||
, m_depthImageAllocation(VK_NULL_HANDLE)
|
|
||||||
, m_depthImageView(VK_NULL_HANDLE)
|
|
||||||
, m_imageAvailableSemaphore(VK_NULL_HANDLE)
|
, m_imageAvailableSemaphore(VK_NULL_HANDLE)
|
||||||
, m_renderFinishedSemaphore(VK_NULL_HANDLE)
|
, m_renderFinishedSemaphore(VK_NULL_HANDLE)
|
||||||
, m_frameIndex(0)
|
, m_frameIndex(0)
|
||||||
{
|
{
|
||||||
m_forwardOpaquePass = std::make_unique<KRRenderPass>(context);
|
m_forwardOpaquePass = std::make_unique<KRRenderPass>(context);
|
||||||
|
m_swapChain = std::make_unique<KRSwapchain>(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
KRSurface::~KRSurface()
|
KRSurface::~KRSurface()
|
||||||
@@ -119,222 +114,41 @@ void KRSurface::destroy()
|
|||||||
|
|
||||||
KrResult KRSurface::createSwapChain()
|
KrResult KRSurface::createSwapChain()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::unique_ptr<KRDevice>& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
std::unique_ptr<KRDevice>& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
||||||
|
|
||||||
|
KrResult res = KR_SUCCESS;
|
||||||
|
VkSurfaceFormatKHR selectedSurfaceFormat{};
|
||||||
|
res =device->selectSurfaceFormat(m_surface, selectedSurfaceFormat);
|
||||||
|
if (res != KR_SUCCESS) return res;
|
||||||
|
|
||||||
|
VkFormat depthImageFormat = VK_FORMAT_UNDEFINED;
|
||||||
|
res = device->selectDepthFormat(depthImageFormat);
|
||||||
|
if (res != KR_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
VkSurfaceCapabilitiesKHR surfaceCapabilities{};
|
VkSurfaceCapabilitiesKHR surfaceCapabilities{};
|
||||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->m_device, m_surface, &surfaceCapabilities);
|
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->m_device, m_surface, &surfaceCapabilities);
|
||||||
|
|
||||||
std::vector<VkSurfaceFormatKHR> surfaceFormats;
|
|
||||||
uint32_t formatCount = 0;
|
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device->m_device, m_surface, &formatCount, nullptr);
|
|
||||||
|
|
||||||
if (formatCount != 0) {
|
|
||||||
surfaceFormats.resize(formatCount);
|
|
||||||
vkGetPhysicalDeviceSurfaceFormatsKHR(device->m_device, m_surface, &formatCount, surfaceFormats.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<VkPresentModeKHR> surfacePresentModes;
|
|
||||||
|
|
||||||
uint32_t presentModeCount = 0;
|
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->m_device, m_surface, &presentModeCount, nullptr);
|
|
||||||
|
|
||||||
if (presentModeCount != 0) {
|
|
||||||
surfacePresentModes.resize(presentModeCount);
|
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->m_device, m_surface, &presentModeCount, surfacePresentModes.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
VkSurfaceFormatKHR selectedSurfaceFormat = surfaceFormats[0];
|
|
||||||
for (const auto& availableFormat : surfaceFormats) {
|
|
||||||
if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
|
||||||
selectedSurfaceFormat = availableFormat;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// VK_PRESENT_MODE_FIFO_KHR is always available
|
|
||||||
VkPresentModeKHR selectedPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
|
||||||
|
|
||||||
// Try to find a better mode
|
|
||||||
for (const auto& availablePresentMode : surfacePresentModes) {
|
|
||||||
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
|
|
||||||
selectedPresentMode = availablePresentMode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
VkExtent2D swapExtent;
|
VkExtent2D swapExtent;
|
||||||
if (surfaceCapabilities.currentExtent.width != UINT32_MAX) {
|
if (surfaceCapabilities.currentExtent.width != UINT32_MAX) {
|
||||||
swapExtent = surfaceCapabilities.currentExtent;
|
swapExtent = surfaceCapabilities.currentExtent;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const uint32_t MAX_WIDTH = 8192;
|
const uint32_t MAX_WIDTH = 8192;
|
||||||
const uint32_t MAX_HEIGHT = 8192;
|
const uint32_t MAX_HEIGHT = 8192;
|
||||||
swapExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, MAX_WIDTH));
|
swapExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, MAX_WIDTH));
|
||||||
swapExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, MAX_HEIGHT));
|
swapExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, MAX_HEIGHT));
|
||||||
}
|
}
|
||||||
m_swapChainExtent = swapExtent;
|
|
||||||
|
|
||||||
uint32_t imageCount = surfaceCapabilities.minImageCount + 1;
|
uint32_t imageCount = surfaceCapabilities.minImageCount + 1;
|
||||||
if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) {
|
if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) {
|
||||||
imageCount = surfaceCapabilities.maxImageCount;
|
imageCount = surfaceCapabilities.maxImageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSwapchainCreateInfoKHR swapChainCreateInfo{};
|
|
||||||
swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
||||||
swapChainCreateInfo.surface = m_surface;
|
|
||||||
swapChainCreateInfo.minImageCount = imageCount;
|
|
||||||
swapChainCreateInfo.imageFormat = selectedSurfaceFormat.format;
|
|
||||||
swapChainCreateInfo.imageColorSpace = selectedSurfaceFormat.colorSpace;
|
|
||||||
swapChainCreateInfo.imageExtent = swapExtent;
|
|
||||||
swapChainCreateInfo.imageArrayLayers = 1;
|
|
||||||
swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
||||||
|
|
||||||
uint32_t queueFamilyIndices[] = {
|
m_forwardOpaquePass->create(*device, selectedSurfaceFormat.format, depthImageFormat);
|
||||||
device->m_graphicsFamilyQueueIndex,
|
m_swapChain->create(*device, m_surface, selectedSurfaceFormat, depthImageFormat, swapExtent, imageCount, *m_forwardOpaquePass);
|
||||||
device->m_computeFamilyQueueIndex
|
|
||||||
};
|
|
||||||
if (device->m_graphicsFamilyQueueIndex == device->m_computeFamilyQueueIndex) {
|
|
||||||
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
swapChainCreateInfo.queueFamilyIndexCount = 0;
|
|
||||||
swapChainCreateInfo.pQueueFamilyIndices = nullptr;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
|
||||||
swapChainCreateInfo.queueFamilyIndexCount = 2;
|
|
||||||
swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
|
|
||||||
}
|
|
||||||
|
|
||||||
swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
|
|
||||||
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
||||||
swapChainCreateInfo.presentMode = selectedPresentMode;
|
|
||||||
swapChainCreateInfo.clipped = VK_TRUE;
|
|
||||||
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
|
|
||||||
|
|
||||||
if (vkCreateSwapchainKHR(device->m_logicalDevice, &swapChainCreateInfo, nullptr, &m_swapChain) != VK_SUCCESS) {
|
|
||||||
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
|
||||||
}
|
|
||||||
|
|
||||||
vkGetSwapchainImagesKHR(device->m_logicalDevice, m_swapChain, &imageCount, nullptr);
|
|
||||||
m_swapChainImages.resize(imageCount);
|
|
||||||
vkGetSwapchainImagesKHR(device->m_logicalDevice, m_swapChain, &imageCount, m_swapChainImages.data());
|
|
||||||
|
|
||||||
m_swapChainImageFormat = selectedSurfaceFormat.format;
|
|
||||||
|
|
||||||
m_swapChainImageViews.resize(m_swapChainImages.size());
|
|
||||||
for (size_t i = 0; i < m_swapChainImages.size(); i++) {
|
|
||||||
VkImageViewCreateInfo createInfo{};
|
|
||||||
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
createInfo.image = m_swapChainImages[i];
|
|
||||||
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
||||||
createInfo.format = m_swapChainImageFormat;
|
|
||||||
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->m_logicalDevice, &createInfo, nullptr, &m_swapChainImageViews[i]) != VK_SUCCESS) {
|
|
||||||
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_depthImageFormat = VK_FORMAT_UNDEFINED;
|
|
||||||
VkFormatFeatureFlags requiredFeatures = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
|
||||||
std::vector<VkFormat> candidateFormats;
|
|
||||||
candidateFormats.push_back(VK_FORMAT_D32_SFLOAT_S8_UINT);
|
|
||||||
candidateFormats.push_back(VK_FORMAT_D24_UNORM_S8_UINT);
|
|
||||||
for (VkFormat format : candidateFormats) {
|
|
||||||
VkFormatProperties props;
|
|
||||||
vkGetPhysicalDeviceFormatProperties(device->m_device, format, &props);
|
|
||||||
|
|
||||||
if ((props.optimalTilingFeatures & requiredFeatures) == requiredFeatures) {
|
|
||||||
m_depthImageFormat = format;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_depthImageFormat == VK_FORMAT_UNDEFINED) {
|
|
||||||
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
createImage(swapChainExtent.width, swapChainExtent.height, depthFormat, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, depthImage, depthImageMemory);
|
|
||||||
depthImageView = createImageView(depthImage, depthFormat);
|
|
||||||
*/
|
|
||||||
{
|
|
||||||
VkImageCreateInfo imageInfo{};
|
|
||||||
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
||||||
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
|
||||||
imageInfo.extent.width = m_swapChainExtent.width;
|
|
||||||
imageInfo.extent.height = m_swapChainExtent.height;
|
|
||||||
imageInfo.extent.depth = 1;
|
|
||||||
imageInfo.mipLevels = 1;
|
|
||||||
imageInfo.arrayLayers = 1;
|
|
||||||
imageInfo.format = m_depthImageFormat;
|
|
||||||
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
|
||||||
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
|
||||||
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
|
||||||
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
||||||
imageInfo.flags = 0;
|
|
||||||
|
|
||||||
VmaAllocator allocator = device->getAllocator();
|
|
||||||
VmaAllocationCreateInfo allocationCreateInfo{};
|
|
||||||
allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
|
||||||
allocationCreateInfo.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
|
||||||
|
|
||||||
if (vmaCreateImage(allocator, &imageInfo, &allocationCreateInfo, &m_depthImage, &m_depthImageAllocation, nullptr) != VK_SUCCESS) {
|
|
||||||
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
VkImageViewCreateInfo viewInfo{};
|
|
||||||
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
||||||
viewInfo.image = m_depthImage;
|
|
||||||
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
||||||
viewInfo.format = m_depthImageFormat;
|
|
||||||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
||||||
viewInfo.subresourceRange.baseMipLevel = 0;
|
|
||||||
viewInfo.subresourceRange.levelCount = 1;
|
|
||||||
viewInfo.subresourceRange.baseArrayLayer = 0;
|
|
||||||
viewInfo.subresourceRange.layerCount = 1;
|
|
||||||
|
|
||||||
if (vkCreateImageView(device->m_logicalDevice, &viewInfo, nullptr, &m_depthImageView) != VK_SUCCESS) {
|
|
||||||
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO - Track memory usage
|
|
||||||
|
|
||||||
VkMemoryRequirements memRequirements;
|
|
||||||
vkGetImageMemoryRequirements(device->m_logicalDevice, m_depthImage, &memRequirements);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
createRenderPasses();
|
|
||||||
|
|
||||||
m_swapChainFramebuffers.resize(m_swapChainImageViews.size());
|
|
||||||
|
|
||||||
for (size_t i = 0; i < m_swapChainImageViews.size(); i++) {
|
|
||||||
std::array<VkImageView, 2> attachments = {
|
|
||||||
m_swapChainImageViews[i],
|
|
||||||
m_depthImageView
|
|
||||||
};
|
|
||||||
|
|
||||||
VkFramebufferCreateInfo framebufferInfo{};
|
|
||||||
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
|
||||||
framebufferInfo.renderPass = m_forwardOpaquePass->m_renderPass;
|
|
||||||
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
|
||||||
framebufferInfo.pAttachments = attachments.data();
|
|
||||||
framebufferInfo.width = m_swapChainExtent.width;
|
|
||||||
framebufferInfo.height = m_swapChainExtent.height;
|
|
||||||
framebufferInfo.layers = 1;
|
|
||||||
|
|
||||||
if (vkCreateFramebuffer(device->m_logicalDevice, &framebufferInfo, nullptr, &m_swapChainFramebuffers[i]) != VK_SUCCESS) {
|
|
||||||
return KR_ERROR_VULKAN_FRAMEBUFFER;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return KR_SUCCESS;
|
return KR_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -347,33 +161,9 @@ void KRSurface::destroySwapChain()
|
|||||||
std::unique_ptr<KRDevice>& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
std::unique_ptr<KRDevice>& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
||||||
// TODO - Handle device removal
|
// TODO - Handle device removal
|
||||||
if (device) {
|
if (device) {
|
||||||
for (auto framebuffer : m_swapChainFramebuffers) {
|
m_swapChain->destroy(*device);
|
||||||
vkDestroyFramebuffer(device->m_logicalDevice, framebuffer, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto imageView : m_swapChainImageViews) {
|
|
||||||
vkDestroyImageView(device->m_logicalDevice, imageView, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_swapChain != VK_NULL_HANDLE) {
|
|
||||||
vkDestroySwapchainKHR(device->m_logicalDevice, m_swapChain, nullptr);
|
|
||||||
m_swapChain = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_depthImageView) {
|
|
||||||
vkDestroyImageView(device->m_logicalDevice, m_depthImageView, nullptr);
|
|
||||||
m_depthImageView = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_depthImage) {
|
|
||||||
vmaDestroyImage(device->getAllocator(), m_depthImage, m_depthImageAllocation);
|
|
||||||
m_depthImage = VK_NULL_HANDLE;
|
|
||||||
m_depthImageAllocation = VK_NULL_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_swapChainFramebuffers.clear();
|
|
||||||
m_swapChainImageViews.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KrResult KRSurface::recreateSwapChain()
|
KrResult KRSurface::recreateSwapChain()
|
||||||
@@ -386,12 +176,6 @@ KrResult KRSurface::recreateSwapChain()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void KRSurface::createRenderPasses()
|
|
||||||
{
|
|
||||||
std::unique_ptr<KRDevice>& device = m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
|
||||||
m_forwardOpaquePass->create(*device, m_swapChainImageFormat, m_depthImageFormat);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<KRDevice>& KRSurface::getDevice()
|
std::unique_ptr<KRDevice>& KRSurface::getDevice()
|
||||||
{
|
{
|
||||||
return m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
return m_pContext->getDeviceManager()->getDevice(m_deviceHandle);
|
||||||
@@ -399,17 +183,17 @@ std::unique_ptr<KRDevice>& KRSurface::getDevice()
|
|||||||
|
|
||||||
uint32_t KRSurface::getWidth() const
|
uint32_t KRSurface::getWidth() const
|
||||||
{
|
{
|
||||||
return m_swapChainExtent.width;
|
return m_swapChain->m_extent.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t KRSurface::getHeight() const
|
uint32_t KRSurface::getHeight() const
|
||||||
{
|
{
|
||||||
return m_swapChainExtent.height;
|
return m_swapChain->m_extent.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkFormat KRSurface::getDepthFormat() const
|
VkFormat KRSurface::getDepthFormat() const
|
||||||
{
|
{
|
||||||
return m_depthImageFormat;
|
return m_swapChain->m_depthFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
class KRDevice;
|
class KRDevice;
|
||||||
class KRRenderPass;
|
class KRRenderPass;
|
||||||
|
class KRSwapchain;
|
||||||
|
|
||||||
class KRSurface : public KRContextObject
|
class KRSurface : public KRContextObject
|
||||||
{
|
{
|
||||||
@@ -58,7 +59,6 @@ public:
|
|||||||
|
|
||||||
KrResult initialize();
|
KrResult initialize();
|
||||||
KrResult recreateSwapChain();
|
KrResult recreateSwapChain();
|
||||||
void createRenderPasses();
|
|
||||||
KRRenderPass& getForwardOpaquePass();
|
KRRenderPass& getForwardOpaquePass();
|
||||||
|
|
||||||
void endFrame();
|
void endFrame();
|
||||||
@@ -68,19 +68,11 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
KrDeviceHandle m_deviceHandle;
|
KrDeviceHandle m_deviceHandle;
|
||||||
VkSurfaceKHR m_surface;
|
VkSurfaceKHR m_surface;
|
||||||
VkSwapchainKHR m_swapChain;
|
|
||||||
std::vector<VkImage> m_swapChainImages;
|
|
||||||
VkFormat m_swapChainImageFormat;
|
|
||||||
VkExtent2D m_swapChainExtent;
|
|
||||||
std::vector<VkImageView> m_swapChainImageViews;
|
|
||||||
std::vector<VkFramebuffer> m_swapChainFramebuffers;
|
|
||||||
VkFormat m_depthImageFormat;
|
|
||||||
VkImage m_depthImage;
|
|
||||||
VmaAllocation m_depthImageAllocation;
|
|
||||||
VkImageView m_depthImageView;
|
|
||||||
VkSemaphore m_imageAvailableSemaphore;
|
VkSemaphore m_imageAvailableSemaphore;
|
||||||
VkSemaphore m_renderFinishedSemaphore;
|
VkSemaphore m_renderFinishedSemaphore;
|
||||||
|
|
||||||
|
std::unique_ptr<KRSwapchain> m_swapChain;
|
||||||
std::unique_ptr<KRRenderPass> m_forwardOpaquePass;
|
std::unique_ptr<KRRenderPass> m_forwardOpaquePass;
|
||||||
|
|
||||||
// TODO - This needs to be advanced per swap chain
|
// TODO - This needs to be advanced per swap chain
|
||||||
|
|||||||
232
kraken/KRSwapchain.cpp
Normal file
232
kraken/KRSwapchain.cpp
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
//
|
||||||
|
// KRSwapchain.cpp
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2021 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "KRSwapchain.h"
|
||||||
|
#include "KRRenderPass.h"
|
||||||
|
|
||||||
|
KRSwapchain::KRSwapchain(KRContext& context)
|
||||||
|
: KRContextObject(context)
|
||||||
|
, m_swapChain(VK_NULL_HANDLE)
|
||||||
|
, m_extent({ 0, 0 })
|
||||||
|
, m_imageFormat(VK_FORMAT_UNDEFINED)
|
||||||
|
, m_depthFormat(VK_FORMAT_UNDEFINED)
|
||||||
|
, m_depthImage(VK_NULL_HANDLE)
|
||||||
|
, m_depthImageAllocation(VK_NULL_HANDLE)
|
||||||
|
, m_depthImageView(VK_NULL_HANDLE)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
KRSwapchain::~KRSwapchain()
|
||||||
|
{
|
||||||
|
assert(m_swapChain == VK_NULL_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
KrResult KRSwapchain::create(KRDevice& device, VkSurfaceKHR& surface, VkSurfaceFormatKHR& surfaceFormat, VkFormat depthFormat, VkExtent2D& extent, uint32_t imageCount, const KRRenderPass& renderPass)
|
||||||
|
{
|
||||||
|
KrResult res = KR_SUCCESS;
|
||||||
|
|
||||||
|
m_extent = extent;
|
||||||
|
VkSurfaceCapabilitiesKHR surfaceCapabilities{};
|
||||||
|
if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device.m_device, surface, &surfaceCapabilities) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkPresentModeKHR selectedPresentMode;
|
||||||
|
res = device.selectPresentMode(surface, selectedPresentMode);
|
||||||
|
if (res != KR_SUCCESS) return res;
|
||||||
|
|
||||||
|
m_imageFormat = surfaceFormat.format;
|
||||||
|
m_depthFormat = depthFormat;
|
||||||
|
|
||||||
|
VkSwapchainCreateInfoKHR swapChainCreateInfo{};
|
||||||
|
swapChainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
||||||
|
swapChainCreateInfo.surface = surface;
|
||||||
|
swapChainCreateInfo.minImageCount = imageCount;
|
||||||
|
swapChainCreateInfo.imageFormat = surfaceFormat.format;
|
||||||
|
swapChainCreateInfo.imageColorSpace = surfaceFormat.colorSpace;
|
||||||
|
swapChainCreateInfo.imageExtent = extent;
|
||||||
|
swapChainCreateInfo.imageArrayLayers = 1;
|
||||||
|
swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
|
||||||
|
uint32_t queueFamilyIndices[] = {
|
||||||
|
device.m_graphicsFamilyQueueIndex,
|
||||||
|
device.m_computeFamilyQueueIndex
|
||||||
|
};
|
||||||
|
if (device.m_graphicsFamilyQueueIndex == device.m_computeFamilyQueueIndex) {
|
||||||
|
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
swapChainCreateInfo.queueFamilyIndexCount = 0;
|
||||||
|
swapChainCreateInfo.pQueueFamilyIndices = nullptr;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
swapChainCreateInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||||
|
swapChainCreateInfo.queueFamilyIndexCount = 2;
|
||||||
|
swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
|
||||||
|
}
|
||||||
|
|
||||||
|
swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
|
||||||
|
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
||||||
|
swapChainCreateInfo.presentMode = selectedPresentMode;
|
||||||
|
swapChainCreateInfo.clipped = VK_TRUE;
|
||||||
|
swapChainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
if (vkCreateSwapchainKHR(device.m_logicalDevice, &swapChainCreateInfo, nullptr, &m_swapChain) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkGetSwapchainImagesKHR(device.m_logicalDevice, m_swapChain, &imageCount, nullptr);
|
||||||
|
m_images.resize(imageCount);
|
||||||
|
vkGetSwapchainImagesKHR(device.m_logicalDevice, m_swapChain, &imageCount, m_images.data());
|
||||||
|
|
||||||
|
m_imageViews.resize(m_images.size());
|
||||||
|
for (size_t i = 0; i < m_images.size(); i++) {
|
||||||
|
VkImageViewCreateInfo createInfo{};
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
createInfo.image = m_images[i];
|
||||||
|
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
createInfo.format = m_imageFormat;
|
||||||
|
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.m_logicalDevice, &createInfo, nullptr, &m_imageViews[i]) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_SWAP_CHAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
VkImageCreateInfo imageInfo{};
|
||||||
|
imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
||||||
|
imageInfo.imageType = VK_IMAGE_TYPE_2D;
|
||||||
|
imageInfo.extent.width = m_extent.width;
|
||||||
|
imageInfo.extent.height = m_extent.height;
|
||||||
|
imageInfo.extent.depth = 1;
|
||||||
|
imageInfo.mipLevels = 1;
|
||||||
|
imageInfo.arrayLayers = 1;
|
||||||
|
imageInfo.format = depthFormat;
|
||||||
|
imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||||
|
imageInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
imageInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
|
imageInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
|
imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
|
imageInfo.flags = 0;
|
||||||
|
|
||||||
|
VmaAllocator allocator = device.getAllocator();
|
||||||
|
VmaAllocationCreateInfo allocationCreateInfo{};
|
||||||
|
allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
|
||||||
|
allocationCreateInfo.requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||||
|
|
||||||
|
if (vmaCreateImage(allocator, &imageInfo, &allocationCreateInfo, &m_depthImage, &m_depthImageAllocation, nullptr) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkImageViewCreateInfo viewInfo{};
|
||||||
|
viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
||||||
|
viewInfo.image = m_depthImage;
|
||||||
|
viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
|
viewInfo.format = depthFormat;
|
||||||
|
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
viewInfo.subresourceRange.baseMipLevel = 0;
|
||||||
|
viewInfo.subresourceRange.levelCount = 1;
|
||||||
|
viewInfo.subresourceRange.baseArrayLayer = 0;
|
||||||
|
viewInfo.subresourceRange.layerCount = 1;
|
||||||
|
|
||||||
|
if (vkCreateImageView(device.m_logicalDevice, &viewInfo, nullptr, &m_depthImageView) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_DEPTHBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO - Track memory usage
|
||||||
|
|
||||||
|
VkMemoryRequirements memRequirements;
|
||||||
|
vkGetImageMemoryRequirements(device->m_logicalDevice, m_depthImage, &memRequirements);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
m_framebuffers.resize(m_imageViews.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < m_imageViews.size(); i++) {
|
||||||
|
std::array<VkImageView, 2> attachments = {
|
||||||
|
m_imageViews[i],
|
||||||
|
m_depthImageView
|
||||||
|
};
|
||||||
|
|
||||||
|
VkFramebufferCreateInfo framebufferInfo{};
|
||||||
|
framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
|
||||||
|
framebufferInfo.renderPass = renderPass.m_renderPass;
|
||||||
|
framebufferInfo.attachmentCount = static_cast<uint32_t>(attachments.size());
|
||||||
|
framebufferInfo.pAttachments = attachments.data();
|
||||||
|
framebufferInfo.width = m_extent.width;
|
||||||
|
framebufferInfo.height = m_extent.height;
|
||||||
|
framebufferInfo.layers = 1;
|
||||||
|
|
||||||
|
if (vkCreateFramebuffer(device.m_logicalDevice, &framebufferInfo, nullptr, &m_framebuffers[i]) != VK_SUCCESS) {
|
||||||
|
return KR_ERROR_VULKAN_FRAMEBUFFER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return KR_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRSwapchain::destroy(KRDevice& device)
|
||||||
|
{
|
||||||
|
for (auto framebuffer : m_framebuffers) {
|
||||||
|
vkDestroyFramebuffer(device.m_logicalDevice, framebuffer, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto imageView : m_imageViews) {
|
||||||
|
vkDestroyImageView(device.m_logicalDevice, imageView, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_swapChain != VK_NULL_HANDLE) {
|
||||||
|
vkDestroySwapchainKHR(device.m_logicalDevice, m_swapChain, nullptr);
|
||||||
|
m_swapChain = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthImageView) {
|
||||||
|
vkDestroyImageView(device.m_logicalDevice, m_depthImageView, nullptr);
|
||||||
|
m_depthImageView = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthImage) {
|
||||||
|
vmaDestroyImage(device.getAllocator(), m_depthImage, m_depthImageAllocation);
|
||||||
|
m_depthImage = VK_NULL_HANDLE;
|
||||||
|
m_depthImageAllocation = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_framebuffers.clear();
|
||||||
|
m_imageViews.clear();
|
||||||
|
}
|
||||||
66
kraken/KRSwapchain.h
Normal file
66
kraken/KRSwapchain.h
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// KRSwapchain.h
|
||||||
|
// Kraken Engine
|
||||||
|
//
|
||||||
|
// Copyright 2021 Kearwood Gilbert. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
// permitted provided that the following conditions are met:
|
||||||
|
//
|
||||||
|
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
// conditions and the following disclaimer.
|
||||||
|
//
|
||||||
|
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
// of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
// provided with the distribution.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
|
||||||
|
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
//
|
||||||
|
// The views and conclusions contained in the software and documentation are those of the
|
||||||
|
// authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
// or implied, of Kearwood Gilbert.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef KRSWAPCHAIN_H
|
||||||
|
#define KRSWAPCHAIN_H
|
||||||
|
|
||||||
|
#include "KREngine-common.h"
|
||||||
|
#include "KRContext.h"
|
||||||
|
|
||||||
|
class KRRenderPass;
|
||||||
|
|
||||||
|
class KRSwapchain : public KRContextObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
KRSwapchain(KRContext& context);
|
||||||
|
~KRSwapchain();
|
||||||
|
|
||||||
|
KrResult create(KRDevice& device, VkSurfaceKHR& surface, VkSurfaceFormatKHR& surfaceFormat, VkFormat depthFormat, VkExtent2D& extent, uint32_t imageCount, const KRRenderPass& renderPass);
|
||||||
|
void destroy(KRDevice& device);
|
||||||
|
|
||||||
|
VkSwapchainKHR m_swapChain;
|
||||||
|
VkExtent2D m_extent;
|
||||||
|
VkFormat m_imageFormat;
|
||||||
|
VkFormat m_depthFormat;
|
||||||
|
|
||||||
|
VkImage m_depthImage;
|
||||||
|
VmaAllocation m_depthImageAllocation;
|
||||||
|
VkImageView m_depthImageView;
|
||||||
|
|
||||||
|
std::vector<VkImage> m_images;
|
||||||
|
std::vector<VkImageView> m_imageViews;
|
||||||
|
std::vector<VkFramebuffer> m_framebuffers;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif KRSWAPCHAIN_H
|
||||||
Reference in New Issue
Block a user