Added more comments to the swapchain, some renaming for clarification

This commit is contained in:
Sascha Willems 2016-07-20 16:45:09 +02:00
parent ac7a902c41
commit eedf4d4188
3 changed files with 81 additions and 21 deletions

View file

@ -1756,5 +1756,5 @@ void VulkanExampleBase::initSwapchain()
void VulkanExampleBase::setupSwapChain() void VulkanExampleBase::setupSwapChain()
{ {
swapChain.create(setupCmdBuffer, &width, &height, enableVSync); swapChain.create(&width, &height, enableVSync);
} }

View file

@ -84,7 +84,7 @@ namespace vk
}; };
/** /**
* @brief Encaspulates a complete Vulkan framebuffer with an arbitrary number and combination of attachments * @brief Encapsulates a complete Vulkan framebuffer with an arbitrary number and combination of attachments
*/ */
struct Framebuffer struct Framebuffer
{ {

View file

@ -1,8 +1,7 @@
/* /*
* 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 * A swap chain is a collection of framebuffers used for rendering and presentation to the windowing system
* 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
* *
@ -87,7 +86,21 @@ public:
uint32_t queueNodeIndex = UINT32_MAX; uint32_t queueNodeIndex = UINT32_MAX;
// Creates an os specific surface // Creates an os specific surface
// Tries to find a graphics and a present queue /**
* Create the surface object, an abstraction for the native platform window
*
* @pre Windows
* @param platformHandle HINSTANCE of the window to create the surface for
* @param platformWindow HWND of the window to create the surface for
*
* @pre Android
* @param window A native platform window
*
* @pre Linux (XCB)
* @param connection xcb connection to the X Server
* @param window The xcb window to create the surface for
* @note Targets other than XCB ar not yet supported
*/
void initSurface( void initSurface(
#ifdef _WIN32 #ifdef _WIN32
void* platformHandle, void* platformWindow void* platformHandle, void* platformWindow
@ -102,7 +115,7 @@ public:
{ {
VkResult err; VkResult err;
// Create surface depending on OS // Create the os-specific surface
#ifdef _WIN32 #ifdef _WIN32
VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {}; VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
@ -217,7 +230,14 @@ public:
colorSpace = surfaceFormats[0].colorSpace; colorSpace = surfaceFormats[0].colorSpace;
} }
// Connect to the instance und device and get all required function pointers /**
* Set instance, physical and logical device to use for the swpachain and get all required function pointers
*
* @param instance Vulkan instance to use
* @param physicalDevice Physical device used to query properties and formats relevant to the swapchain
* @param device Logical representation of the device to create the swapchain for
*
*/
void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device) void connect(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device)
{ {
this->instance = instance; this->instance = instance;
@ -234,8 +254,14 @@ public:
GET_DEVICE_PROC_ADDR(device, QueuePresentKHR); GET_DEVICE_PROC_ADDR(device, QueuePresentKHR);
} }
// Create the swap chain and get images with given width and height /**
void create(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height, bool vsync = false) * Create the swapchain and get it's images with given width and height
*
* @param width Pointer to the width of the swapchain (may be adjusted to fit the requirements of the swapchain)
* @param height Pointer to the height of the swapchain (may be adjusted to fit the requirements of the swapchain)
* @param vsync (Optional) Can be used to force vsync'd rendering (by using VK_PRESENT_MODE_FIFO_KHR as presentation mode)
*/
void create(uint32_t *width, uint32_t *height, bool vsync = false)
{ {
VkResult err; VkResult err;
VkSwapchainKHR oldSwapchain = swapChain; VkSwapchainKHR oldSwapchain = swapChain;
@ -280,7 +306,7 @@ public:
// This mode waits for the vertical blank ("v-sync") // This mode waits for the vertical blank ("v-sync")
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
// If v-sync is not requested, try to find a mailbox mode if present // If v-sync is not requested, try to find a mailbox mode
// It's the lowest latency non-tearing present mode available // It's the lowest latency non-tearing present mode available
if (!vsync) if (!vsync)
{ {
@ -305,9 +331,11 @@ public:
desiredNumberOfSwapchainImages = surfCaps.maxImageCount; desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
} }
// Find the transformation of the surface
VkSurfaceTransformFlagsKHR preTransform; VkSurfaceTransformFlagsKHR preTransform;
if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
{ {
// We prefer a non-rotated transform
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
} }
else else
@ -331,7 +359,8 @@ public:
swapchainCI.pQueueFamilyIndices = NULL; swapchainCI.pQueueFamilyIndices = NULL;
swapchainCI.presentMode = swapchainPresentMode; swapchainCI.presentMode = swapchainPresentMode;
swapchainCI.oldSwapchain = oldSwapchain; swapchainCI.oldSwapchain = oldSwapchain;
swapchainCI.clipped = true; // Setting clipped to VK_TRUE allows the implementation to discard rendering outside of the surface area
swapchainCI.clipped = VK_TRUE;
swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain); err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
@ -387,33 +416,62 @@ public:
} }
} }
// Acquires the next image in the swap chain /**
VkResult acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t *currentBuffer) * Acquires the next image in the swap chain
*
* @param presentCompleteSemaphore (Optional) Semaphore that is signaled when the image is ready for use
* @param imageIndex Pointer to the image index that will be increased if the next image could be acquired
*
* @note The function will always wait until the next image has been acquired by setting timeout to UINT64_MAX
*
* @return VkResult of the image acquisition
*/
VkResult acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t *imageIndex)
{ {
return fpAcquireNextImageKHR(device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence)nullptr, currentBuffer); // By setting timeout to UINT64_MAX we will always wait until the next image has been acquired or an actual error is thrown
// With that we don't have to handle VK_NOT_READY
return fpAcquireNextImageKHR(device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence)nullptr, imageIndex);
} }
// Present the current image to the queue /**
VkResult queuePresent(VkQueue queue, uint32_t currentBuffer) * Queue an image for presentation
*
* @param queue Presentation queue for presenting the image
* @param imageIndex Index of the swapchain image to queue for presentation
*
* @note Does not wait on a semaphore
*
* @return VkResult of the queue presentation
*/
VkResult queuePresent(VkQueue queue, uint32_t imageIndex)
{ {
VkPresentInfoKHR presentInfo = {}; VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pNext = NULL; presentInfo.pNext = NULL;
presentInfo.swapchainCount = 1; presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapChain; presentInfo.pSwapchains = &swapChain;
presentInfo.pImageIndices = &currentBuffer; presentInfo.pImageIndices = &imageIndex;
return fpQueuePresentKHR(queue, &presentInfo); return fpQueuePresentKHR(queue, &presentInfo);
} }
// Present the current image to the queue /**
VkResult queuePresent(VkQueue queue, uint32_t currentBuffer, VkSemaphore waitSemaphore) * Queue an image for presentation
*
* @param queue Presentation queue for presenting the image
* @param imageIndex Index of the swapchain image to queue for presentation
* @param waitSemaphore (Optional) Semaphore that is waited on before the image is presented (only used if != VK_NULL_HANDLE)
*
* @return VkResult of the queue presentation
*/
VkResult queuePresent(VkQueue queue, uint32_t imageIndex, VkSemaphore waitSemaphore)
{ {
VkPresentInfoKHR presentInfo = {}; VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.pNext = NULL; presentInfo.pNext = NULL;
presentInfo.swapchainCount = 1; presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &swapChain; presentInfo.pSwapchains = &swapChain;
presentInfo.pImageIndices = &currentBuffer; presentInfo.pImageIndices = &imageIndex;
// Check if a wait semaphore has been specified to wait for before presenting the image
if (waitSemaphore != VK_NULL_HANDLE) if (waitSemaphore != VK_NULL_HANDLE)
{ {
presentInfo.pWaitSemaphores = &waitSemaphore; presentInfo.pWaitSemaphores = &waitSemaphore;
@ -423,7 +481,9 @@ public:
} }
// Free all Vulkan resources used by the swap chain /**
* Destroy and free Vulkan resources used for the swapchain
*/
void cleanup() void cleanup()
{ {
for (uint32_t i = 0; i < imageCount; i++) for (uint32_t i = 0; i < imageCount; i++)