Replaced pointers with std::vectors, added a few comments, some code refactoring, Fixes #39
This commit is contained in:
parent
5979e31c56
commit
fb41887c9d
1 changed files with 53 additions and 49 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* Class wrapping access to the swap chain
|
* Class wrapping access to the swap chain
|
||||||
|
*
|
||||||
|
* A swap chain is a collection of framebuffers used for rendering
|
||||||
|
* The swap chain images can then presented to the windowing system
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
||||||
*
|
*
|
||||||
|
|
@ -13,6 +16,7 @@
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <vector>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
@ -72,17 +76,18 @@ private:
|
||||||
public:
|
public:
|
||||||
VkFormat colorFormat;
|
VkFormat colorFormat;
|
||||||
VkColorSpaceKHR colorSpace;
|
VkColorSpaceKHR colorSpace;
|
||||||
VkImage* swapchainImages;
|
|
||||||
|
|
||||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||||
|
|
||||||
uint32_t imageCount;
|
uint32_t imageCount;
|
||||||
SwapChainBuffer* buffers;
|
std::vector<VkImage> images;
|
||||||
|
std::vector<SwapChainBuffer> buffers;
|
||||||
|
|
||||||
// Index of the deteced graphics and presenting device queue
|
// Index of the deteced graphics and presenting device queue
|
||||||
uint32_t queueNodeIndex = UINT32_MAX;
|
uint32_t queueNodeIndex = UINT32_MAX;
|
||||||
|
|
||||||
// wip naming
|
// Creates an os specific surface
|
||||||
|
// Tries to find a graphics and a present queue
|
||||||
void initSwapChain(
|
void initSwapChain(
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
void* platformHandle, void* platformWindow
|
void* platformHandle, void* platformWindow
|
||||||
|
|
@ -95,9 +100,6 @@ public:
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
uint32_t queueCount;
|
|
||||||
VkQueueFamilyProperties *queueProps;
|
|
||||||
|
|
||||||
VkResult err;
|
VkResult err;
|
||||||
|
|
||||||
// Create surface depending on OS
|
// Create surface depending on OS
|
||||||
|
|
@ -122,29 +124,28 @@ public:
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t i;
|
// Get available queue family properties
|
||||||
|
uint32_t queueCount;
|
||||||
// Get queue properties
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
||||||
|
|
||||||
queueProps = (VkQueueFamilyProperties *)malloc(queueCount * sizeof(VkQueueFamilyProperties));
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps);
|
|
||||||
assert(queueCount >= 1);
|
assert(queueCount >= 1);
|
||||||
|
|
||||||
|
std::vector<VkQueueFamilyProperties> queueProps(queueCount);
|
||||||
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
||||||
|
|
||||||
// Iterate over each queue to learn whether it supports presenting:
|
// Iterate over each queue to learn whether it supports presenting:
|
||||||
VkBool32* supportsPresent = (VkBool32 *)malloc(queueCount * sizeof(VkBool32));
|
// Find a queue with present support
|
||||||
for (i = 0; i < queueCount; i++)
|
// Will be used to present the swap chain images to the windowing system
|
||||||
|
std::vector<VkBool32> supportsPresent(queueCount);
|
||||||
|
for (uint32_t i = 0; i < queueCount; i++)
|
||||||
{
|
{
|
||||||
fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i,
|
fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &supportsPresent[i]);
|
||||||
surface,
|
|
||||||
&supportsPresent[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for a graphics and a present queue in the array of queue
|
// Search for a graphics and a present queue in the array of queue
|
||||||
// families, try to find one that supports both
|
// families, try to find one that supports both
|
||||||
uint32_t graphicsQueueNodeIndex = UINT32_MAX;
|
uint32_t graphicsQueueNodeIndex = UINT32_MAX;
|
||||||
uint32_t presentQueueNodeIndex = UINT32_MAX;
|
uint32_t presentQueueNodeIndex = UINT32_MAX;
|
||||||
for (i = 0; i < queueCount; i++)
|
for (uint32_t i = 0; i < queueCount; i++)
|
||||||
{
|
{
|
||||||
if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
|
if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
|
||||||
{
|
{
|
||||||
|
|
@ -174,45 +175,49 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(supportsPresent);
|
|
||||||
|
|
||||||
// Generate error if could not find both a graphics and a present queue
|
// Exit if either a graphics or a presenting queue hasn't been found
|
||||||
if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
|
if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
|
||||||
{
|
{
|
||||||
// todo : error message
|
vkTools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo : Add support for separate graphics and presenting queue
|
||||||
if (graphicsQueueNodeIndex != presentQueueNodeIndex)
|
if (graphicsQueueNodeIndex != presentQueueNodeIndex)
|
||||||
{
|
{
|
||||||
// todo : error message
|
vkTools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
|
||||||
}
|
}
|
||||||
|
|
||||||
queueNodeIndex = graphicsQueueNodeIndex;
|
queueNodeIndex = graphicsQueueNodeIndex;
|
||||||
|
|
||||||
// Get list of supported formats
|
// Get list of supported surface formats
|
||||||
uint32_t formatCount;
|
uint32_t formatCount;
|
||||||
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
|
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
assert(formatCount > 0);
|
||||||
|
|
||||||
VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
|
std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
|
||||||
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfFormats);
|
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfaceFormats.data());
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
// If the format list includes just one entry of VK_FORMAT_UNDEFINED,
|
// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
|
||||||
// the surface has no preferred format. Otherwise, at least one
|
// there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
|
||||||
// supported format will be returned.
|
if ((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
|
||||||
if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
|
|
||||||
{
|
{
|
||||||
colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
assert(formatCount >= 1);
|
// Always select the first available color format
|
||||||
colorFormat = surfFormats[0].format;
|
// If you need a specific format (e.g. SRGB) you'd need to
|
||||||
|
// iterate over the list of available surface format and
|
||||||
|
// check for it's presence
|
||||||
|
colorFormat = surfaceFormats[0].format;
|
||||||
}
|
}
|
||||||
colorSpace = surfFormats[0].colorSpace;
|
colorSpace = surfaceFormats[0].colorSpace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assign instance und device handles and get all required function pointers
|
||||||
void init(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device)
|
void init(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device)
|
||||||
{
|
{
|
||||||
this->instance = instance;
|
this->instance = instance;
|
||||||
|
|
@ -229,6 +234,7 @@ public:
|
||||||
GET_DEVICE_PROC_ADDR(device, QueuePresentKHR);
|
GET_DEVICE_PROC_ADDR(device, QueuePresentKHR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the swap chain images with given width and height
|
||||||
void setup(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height)
|
void setup(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height)
|
||||||
{
|
{
|
||||||
VkResult err;
|
VkResult err;
|
||||||
|
|
@ -239,14 +245,15 @@ public:
|
||||||
err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps);
|
err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
|
// Get available present modes
|
||||||
uint32_t presentModeCount;
|
uint32_t presentModeCount;
|
||||||
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL);
|
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
assert(presentModeCount > 0);
|
||||||
|
|
||||||
// todo : replace with vector?
|
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||||
VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
|
|
||||||
|
|
||||||
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes);
|
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data());
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
VkExtent2D swapchainExtent = {};
|
VkExtent2D swapchainExtent = {};
|
||||||
|
|
@ -266,8 +273,7 @@ public:
|
||||||
*height = surfCaps.currentExtent.height;
|
*height = surfCaps.currentExtent.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to use mailbox mode
|
// Prefer mailbox mode if present, it's the lowest latency non-tearing present mode
|
||||||
// Low latency and non-tearing
|
|
||||||
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
for (size_t i = 0; i < presentModeCount; i++)
|
for (size_t i = 0; i < presentModeCount; i++)
|
||||||
{
|
{
|
||||||
|
|
@ -294,7 +300,8 @@ public:
|
||||||
{
|
{
|
||||||
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
preTransform = surfCaps.currentTransform;
|
preTransform = surfCaps.currentTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -320,10 +327,8 @@ public:
|
||||||
err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
|
err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
// If we just re-created an existing swapchain, we should destroy the old
|
// If an existing sawp chain is re-created, destroy the old swap chain
|
||||||
// swapchain at this point.
|
// This also cleans up all the presentable images
|
||||||
// Note: destroying the swapchain also cleans up all its associated
|
|
||||||
// presentable images once the platform is done with them.
|
|
||||||
if (oldSwapchain != VK_NULL_HANDLE)
|
if (oldSwapchain != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
fpDestroySwapchainKHR(device, oldSwapchain, nullptr);
|
fpDestroySwapchainKHR(device, oldSwapchain, nullptr);
|
||||||
|
|
@ -332,14 +337,13 @@ public:
|
||||||
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL);
|
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL);
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
swapchainImages = (VkImage*)malloc(imageCount * sizeof(VkImage));
|
// Get the swap chain images
|
||||||
assert(swapchainImages);
|
images.resize(imageCount);
|
||||||
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, swapchainImages);
|
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, images.data());
|
||||||
assert(!err);
|
assert(!err);
|
||||||
|
|
||||||
buffers = (SwapChainBuffer*)malloc(sizeof(SwapChainBuffer)*imageCount);
|
// Get the swap chain buffers containing the image and imageview
|
||||||
assert(buffers);
|
buffers.resize(imageCount);
|
||||||
//buffers.resize(imageCount);
|
|
||||||
for (uint32_t i = 0; i < imageCount; i++)
|
for (uint32_t i = 0; i < imageCount; i++)
|
||||||
{
|
{
|
||||||
VkImageViewCreateInfo colorAttachmentView = {};
|
VkImageViewCreateInfo colorAttachmentView = {};
|
||||||
|
|
@ -360,7 +364,7 @@ public:
|
||||||
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||||
colorAttachmentView.flags = 0;
|
colorAttachmentView.flags = 0;
|
||||||
|
|
||||||
buffers[i].image = swapchainImages[i];
|
buffers[i].image = images[i];
|
||||||
|
|
||||||
vkTools::setImageLayout(
|
vkTools::setImageLayout(
|
||||||
cmdBuffer,
|
cmdBuffer,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue