2016-02-16 15:07:25 +01:00
|
|
|
/*
|
|
|
|
|
* Class wrapping access to the swap chain
|
2016-02-23 21:21:36 +01:00
|
|
|
*
|
|
|
|
|
* A swap chain is a collection of framebuffers used for rendering
|
|
|
|
|
* The swap chain images can then presented to the windowing system
|
2016-02-16 15:07:25 +01:00
|
|
|
*
|
2016-02-23 13:21:34 +01:00
|
|
|
* Copyright (C) 2016 by Sascha Willems - www.saschawillems.de
|
2016-02-16 15:07:25 +01:00
|
|
|
*
|
|
|
|
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string>
|
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
#include <stdio.h>
|
2016-02-23 21:21:36 +01:00
|
|
|
#include <vector>
|
2016-02-16 15:07:25 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
|
#include <windows.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <io.h>
|
|
|
|
|
#else
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <vulkan/vulkan.h>
|
|
|
|
|
#include "vulkantools.h"
|
|
|
|
|
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
|
#include "vulkanandroid.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// Macro to get a procedure address based on a vulkan instance
|
|
|
|
|
#define GET_INSTANCE_PROC_ADDR(inst, entrypoint) \
|
|
|
|
|
{ \
|
|
|
|
|
fp##entrypoint = (PFN_vk##entrypoint) vkGetInstanceProcAddr(inst, "vk"#entrypoint); \
|
|
|
|
|
if (fp##entrypoint == NULL) \
|
|
|
|
|
{ \
|
|
|
|
|
exit(1); \
|
|
|
|
|
} \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Macro to get a procedure address based on a vulkan device
|
|
|
|
|
#define GET_DEVICE_PROC_ADDR(dev, entrypoint) \
|
|
|
|
|
{ \
|
|
|
|
|
fp##entrypoint = (PFN_vk##entrypoint) vkGetDeviceProcAddr(dev, "vk"#entrypoint); \
|
|
|
|
|
if (fp##entrypoint == NULL) \
|
|
|
|
|
{ \
|
|
|
|
|
exit(1); \
|
|
|
|
|
} \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef struct _SwapChainBuffers {
|
|
|
|
|
VkImage image;
|
|
|
|
|
VkImageView view;
|
|
|
|
|
} SwapChainBuffer;
|
|
|
|
|
|
|
|
|
|
class VulkanSwapChain
|
|
|
|
|
{
|
|
|
|
|
private:
|
|
|
|
|
VkInstance instance;
|
|
|
|
|
VkDevice device;
|
|
|
|
|
VkPhysicalDevice physicalDevice;
|
|
|
|
|
VkSurfaceKHR surface;
|
|
|
|
|
// Function pointers
|
|
|
|
|
PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR;
|
|
|
|
|
PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR;
|
|
|
|
|
PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR;
|
|
|
|
|
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR;
|
|
|
|
|
PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR;
|
|
|
|
|
PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR;
|
|
|
|
|
PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR;
|
|
|
|
|
PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR;
|
|
|
|
|
PFN_vkQueuePresentKHR fpQueuePresentKHR;
|
|
|
|
|
public:
|
|
|
|
|
VkFormat colorFormat;
|
|
|
|
|
VkColorSpaceKHR colorSpace;
|
|
|
|
|
|
|
|
|
|
VkSwapchainKHR swapChain = VK_NULL_HANDLE;
|
|
|
|
|
|
|
|
|
|
uint32_t imageCount;
|
2016-02-23 21:21:36 +01:00
|
|
|
std::vector<VkImage> images;
|
|
|
|
|
std::vector<SwapChainBuffer> buffers;
|
2016-02-16 15:07:25 +01:00
|
|
|
|
|
|
|
|
// Index of the deteced graphics and presenting device queue
|
|
|
|
|
uint32_t queueNodeIndex = UINT32_MAX;
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Creates an os specific surface
|
|
|
|
|
// Tries to find a graphics and a present queue
|
2016-02-16 15:07:25 +01:00
|
|
|
void initSwapChain(
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
void* platformHandle, void* platformWindow
|
|
|
|
|
#else
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
|
ANativeWindow* window
|
|
|
|
|
#else
|
|
|
|
|
xcb_connection_t* connection, xcb_window_t window
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
)
|
|
|
|
|
{
|
|
|
|
|
VkResult err;
|
|
|
|
|
|
|
|
|
|
// Create surface depending on OS
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
|
VkWin32SurfaceCreateInfoKHR surfaceCreateInfo = {};
|
|
|
|
|
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
|
|
|
|
|
surfaceCreateInfo.hinstance = (HINSTANCE)platformHandle;
|
|
|
|
|
surfaceCreateInfo.hwnd = (HWND)platformWindow;
|
|
|
|
|
err = vkCreateWin32SurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
|
|
|
|
|
#else
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
|
VkAndroidSurfaceCreateInfoKHR surfaceCreateInfo = {};
|
|
|
|
|
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
|
|
|
|
|
surfaceCreateInfo.window = window;
|
|
|
|
|
err = vkCreateAndroidSurfaceKHR(instance, &surfaceCreateInfo, NULL, &surface);
|
|
|
|
|
#else
|
|
|
|
|
VkXcbSurfaceCreateInfoKHR surfaceCreateInfo = {};
|
|
|
|
|
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
|
|
|
|
|
surfaceCreateInfo.connection = connection;
|
|
|
|
|
surfaceCreateInfo.window = window;
|
|
|
|
|
err = vkCreateXcbSurfaceKHR(instance, &surfaceCreateInfo, nullptr, &surface);
|
|
|
|
|
#endif
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Get available queue family properties
|
|
|
|
|
uint32_t queueCount;
|
2016-02-16 15:07:25 +01:00
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
|
|
|
|
assert(queueCount >= 1);
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
std::vector<VkQueueFamilyProperties> queueProps(queueCount);
|
|
|
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
|
|
|
|
|
2016-02-16 15:07:25 +01:00
|
|
|
// Iterate over each queue to learn whether it supports presenting:
|
2016-02-23 21:21:36 +01:00
|
|
|
// 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++)
|
2016-02-16 15:07:25 +01:00
|
|
|
{
|
2016-02-23 21:21:36 +01:00
|
|
|
fpGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, i, surface, &supportsPresent[i]);
|
2016-02-16 15:07:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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;
|
2016-02-23 21:21:36 +01:00
|
|
|
for (uint32_t i = 0; i < queueCount; i++)
|
2016-02-16 15:07:25 +01:00
|
|
|
{
|
|
|
|
|
if ((queueProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0)
|
|
|
|
|
{
|
|
|
|
|
if (graphicsQueueNodeIndex == UINT32_MAX)
|
|
|
|
|
{
|
|
|
|
|
graphicsQueueNodeIndex = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (supportsPresent[i] == VK_TRUE)
|
|
|
|
|
{
|
|
|
|
|
graphicsQueueNodeIndex = i;
|
|
|
|
|
presentQueueNodeIndex = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (presentQueueNodeIndex == UINT32_MAX)
|
|
|
|
|
{
|
|
|
|
|
// If there's no queue that supports both present and graphics
|
|
|
|
|
// try to find a separate present queue
|
|
|
|
|
for (uint32_t i = 0; i < queueCount; ++i)
|
|
|
|
|
{
|
|
|
|
|
if (supportsPresent[i] == VK_TRUE)
|
|
|
|
|
{
|
|
|
|
|
presentQueueNodeIndex = i;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Exit if either a graphics or a presenting queue hasn't been found
|
2016-02-16 15:07:25 +01:00
|
|
|
if (graphicsQueueNodeIndex == UINT32_MAX || presentQueueNodeIndex == UINT32_MAX)
|
|
|
|
|
{
|
2016-02-23 21:21:36 +01:00
|
|
|
vkTools::exitFatal("Could not find a graphics and/or presenting queue!", "Fatal error");
|
2016-02-16 15:07:25 +01:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// todo : Add support for separate graphics and presenting queue
|
2016-02-16 15:07:25 +01:00
|
|
|
if (graphicsQueueNodeIndex != presentQueueNodeIndex)
|
|
|
|
|
{
|
2016-02-23 21:21:36 +01:00
|
|
|
vkTools::exitFatal("Separate graphics and presenting queues are not supported yet!", "Fatal error");
|
2016-02-16 15:07:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queueNodeIndex = graphicsQueueNodeIndex;
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Get list of supported surface formats
|
2016-02-16 15:07:25 +01:00
|
|
|
uint32_t formatCount;
|
|
|
|
|
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL);
|
|
|
|
|
assert(!err);
|
2016-02-23 21:21:36 +01:00
|
|
|
assert(formatCount > 0);
|
2016-02-16 15:07:25 +01:00
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount);
|
|
|
|
|
err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfaceFormats.data());
|
2016-02-16 15:07:25 +01:00
|
|
|
assert(!err);
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// 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))
|
2016-02-16 15:07:25 +01:00
|
|
|
{
|
|
|
|
|
colorFormat = VK_FORMAT_B8G8R8A8_UNORM;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2016-02-23 21:21:36 +01:00
|
|
|
// 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;
|
2016-02-16 15:07:25 +01:00
|
|
|
}
|
2016-02-23 21:21:36 +01:00
|
|
|
colorSpace = surfaceFormats[0].colorSpace;
|
2016-02-16 15:07:25 +01:00
|
|
|
}
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Assign instance und device handles and get all required function pointers
|
2016-02-16 15:07:25 +01:00
|
|
|
void init(VkInstance instance, VkPhysicalDevice physicalDevice, VkDevice device)
|
|
|
|
|
{
|
|
|
|
|
this->instance = instance;
|
|
|
|
|
this->physicalDevice = physicalDevice;
|
|
|
|
|
this->device = device;
|
|
|
|
|
GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfaceSupportKHR);
|
|
|
|
|
GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfaceCapabilitiesKHR);
|
|
|
|
|
GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfaceFormatsKHR);
|
|
|
|
|
GET_INSTANCE_PROC_ADDR(instance, GetPhysicalDeviceSurfacePresentModesKHR);
|
|
|
|
|
GET_DEVICE_PROC_ADDR(device, CreateSwapchainKHR);
|
|
|
|
|
GET_DEVICE_PROC_ADDR(device, DestroySwapchainKHR);
|
|
|
|
|
GET_DEVICE_PROC_ADDR(device, GetSwapchainImagesKHR);
|
|
|
|
|
GET_DEVICE_PROC_ADDR(device, AcquireNextImageKHR);
|
|
|
|
|
GET_DEVICE_PROC_ADDR(device, QueuePresentKHR);
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Create the swap chain images with given width and height
|
2016-02-16 15:07:25 +01:00
|
|
|
void setup(VkCommandBuffer cmdBuffer, uint32_t *width, uint32_t *height)
|
|
|
|
|
{
|
|
|
|
|
VkResult err;
|
|
|
|
|
VkSwapchainKHR oldSwapchain = swapChain;
|
|
|
|
|
|
|
|
|
|
// Get physical device surface properties and formats
|
|
|
|
|
VkSurfaceCapabilitiesKHR surfCaps;
|
|
|
|
|
err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps);
|
|
|
|
|
assert(!err);
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Get available present modes
|
2016-02-16 15:07:25 +01:00
|
|
|
uint32_t presentModeCount;
|
|
|
|
|
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, NULL);
|
|
|
|
|
assert(!err);
|
2016-02-23 21:21:36 +01:00
|
|
|
assert(presentModeCount > 0);
|
2016-02-16 15:07:25 +01:00
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
2016-02-16 15:07:25 +01:00
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
err = fpGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, surface, &presentModeCount, presentModes.data());
|
2016-02-16 15:07:25 +01:00
|
|
|
assert(!err);
|
|
|
|
|
|
|
|
|
|
VkExtent2D swapchainExtent = {};
|
|
|
|
|
// width and height are either both -1, or both not -1.
|
|
|
|
|
if (surfCaps.currentExtent.width == -1)
|
|
|
|
|
{
|
|
|
|
|
// If the surface size is undefined, the size is set to
|
|
|
|
|
// the size of the images requested.
|
|
|
|
|
swapchainExtent.width = *width;
|
|
|
|
|
swapchainExtent.height = *height;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// If the surface size is defined, the swap chain size must match
|
|
|
|
|
swapchainExtent = surfCaps.currentExtent;
|
|
|
|
|
*width = surfCaps.currentExtent.width;
|
|
|
|
|
*height = surfCaps.currentExtent.height;
|
|
|
|
|
}
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Prefer mailbox mode if present, it's the lowest latency non-tearing present mode
|
2016-02-16 15:07:25 +01:00
|
|
|
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
|
|
|
|
for (size_t i = 0; i < presentModeCount; i++)
|
|
|
|
|
{
|
|
|
|
|
if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR)
|
|
|
|
|
{
|
|
|
|
|
swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) && (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR))
|
|
|
|
|
{
|
|
|
|
|
swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine the number of images
|
|
|
|
|
uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1;
|
|
|
|
|
if ((surfCaps.maxImageCount > 0) && (desiredNumberOfSwapchainImages > surfCaps.maxImageCount))
|
|
|
|
|
{
|
|
|
|
|
desiredNumberOfSwapchainImages = surfCaps.maxImageCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkSurfaceTransformFlagsKHR preTransform;
|
|
|
|
|
if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
|
|
|
|
|
{
|
|
|
|
|
preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
|
|
|
|
|
}
|
2016-02-23 21:21:36 +01:00
|
|
|
else
|
|
|
|
|
{
|
2016-02-16 15:07:25 +01:00
|
|
|
preTransform = surfCaps.currentTransform;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
VkSwapchainCreateInfoKHR swapchainCI = {};
|
|
|
|
|
swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
|
|
|
|
|
swapchainCI.pNext = NULL;
|
|
|
|
|
swapchainCI.surface = surface;
|
|
|
|
|
swapchainCI.minImageCount = desiredNumberOfSwapchainImages;
|
|
|
|
|
swapchainCI.imageFormat = colorFormat;
|
|
|
|
|
swapchainCI.imageColorSpace = colorSpace;
|
|
|
|
|
swapchainCI.imageExtent = { swapchainExtent.width, swapchainExtent.height };
|
|
|
|
|
swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
|
|
|
|
swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)preTransform;
|
|
|
|
|
swapchainCI.imageArrayLayers = 1;
|
2016-02-23 13:21:34 +01:00
|
|
|
swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
2016-02-16 15:07:25 +01:00
|
|
|
swapchainCI.queueFamilyIndexCount = 0;
|
|
|
|
|
swapchainCI.pQueueFamilyIndices = NULL;
|
|
|
|
|
swapchainCI.presentMode = swapchainPresentMode;
|
|
|
|
|
swapchainCI.oldSwapchain = oldSwapchain;
|
|
|
|
|
swapchainCI.clipped = true;
|
|
|
|
|
swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
|
|
|
|
|
|
|
|
|
|
err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain);
|
|
|
|
|
assert(!err);
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// If an existing sawp chain is re-created, destroy the old swap chain
|
|
|
|
|
// This also cleans up all the presentable images
|
2016-02-16 15:07:25 +01:00
|
|
|
if (oldSwapchain != VK_NULL_HANDLE)
|
|
|
|
|
{
|
|
|
|
|
fpDestroySwapchainKHR(device, oldSwapchain, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, NULL);
|
|
|
|
|
assert(!err);
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Get the swap chain images
|
|
|
|
|
images.resize(imageCount);
|
|
|
|
|
err = fpGetSwapchainImagesKHR(device, swapChain, &imageCount, images.data());
|
2016-02-16 15:07:25 +01:00
|
|
|
assert(!err);
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
// Get the swap chain buffers containing the image and imageview
|
|
|
|
|
buffers.resize(imageCount);
|
2016-02-16 15:07:25 +01:00
|
|
|
for (uint32_t i = 0; i < imageCount; i++)
|
|
|
|
|
{
|
|
|
|
|
VkImageViewCreateInfo colorAttachmentView = {};
|
|
|
|
|
colorAttachmentView.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
|
|
|
colorAttachmentView.pNext = NULL;
|
|
|
|
|
colorAttachmentView.format = colorFormat;
|
|
|
|
|
colorAttachmentView.components = {
|
|
|
|
|
VK_COMPONENT_SWIZZLE_R,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_G,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_B,
|
|
|
|
|
VK_COMPONENT_SWIZZLE_A
|
|
|
|
|
};
|
|
|
|
|
colorAttachmentView.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
|
|
colorAttachmentView.subresourceRange.baseMipLevel = 0;
|
|
|
|
|
colorAttachmentView.subresourceRange.levelCount = 1;
|
|
|
|
|
colorAttachmentView.subresourceRange.baseArrayLayer = 0;
|
|
|
|
|
colorAttachmentView.subresourceRange.layerCount = 1;
|
|
|
|
|
colorAttachmentView.viewType = VK_IMAGE_VIEW_TYPE_2D;
|
|
|
|
|
colorAttachmentView.flags = 0;
|
|
|
|
|
|
2016-02-23 21:21:36 +01:00
|
|
|
buffers[i].image = images[i];
|
2016-02-16 15:07:25 +01:00
|
|
|
|
|
|
|
|
vkTools::setImageLayout(
|
|
|
|
|
cmdBuffer,
|
|
|
|
|
buffers[i].image,
|
|
|
|
|
VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
|
|
|
|
|
|
|
|
|
colorAttachmentView.image = buffers[i].image;
|
|
|
|
|
|
|
|
|
|
err = vkCreateImageView(device, &colorAttachmentView, nullptr, &buffers[i].view);
|
|
|
|
|
assert(!err);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Acquires the next image in the swap chain
|
|
|
|
|
VkResult acquireNextImage(VkSemaphore presentCompleteSemaphore, uint32_t *currentBuffer)
|
|
|
|
|
{
|
|
|
|
|
return fpAcquireNextImageKHR(device, swapChain, UINT64_MAX, presentCompleteSemaphore, (VkFence)nullptr, currentBuffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Present the current image to the queue
|
|
|
|
|
VkResult queuePresent(VkQueue queue, uint32_t currentBuffer)
|
|
|
|
|
{
|
|
|
|
|
VkPresentInfoKHR presentInfo = {};
|
|
|
|
|
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
|
|
|
|
|
presentInfo.pNext = NULL;
|
|
|
|
|
presentInfo.swapchainCount = 1;
|
|
|
|
|
presentInfo.pSwapchains = &swapChain;
|
|
|
|
|
presentInfo.pImageIndices = ¤tBuffer;
|
|
|
|
|
return fpQueuePresentKHR(queue, &presentInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void cleanup()
|
|
|
|
|
{
|
|
|
|
|
for (uint32_t i = 0; i < imageCount; i++)
|
|
|
|
|
{
|
|
|
|
|
vkDestroyImageView(device, buffers[i].view, nullptr);
|
|
|
|
|
}
|
|
|
|
|
fpDestroySwapchainKHR(device, swapChain, nullptr);
|
|
|
|
|
vkDestroySurfaceKHR(instance, surface, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|