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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
|
|
@ -13,6 +16,7 @@
|
|||
#include <fstream>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <fcntl.h>
|
||||
|
|
@ -72,17 +76,18 @@ private:
|
|||
public:
|
||||
VkFormat colorFormat;
|
||||
VkColorSpaceKHR colorSpace;
|
||||
VkImage* swapchainImages;
|
||||
|
||||
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
||||
|
||||
uint32_t imageCount;
|
||||
SwapChainBuffer* buffers;
|
||||
std::vector<VkImage> images;
|
||||
std::vector<SwapChainBuffer> buffers;
|
||||
|
||||
// Index of the deteced graphics and presenting device queue
|
||||
uint32_t queueNodeIndex = UINT32_MAX;
|
||||
|
||||
// wip naming
|
||||
// Creates an os specific surface
|
||||
// Tries to find a graphics and a present queue
|
||||
void initSwapChain(
|
||||
#ifdef _WIN32
|
||||
void* platformHandle, void* platformWindow
|
||||
|
|
@ -95,9 +100,6 @@ public:
|
|||
#endif
|
||||
)
|
||||
{
|
||||
uint32_t queueCount;
|
||||
VkQueueFamilyProperties *queueProps;
|
||||
|
||||
VkResult err;
|
||||
|
||||
// Create surface depending on OS
|
||||
|
|
@ -122,29 +124,28 @@ public:
|
|||
#endif
|
||||
#endif
|
||||
|
||||
uint32_t i;
|
||||
|
||||
// Get queue properties
|
||||
// Get available queue family properties
|
||||
uint32_t queueCount;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
||||
|
||||
queueProps = (VkQueueFamilyProperties *)malloc(queueCount * sizeof(VkQueueFamilyProperties));
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps);
|
||||
assert(queueCount >= 1);
|
||||
|
||||
std::vector<VkQueueFamilyProperties> queueProps(queueCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
||||
|
||||
// Iterate over each queue to learn whether it supports presenting:
|
||||
VkBool32* supportsPresent = (VkBool32 *)malloc(queueCount * sizeof(VkBool32));
|
||||
for (i = 0; i < queueCount; i++)
|
||||
// Find a queue with present support
|
||||
// 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,
|
||||
surface,
|
||||
&supportsPresent[i]);
|
||||
fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &supportsPresent[i]);
|
||||
}
|
||||
|
||||
// Search for a graphics and a present queue in the array of queue
|
||||
// families, try to find one that supports both
|
||||
uint32_t graphicsQueueNodeIndex = 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)
|
||||
{
|
||||
|
|
@ -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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
// todo : error message
|
||||
vkTools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
|
||||
}
|
||||
|
||||
queueNodeIndex = graphicsQueueNodeIndex;
|
||||
|
||||
// Get list of supported formats
|
||||
// Get list of supported surface formats
|
||||
uint32_t formatCount;
|
||||
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
|
||||
assert(!err);
|
||||
assert(formatCount > 0);
|
||||
|
||||
VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
|
||||
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfFormats);
|
||||
std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
|
||||
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfaceFormats.data());
|
||||
assert(!err);
|
||||
|
||||
// If the format list includes just one entry of VK_FORMAT_UNDEFINED,
|
||||
// the surface has no preferred format. Otherwise, at least one
|
||||
// supported format will be returned.
|
||||
if (formatCount == 1 && surfFormats[0].format == VK_FORMAT_UNDEFINED)
|
||||
// If the surface format list only includes one entry with VK_FORMAT_UNDEFINED,
|
||||
// there is no preferered format, so we assume VK_FORMAT_B8G8R8A8_UNORM
|
||||
if ((formatCount == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED))
|
||||
{
|
||||
colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(formatCount >= 1);
|
||||
colorFormat = surfFormats[0].format;
|
||||
// Always select the first available color 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)
|
||||
{
|
||||
this->instance = instance;
|
||||
|
|
@ -229,6 +234,7 @@ public:
|
|||
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)
|
||||
{
|
||||
VkResult err;
|
||||
|
|
@ -239,14 +245,15 @@ public:
|
|||
err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps);
|
||||
assert(!err);
|
||||
|
||||
// Get available present modes
|
||||
uint32_t presentModeCount;
|
||||
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL);
|
||||
assert(!err);
|
||||
assert(presentModeCount > 0);
|
||||
|
||||
// todo : replace with vector?
|
||||
VkPresentModeKHR *presentModes = (VkPresentModeKHR *)malloc(presentModeCount * sizeof(VkPresentModeKHR));
|
||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||
|
||||
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes);
|
||||
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data());
|
||||
assert(!err);
|
||||
|
||||
VkExtent2D swapchainExtent = {};
|
||||
|
|
@ -266,8 +273,7 @@ public:
|
|||
*height = surfCaps.currentExtent.height;
|
||||
}
|
||||
|
||||
// Try to use mailbox mode
|
||||
// Low latency and non-tearing
|
||||
// Prefer mailbox mode if present, it's the lowest latency non-tearing present mode
|
||||
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
for (size_t i = 0; i < presentModeCount; i++)
|
||||
{
|
||||
|
|
@ -294,7 +300,8 @@ public:
|
|||
{
|
||||
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
preTransform = surfCaps.currentTransform;
|
||||
}
|
||||
|
||||
|
|
@ -320,10 +327,8 @@ public:
|
|||
err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
|
||||
assert(!err);
|
||||
|
||||
// If we just re-created an existing swapchain, we should destroy the old
|
||||
// swapchain at this point.
|
||||
// Note: destroying the swapchain also cleans up all its associated
|
||||
// presentable images once the platform is done with them.
|
||||
// If an existing sawp chain is re-created, destroy the old swap chain
|
||||
// This also cleans up all the presentable images
|
||||
if (oldSwapchain != VK_NULL_HANDLE)
|
||||
{
|
||||
fpDestroySwapchainKHR(device, oldSwapchain, nullptr);
|
||||
|
|
@ -332,14 +337,13 @@ public:
|
|||
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL);
|
||||
assert(!err);
|
||||
|
||||
swapchainImages = (VkImage*)malloc(imageCount * sizeof(VkImage));
|
||||
assert(swapchainImages);
|
||||
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, swapchainImages);
|
||||
// Get the swap chain images
|
||||
images.resize(imageCount);
|
||||
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, images.data());
|
||||
assert(!err);
|
||||
|
||||
buffers = (SwapChainBuffer*)malloc(sizeof(SwapChainBuffer)*imageCount);
|
||||
assert(buffers);
|
||||
//buffers.resize(imageCount);
|
||||
// Get the swap chain buffers containing the image and imageview
|
||||
buffers.resize(imageCount);
|
||||
for (uint32_t i = 0; i < imageCount; i++)
|
||||
{
|
||||
VkImageViewCreateInfo colorAttachmentView = {};
|
||||
|
|
@ -360,7 +364,7 @@ public:
|
|||
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
||||
colorAttachmentView.flags = 0;
|
||||
|
||||
buffers[i].image = swapchainImages[i];
|
||||
buffers[i].image = images[i];
|
||||
|
||||
vkTools::setImageLayout(
|
||||
cmdBuffer,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue