Vulkan-Hpp
CopyBlitImage.cpp
Go to the documentation of this file.
1 // Copyright(c) 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 : CopyBlitImage
16 // Draw a cube
17 
18 #include "../utils/utils.hpp"
19 
20 #include <thread>
21 
22 static char const * AppName = "CopyBlitImage";
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  vk::su::SurfaceData surfaceData( instance, AppName, vk::Extent2D( 640, 640 ) );
37 
38  vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR( surfaceData.surface );
39  if ( !( surfaceCapabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst ) )
40  {
41  std::cout << "Surface cannot be destination of blit - abort \n";
42  exit( -1 );
43  }
44 
45  std::pair<uint32_t, uint32_t> graphicsAndPresentQueueFamilyIndex = vk::su::findGraphicsAndPresentQueueFamilyIndex( physicalDevice, surfaceData.surface );
46  vk::Device device = vk::su::createDevice( physicalDevice, graphicsAndPresentQueueFamilyIndex.first, vk::su::getDeviceExtensions() );
47 
48  vk::CommandPool commandPool = device.createCommandPool( { {}, graphicsAndPresentQueueFamilyIndex.first } );
49  vk::CommandBuffer commandBuffer =
51 
52  vk::Queue graphicsQueue = device.getQueue( graphicsAndPresentQueueFamilyIndex.first, 0 );
53  vk::Queue presentQueue = device.getQueue( graphicsAndPresentQueueFamilyIndex.second, 0 );
54 
55  vk::su::SwapChainData swapChainData( physicalDevice,
56  device,
57  surfaceData.surface,
58  surfaceData.extent,
60  {},
61  graphicsAndPresentQueueFamilyIndex.first,
62  graphicsAndPresentQueueFamilyIndex.second );
63 
64  /* VULKAN_KEY_START */
65 #if !defined( NDEBUG )
66  vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( swapChainData.colorFormat );
67  assert( ( formatProperties.linearTilingFeatures & vk::FormatFeatureFlagBits::eBlitSrc ) && "Format cannot be used as transfer source" );
68 #endif
69 
70  vk::Semaphore imageAcquiredSemaphore = device.createSemaphore( vk::SemaphoreCreateInfo() );
71 
72  // Get the index of the next available swapchain image:
73  vk::ResultValue<uint32_t> nextImage = device.acquireNextImageKHR( swapChainData.swapChain, vk::su::FenceTimeout, imageAcquiredSemaphore, nullptr );
74  assert( nextImage.result == vk::Result::eSuccess );
75  assert( nextImage.value < swapChainData.images.size() );
76  uint32_t imageIndex = nextImage.value;
77 
78  commandBuffer.begin( vk::CommandBufferBeginInfo() );
80  commandBuffer, swapChainData.images[imageIndex], swapChainData.colorFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal );
81 
82  // Create an image, map it, and write some values to the image
83  vk::ImageCreateInfo imageCreateInfo( vk::ImageCreateFlags(),
85  swapChainData.colorFormat,
86  vk::Extent3D( surfaceData.extent, 1 ),
87  1,
88  1,
92  vk::Image blitSourceImage = device.createImage( imageCreateInfo );
93 
94  vk::PhysicalDeviceMemoryProperties memoryProperties = physicalDevice.getMemoryProperties();
95  vk::MemoryRequirements memoryRequirements = device.getImageMemoryRequirements( blitSourceImage );
96  uint32_t memoryTypeIndex = vk::su::findMemoryType( memoryProperties, memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible );
97 
98  vk::DeviceMemory deviceMemory = device.allocateMemory( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
99  device.bindImageMemory( blitSourceImage, deviceMemory, 0 );
100 
101  vk::su::setImageLayout( commandBuffer, blitSourceImage, swapChainData.colorFormat, vk::ImageLayout::eUndefined, vk::ImageLayout::eGeneral );
102 
103  commandBuffer.end();
104 
105  /* Queue the command buffer for execution */
106  vk::Fence commandFence = device.createFence( {} );
108  graphicsQueue.submit( vk::SubmitInfo( imageAcquiredSemaphore, pipeStageFlags, commandBuffer ), commandFence );
109 
110  /* Make sure command buffer is finished before mapping */
111  while ( device.waitForFences( commandFence, true, vk::su::FenceTimeout ) == vk::Result::eTimeout )
112  ;
113 
114  unsigned char * pImageMemory = static_cast<unsigned char *>( device.mapMemory( deviceMemory, 0, memoryRequirements.size ) );
115 
116  // Checkerboard of 8x8 pixel squares
117  for ( uint32_t row = 0; row < surfaceData.extent.height; row++ )
118  {
119  for ( uint32_t col = 0; col < surfaceData.extent.width; col++ )
120  {
121  unsigned char rgb = ( ( ( row & 0x8 ) == 0 ) ^ ( ( col & 0x8 ) == 0 ) ) * 255;
122  pImageMemory[0] = rgb;
123  pImageMemory[1] = rgb;
124  pImageMemory[2] = rgb;
125  pImageMemory[3] = 255;
126  pImageMemory += 4;
127  }
128  }
129 
130  // Flush the mapped memory and then unmap it. Assume it isn't coherent since we didn't really confirm
131  device.flushMappedMemoryRanges( vk::MappedMemoryRange( deviceMemory, 0, memoryRequirements.size ) );
132  device.unmapMemory( deviceMemory );
133 
134  // reset the command buffer by resetting the complete command pool
135  device.resetCommandPool( commandPool );
136 
137  commandBuffer.begin( vk::CommandBufferBeginInfo() );
138 
139  // Intend to blit from this image, set the layout accordingly
141 
142  vk::Image blitDestinationImage = swapChainData.images[imageIndex];
143 
144  // Do a 32x32 blit to all of the dst image - should get big squares
145  vk::ImageSubresourceLayers imageSubresourceLayers( vk::ImageAspectFlagBits::eColor, 0, 0, 1 );
146  vk::ImageBlit imageBlit( imageSubresourceLayers,
147  { { vk::Offset3D( 0, 0, 0 ), vk::Offset3D( 32, 32, 1 ) } },
148  imageSubresourceLayers,
149  { { vk::Offset3D( 0, 0, 0 ), vk::Offset3D( surfaceData.extent.width, surfaceData.extent.height, 1 ) } } );
150  commandBuffer.blitImage(
151  blitSourceImage, vk::ImageLayout::eTransferSrcOptimal, blitDestinationImage, vk::ImageLayout::eTransferDstOptimal, imageBlit, vk::Filter::eLinear );
152 
153  // Use a barrier to make sure the blit is finished before the copy starts
154  // Note: for a layout of vk::ImageLayout::eTransferDstOptimal, the access mask is supposed to be vk::AccessFlagBits::eTransferWrite
161  blitDestinationImage,
163  commandBuffer.pipelineBarrier(
165 
166  // Do a image copy to part of the dst image - checks should stay small
167  vk::ImageCopy imageCopy( imageSubresourceLayers, vk::Offset3D(), imageSubresourceLayers, vk::Offset3D( 256, 256, 0 ), vk::Extent3D( 128, 128, 1 ) );
168  commandBuffer.copyImage( blitSourceImage, vk::ImageLayout::eTransferSrcOptimal, blitDestinationImage, vk::ImageLayout::eTransferDstOptimal, imageCopy );
169 
170  // Note: for a layout of vk::ImageLayout::ePresentSrcKHR, the access mask is supposed to be empty
172  {},
177  swapChainData.images[imageIndex],
179  commandBuffer.pipelineBarrier(
181  commandBuffer.end();
182 
183  vk::Fence drawFence = device.createFence( {} );
184  graphicsQueue.submit( vk::SubmitInfo( {}, {}, commandBuffer ), drawFence );
185  graphicsQueue.waitIdle();
186 
187  /* Make sure command buffer is finished before presenting */
188  while ( device.waitForFences( drawFence, true, vk::su::FenceTimeout ) == vk::Result::eTimeout )
189  ;
190 
191  /* Now present the image in the window */
192  vk::Result result = presentQueue.presentKHR( vk::PresentInfoKHR( {}, swapChainData.swapChain, imageIndex, {} ) );
193  switch ( result )
194  {
195  case vk::Result::eSuccess: break;
196  case vk::Result::eSuboptimalKHR: std::cout << "vk::Queue::presentKHR returned vk::Result::eSuboptimalKHR !\n"; break;
197  default: assert( false ); // an unexpected result is returned !
198  }
199  std::this_thread::sleep_for( std::chrono::milliseconds( 1000 ) );
200 
201  /* VULKAN_KEY_END */
202 
203  device.destroyFence( drawFence );
204  device.destroyFence( commandFence );
205  device.destroyImage( blitSourceImage ); // destroy the image before the bound device memory to prevent some validation layer warning
206  device.freeMemory( deviceMemory );
207  device.destroySemaphore( imageAcquiredSemaphore );
208  swapChainData.clear( device );
209  device.freeCommandBuffers( commandPool, commandBuffer );
210  device.destroyCommandPool( commandPool );
211  device.destroy();
212  instance.destroySurfaceKHR( surfaceData.surface );
213 #if !defined( NDEBUG )
214  instance.destroyDebugUtilsMessengerEXT( debugUtilsMessenger );
215 #endif
216  instance.destroy();
217  }
218  catch ( vk::SystemError & err )
219  {
220  std::cout << "vk::SystemError: " << err.what() << std::endl;
221  exit( -1 );
222  }
223  catch ( std::exception & err )
224  {
225  std::cout << "std::exception: " << err.what() << std::endl;
226  exit( -1 );
227  }
228  catch ( ... )
229  {
230  std::cout << "unknown error\n";
231  exit( -1 );
232  }
233  return 0;
234 }
int main(int, char **)
void cout(vk::SurfaceCapabilitiesKHR const &surfaceCapabilities)
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS ResultValueType< void >::type end(Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const
VULKAN_HPP_NODISCARD Result begin(const vk::CommandBufferBeginInfo *pBeginInfo, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void blitImage(vk::Image srcImage, vk::ImageLayout srcImageLayout, vk::Image dstImage, vk::ImageLayout dstImageLayout, uint32_t regionCount, const vk::ImageBlit *pRegions, vk::Filter filter, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void copyImage(vk::Image srcImage, vk::ImageLayout srcImageLayout, vk::Image dstImage, vk::ImageLayout dstImageLayout, uint32_t regionCount, const vk::ImageCopy *pRegions, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void pipelineBarrier(vk::PipelineStageFlags srcStageMask, vk::PipelineStageFlags dstStageMask, vk::DependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const vk::MemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const vk::BufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const vk::ImageMemoryBarrier *pImageMemoryBarriers, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createFence(const vk::FenceCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Fence *pFence, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void getImageMemoryRequirements(vk::Image image, vk::MemoryRequirements *pMemoryRequirements, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result allocateMemory(const vk::MemoryAllocateInfo *pAllocateInfo, const vk::AllocationCallbacks *pAllocator, vk::DeviceMemory *pMemory, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroySemaphore(vk::Semaphore semaphore, const vk::AllocationCallbacks *pAllocator, 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
void unmapMemory(vk::DeviceMemory memory, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void freeCommandBuffers(vk::CommandPool commandPool, uint32_t commandBufferCount, const vk::CommandBuffer *pCommandBuffers, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
ResultValueType< void >::type resetCommandPool(vk::CommandPool commandPool, vk::CommandPoolResetFlags flags VULKAN_HPP_DEFAULT_ARGUMENT_ASSIGNMENT, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const
void destroyCommandPool(vk::CommandPool commandPool, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result mapMemory(vk::DeviceMemory memory, vk::DeviceSize offset, vk::DeviceSize size, vk::MemoryMapFlags flags, void **ppData, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result waitForFences(uint32_t fenceCount, const vk::Fence *pFences, vk::Bool32 waitAll, uint64_t timeout, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS ResultValueType< void >::type bindImageMemory(vk::Image image, vk::DeviceMemory memory, vk::DeviceSize memoryOffset, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const
void freeMemory(vk::DeviceMemory memory, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createSemaphore(const vk::SemaphoreCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Semaphore *pSemaphore, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createImage(const vk::ImageCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Image *pImage, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createCommandPool(const vk::CommandPoolCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::CommandPool *pCommandPool, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result flushMappedMemoryRanges(uint32_t memoryRangeCount, const vk::MappedMemoryRange *pMemoryRanges, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroyFence(vk::Fence fence, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void destroyImage(vk::Image image, const vk::AllocationCallbacks *pAllocator, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
void getQueue(uint32_t queueFamilyIndex, uint32_t queueIndex, vk::Queue *pQueue, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result allocateCommandBuffers(const vk::CommandBufferAllocateInfo *pAllocateInfo, vk::CommandBuffer *pCommandBuffers, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result acquireNextImageKHR(vk::SwapchainKHR swapchain, uint64_t timeout, vk::Semaphore semaphore, vk::Fence fence, uint32_t *pImageIndex, 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
void getFormatProperties(vk::Format format, vk::FormatProperties *pFormatProperties, 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
void getMemoryProperties(vk::PhysicalDeviceMemoryProperties *pMemoryProperties, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result presentKHR(const vk::PresentInfoKHR *pPresentInfo, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result submit(uint32_t submitCount, const vk::SubmitInfo *pSubmits, vk::Fence fence, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD_WHEN_NO_EXCEPTIONS ResultValueType< void >::type waitIdle(Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const
virtual const char * what() const VULKAN_HPP_NOEXCEPT
Definition: vulkan.hpp:6206
vk::DebugUtilsMessengerCreateInfoEXT makeDebugUtilsMessengerCreateInfoEXT()
Definition: utils.cpp:1025
uint32_t findMemoryType(vk::PhysicalDeviceMemoryProperties const &memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask)
Definition: utils.cpp:456
void setImageLayout(vk::CommandBuffer const &commandBuffer, vk::Image image, vk::Format format, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout)
Definition: utils.cpp:574
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
const uint64_t FenceTimeout
Definition: utils.hpp:31
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
std::pair< uint32_t, uint32_t > findGraphicsAndPresentQueueFamilyIndex(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR const &surface)
Definition: utils.cpp:420
std::vector< std::string > getInstanceExtensions()
Definition: utils.cpp:477
std::vector< std::string > getDeviceExtensions()
Definition: utils.cpp:472
vk::FormatFeatureFlags linearTilingFeatures
vk::ImageUsageFlags supportedUsageFlags
vk::Extent2D extent
Definition: utils.hpp:203
vk::SurfaceKHR surface
Definition: utils.hpp:205
vk::SwapchainKHR swapChain
Definition: utils.hpp:231
vk::Format colorFormat
Definition: utils.hpp:230
void clear(vk::Device const &device)
Definition: utils.hpp:219
std::vector< vk::Image > images
Definition: utils.hpp:232
#define VK_QUEUE_FAMILY_IGNORED
Definition: vulkan_core.h:127