Vulkan-Hpp
05_InitSwapchain.cpp
Go to the documentation of this file.
1 // Copyright(c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // VulkanHpp Samples : 05_InitSwapchain
16 // Initialize a swapchain
17 
18 #include "../utils/utils.hpp"
19 
20 #include <iostream>
21 
22 static char const * AppName = "05_InitSwapchain";
23 static char const * EngineName = "Vulkan.hpp";
24 
25 int main( int /*argc*/, char ** /*argv*/ )
26 {
27  try
28  {
29  vk::Instance instance = vk::su::createInstance( AppName, EngineName, {}, vk::su::getInstanceExtensions() );
30 #if !defined( NDEBUG )
32 #endif
33 
34  vk::PhysicalDevice physicalDevice = instance.enumeratePhysicalDevices().front();
35 
36  std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
37  uint32_t graphicsQueueFamilyIndex = vk::su::findGraphicsQueueFamilyIndex( queueFamilyProperties );
38 
39  /* VULKAN_HPP_KEY_START */
40 
41  uint32_t width = 64;
42  uint32_t height = 64;
43  vk::su::WindowData window = vk::su::createWindow( AppName, { width, height } );
44  vk::SurfaceKHR surface;
45  {
46  VkSurfaceKHR _surface;
47  glfwCreateWindowSurface( static_cast<VkInstance>( instance ), window.handle, nullptr, &_surface );
48  surface = vk::SurfaceKHR( _surface );
49  }
50 
51  // determine a queueFamilyIndex that suports present
52  // first check if the graphicsQueueFamiliyIndex is good enough
53  size_t presentQueueFamilyIndex = physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( graphicsQueueFamilyIndex ), surface )
54  ? graphicsQueueFamilyIndex
55  : queueFamilyProperties.size();
56  if ( presentQueueFamilyIndex == queueFamilyProperties.size() )
57  {
58  // the graphicsQueueFamilyIndex doesn't support present -> look for an other family index that supports both
59  // graphics and present
60  for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
61  {
62  if ( ( queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics ) &&
63  physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), surface ) )
64  {
65  graphicsQueueFamilyIndex = vk::su::checked_cast<uint32_t>( i );
66  presentQueueFamilyIndex = i;
67  break;
68  }
69  }
70  if ( presentQueueFamilyIndex == queueFamilyProperties.size() )
71  {
72  // there's nothing like a single family index that supports both graphics and present -> look for an other
73  // family index that supports present
74  for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
75  {
76  if ( physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), surface ) )
77  {
78  presentQueueFamilyIndex = i;
79  break;
80  }
81  }
82  }
83  }
84  if ( ( graphicsQueueFamilyIndex == queueFamilyProperties.size() ) || ( presentQueueFamilyIndex == queueFamilyProperties.size() ) )
85  {
86  throw std::runtime_error( "Could not find a queue for graphics or present -> terminating" );
87  }
88 
89  // create a device
90  vk::Device device = vk::su::createDevice( physicalDevice, graphicsQueueFamilyIndex, vk::su::getDeviceExtensions() );
91 
92  // get the supported VkFormats
93  std::vector<vk::SurfaceFormatKHR> formats = physicalDevice.getSurfaceFormatsKHR( surface );
94  assert( !formats.empty() );
95  vk::Format format = ( formats[0].format == vk::Format::eUndefined ) ? vk::Format::eB8G8R8A8Unorm : formats[0].format;
96 
97  vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR( surface );
98  vk::Extent2D swapchainExtent;
99  if ( surfaceCapabilities.currentExtent.width == std::numeric_limits<uint32_t>::max() )
100  {
101  // If the surface size is undefined, the size is set to the size of the images requested.
102  swapchainExtent.width = vk::su::clamp( width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width );
103  swapchainExtent.height = vk::su::clamp( height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height );
104  }
105  else
106  {
107  // If the surface size is defined, the swap chain size must match
108  swapchainExtent = surfaceCapabilities.currentExtent;
109  }
110 
111  // The FIFO present mode is guaranteed by the spec to be supported
112  vk::PresentModeKHR swapchainPresentMode = vk::PresentModeKHR::eFifo;
113 
116  : surfaceCapabilities.currentTransform;
117 
118  vk::CompositeAlphaFlagBitsKHR compositeAlpha =
123 
125  surface,
126  vk::su::clamp( 3u, surfaceCapabilities.minImageCount, surfaceCapabilities.maxImageCount ),
127  format,
129  swapchainExtent,
130  1,
133  {},
134  preTransform,
135  compositeAlpha,
136  swapchainPresentMode,
137  true,
138  nullptr );
139 
140  uint32_t queueFamilyIndices[2] = { static_cast<uint32_t>( graphicsQueueFamilyIndex ), static_cast<uint32_t>( presentQueueFamilyIndex ) };
141  if ( graphicsQueueFamilyIndex != presentQueueFamilyIndex )
142  {
143  // If the graphics and present queues are from different queue families, we either have to explicitly transfer
144  // ownership of images between the queues, or we have to create the swapchain with imageSharingMode as
145  // VK_SHARING_MODE_CONCURRENT
146  swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent;
147  swapChainCreateInfo.queueFamilyIndexCount = 2;
148  swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
149  }
150 
151  vk::SwapchainKHR swapChain = device.createSwapchainKHR( swapChainCreateInfo );
152 
153  std::vector<vk::Image> swapChainImages = device.getSwapchainImagesKHR( swapChain );
154 
155  std::vector<vk::ImageView> imageViews;
156  imageViews.reserve( swapChainImages.size() );
157  vk::ImageViewCreateInfo imageViewCreateInfo( {}, {}, vk::ImageViewType::e2D, format, {}, { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } );
158  for ( auto image : swapChainImages )
159  {
160  imageViewCreateInfo.image = image;
161  imageViews.push_back( device.createImageView( imageViewCreateInfo ) );
162  }
163 
164  // destroy the imageViews, the swapChain, and the surface
165  for ( auto & imageView : imageViews )
166  {
167  device.destroyImageView( imageView );
168  }
169  device.destroySwapchainKHR( swapChain );
170  instance.destroySurfaceKHR( surface );
171 
172  /* VULKAN_HPP_KEY_END */
173 
174  device.destroy();
175 #if !defined( NDEBUG )
176  instance.destroyDebugUtilsMessengerEXT( debugUtilsMessenger );
177 #endif
178  instance.destroy();
179  }
180  catch ( vk::SystemError & err )
181  {
182  std::cout << "vk::SystemError: " << err.what() << std::endl;
183  exit( -1 );
184  }
185  catch ( std::exception & err )
186  {
187  std::cout << "std::exception: " << err.what() << std::endl;
188  exit( -1 );
189  }
190  catch ( ... )
191  {
192  std::cout << "unknown error\n";
193  exit( -1 );
194  }
195  return 0;
196 }
int main(int, char **)
void cout(vk::SurfaceCapabilitiesKHR const &surfaceCapabilities)
void destroy(const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroyImageView(vk::ImageView imageView, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createImageView(const vk::ImageViewCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::ImageView *pView, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createSwapchainKHR(const vk::SwapchainCreateInfoKHR *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::SwapchainKHR *pSwapchain, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result getSwapchainImagesKHR(vk::SwapchainKHR swapchain, uint32_t *pSwapchainImageCount, vk::Image *pSwapchainImages, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroySwapchainKHR(vk::SwapchainKHR swapchain, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createDebugUtilsMessengerEXT(const vk::DebugUtilsMessengerCreateInfoEXT *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::DebugUtilsMessengerEXT *pMessenger, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroy(const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result enumeratePhysicalDevices(uint32_t *pPhysicalDeviceCount, vk::PhysicalDevice *pPhysicalDevices, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroySurfaceKHR(vk::SurfaceKHR surface, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroyDebugUtilsMessengerEXT(vk::DebugUtilsMessengerEXT messenger, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result getSurfaceFormatsKHR(vk::SurfaceKHR surface, uint32_t *pSurfaceFormatCount, vk::SurfaceFormatKHR *pSurfaceFormats, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void getQueueFamilyProperties(uint32_t *pQueueFamilyPropertyCount, vk::QueueFamilyProperties *pQueueFamilyProperties, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result getSurfaceCapabilitiesKHR(vk::SurfaceKHR surface, vk::SurfaceCapabilitiesKHR *pSurfaceCapabilities, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result getSurfaceSupportKHR(uint32_t queueFamilyIndex, vk::SurfaceKHR surface, vk::Bool32 *pSupported, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
virtual const char * what() const VULKAN_HPP_NOEXCEPT
Definition: vulkan.hpp:6206
uint32_t findGraphicsQueueFamilyIndex(std::vector< vk::QueueFamilyProperties > const &queueFamilyProperties)
Definition: utils.cpp:409
vk::DebugUtilsMessengerCreateInfoEXT makeDebugUtilsMessengerCreateInfoEXT()
Definition: utils.cpp:1025
vk::Instance createInstance(std::string const &appName, std::string const &engineName, std::vector< std::string > const &layers, std::vector< std::string > const &extensions, uint32_t apiVersion)
Definition: utils.cpp:279
vk::Device createDevice(vk::PhysicalDevice const &physicalDevice, uint32_t queueFamilyIndex, std::vector< std::string > const &extensions, vk::PhysicalDeviceFeatures const *physicalDeviceFeatures, void const *pNext)
Definition: utils.cpp:86
WindowData createWindow(std::string const &windowName, vk::Extent2D const &extent)
Definition: utils.cpp:996
std::vector< std::string > getInstanceExtensions()
Definition: utils.cpp:477
constexpr VULKAN_HPP_INLINE const T & clamp(const T &v, const T &lo, const T &hi)
Definition: utils.hpp:72
std::vector< std::string > getDeviceExtensions()
Definition: utils.cpp:472
SurfaceTransformFlagBitsKHR
CompositeAlphaFlagBitsKHR
PresentModeKHR
vk::SurfaceTransformFlagsKHR supportedTransforms
vk::SurfaceTransformFlagBitsKHR currentTransform
vk::CompositeAlphaFlagsKHR supportedCompositeAlpha
const uint32_t * pQueueFamilyIndices
GLFWwindow * handle
Definition: utils.hpp:87
uint64_t VkSurfaceKHR
Definition: vulkan_core.h:7513
struct VkInstance_T * VkInstance
Definition: vulkan_core.h:101