initial
This commit is contained in:
+213
@@ -0,0 +1,213 @@
|
||||
#include "Swapchain.hpp"
|
||||
#include "Instance.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <print>
|
||||
|
||||
VkSurfaceFormatKHR Swapchain::choose_format() {
|
||||
uint32_t formatCount = 0;
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_gpu->gpu(), m_surface, &formatCount, nullptr);
|
||||
assert(formatCount > 0);
|
||||
|
||||
auto formats = std::vector<VkSurfaceFormatKHR>(formatCount);
|
||||
vkGetPhysicalDeviceSurfaceFormatsKHR(m_gpu->gpu(), m_surface, &formatCount, formats.data());
|
||||
|
||||
for(uint32_t i = 0; i < formatCount; i++) {
|
||||
if(formats[i].format == VK_FORMAT_B8G8R8A8_UNORM &&
|
||||
formats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
|
||||
return formats[i];
|
||||
}
|
||||
}
|
||||
|
||||
auto result = formats[0];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VkPresentModeKHR Swapchain::choose_present_mode() {
|
||||
uint32_t presentModeCount = 0;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(m_gpu->gpu(), m_surface,
|
||||
&presentModeCount, nullptr);
|
||||
|
||||
VkPresentModeKHR presentModeResult = VK_PRESENT_MODE_FIFO_KHR;
|
||||
|
||||
auto presentModes = new VkPresentModeKHR[presentModeCount];
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(m_gpu->gpu(), m_surface,
|
||||
&presentModeCount, presentModes);
|
||||
|
||||
for(uint32_t i = 0; i < presentModeCount; i++) {
|
||||
if(presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
|
||||
presentModeResult = presentModes[i];
|
||||
}
|
||||
}
|
||||
|
||||
delete [] presentModes;
|
||||
|
||||
return presentModeResult;
|
||||
}
|
||||
|
||||
VkExtent2D Swapchain::choose_extent(VkExtent2D actualExtent) {
|
||||
VkSurfaceCapabilitiesKHR capabilities = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpu->gpu(), m_surface, &capabilities);
|
||||
|
||||
VkExtent2D result = {};
|
||||
|
||||
if(capabilities.currentExtent.width != UINT32_MAX) {
|
||||
result = capabilities.currentExtent;
|
||||
} else {
|
||||
result.width = std::max(
|
||||
capabilities.minImageExtent.width,
|
||||
std::min(capabilities.maxImageExtent.width, actualExtent.width)
|
||||
);
|
||||
|
||||
result.height = std::max(
|
||||
capabilities.minImageExtent.height,
|
||||
std::min(capabilities.maxImageExtent.height, actualExtent.height)
|
||||
);
|
||||
}
|
||||
|
||||
assert(result.width > 0 && result.height > 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ResultCode Swapchain::get_images(uint32_t *pOutNumImages, VkImage *pOutImages) {
|
||||
/* Get images to render to, rendertargets */
|
||||
EXPECT(vkGetSwapchainImagesKHR(m_gpu->dev(), m_swapchain, pOutNumImages, pOutImages) == VK_SUCCESS,
|
||||
"Failed to get swapchain images");
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
ResultCode Swapchain::create_views() {
|
||||
m_pImageViews = (VkImageView*)malloc(sizeof(VkImageView) * m_numImages);
|
||||
assert(m_pImageViews);
|
||||
|
||||
for(unsigned i = 0; i < m_numImages; i++) {
|
||||
VkImageViewCreateInfo viewInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
||||
.image = m_pImages[i],
|
||||
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
||||
.format = m_format.format,
|
||||
.components = {
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY,
|
||||
VK_COMPONENT_SWIZZLE_IDENTITY
|
||||
},
|
||||
.subresourceRange = {
|
||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||
.baseMipLevel = 0,
|
||||
.levelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
}
|
||||
};
|
||||
|
||||
EXPECT(vkCreateImageView(m_gpu->dev(), &viewInfo, NULL, &m_pImageViews[i]) == VK_SUCCESS,
|
||||
"Failed to create image view");
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
ResultCode Swapchain::create_swapchain() {
|
||||
VkSurfaceCapabilitiesKHR capabilities = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpu->gpu(), m_surface, &capabilities);
|
||||
|
||||
VkSwapchainCreateInfoKHR swapchainInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
|
||||
.surface = m_surface,
|
||||
.minImageCount = m_numImages,
|
||||
.imageFormat = m_format.format,
|
||||
.imageColorSpace = m_format.colorSpace,
|
||||
.imageExtent = m_extent,
|
||||
.imageArrayLayers = 1,
|
||||
.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
.preTransform = capabilities.currentTransform,
|
||||
.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
|
||||
.presentMode = choose_present_mode(),
|
||||
.clipped = VK_TRUE
|
||||
};
|
||||
|
||||
/* Allow sharing across graphics and present queue when those two are not
|
||||
* the same. Meaning we can draw with commands submitted to graphics queue
|
||||
* to swapchain images, that need to be used by command submitted to
|
||||
* present queue. */
|
||||
auto presentQueues = m_gpu->present_queue_ids();
|
||||
if(presentQueues.size() > 1) {
|
||||
swapchainInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
|
||||
swapchainInfo.queueFamilyIndexCount = presentQueues.size();
|
||||
swapchainInfo.pQueueFamilyIndices = presentQueues.data();
|
||||
} else {
|
||||
/* Don't need to share the images */
|
||||
swapchainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||
}
|
||||
|
||||
EXPECT(vkCreateSwapchainKHR(m_gpu->dev(), &swapchainInfo, NULL, &m_swapchain) == VK_SUCCESS, "Failed to create swapchain");
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void Swapchain::cleanup() {
|
||||
for(int i = 0; i < m_numImages; i++) {
|
||||
vkDestroyImageView(m_gpu->dev(), m_pImageViews[i], nullptr);
|
||||
}
|
||||
|
||||
vkDestroySwapchainKHR(m_gpu->dev(), m_swapchain, nullptr);
|
||||
}
|
||||
|
||||
void Swapchain::resize(VkExtent2D extent) {
|
||||
cleanup();
|
||||
|
||||
m_extent = extent;
|
||||
|
||||
create_swapchain();
|
||||
|
||||
get_images(&m_numImages, NULL);
|
||||
m_pImages = new VkImage[m_numImages];
|
||||
get_images(&m_numImages, m_pImages);
|
||||
|
||||
create_views();
|
||||
|
||||
m_images.resize(m_numImages);
|
||||
m_views.resize(m_numImages);
|
||||
for(int i = 0; i < m_numImages; i++) {
|
||||
m_images[i].img = m_pImages[i];
|
||||
std::println("View: {:#06x}", (unsigned long)m_pImageViews[i]);
|
||||
m_views[i].view = m_pImageViews[i];
|
||||
}
|
||||
}
|
||||
|
||||
Swapchain::Swapchain(const Gpu* gpu, VkExtent2D extent, Surface* surface) :
|
||||
m_gpu(gpu),
|
||||
m_surface(surface->surface())
|
||||
{
|
||||
VkSurfaceCapabilitiesKHR capabilities = {};
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_gpu->gpu(), m_surface, &capabilities);
|
||||
|
||||
m_format = choose_format();
|
||||
m_extent = choose_extent(extent);
|
||||
|
||||
uint32_t imageCount = capabilities.minImageCount + 1;
|
||||
m_numImages = imageCount;
|
||||
|
||||
if(capabilities.maxImageCount > 0 &&
|
||||
imageCount < capabilities.maxImageCount) {
|
||||
m_numImages = capabilities.maxImageCount;
|
||||
}
|
||||
m_numFrames = m_numImages;
|
||||
|
||||
create_swapchain();
|
||||
|
||||
get_images(&m_numImages, NULL);
|
||||
m_pImages = new VkImage[m_numImages];
|
||||
get_images(&m_numImages, m_pImages);
|
||||
|
||||
create_views();
|
||||
|
||||
m_images.resize(m_numImages);
|
||||
m_views.resize(m_numImages);
|
||||
for(int i = 0; i < m_numImages; i++) {
|
||||
m_images[i].img = m_pImages[i];
|
||||
m_views[i].view = m_pImageViews[i];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user