Vulkan-Hpp
utils.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 
16 #if defined( _MSC_VER )
17 // no need to ignore any warnings with MSVC
18 #elif defined( __clang__ )
19 # pragma clang diagnostic ignored "-Wmissing-braces"
20 #elif defined( __GNUC__ )
21 // no need to ignore any warnings with GCC
22 #else
23 // unknow compiler... just ignore the warnings for yourselves ;)
24 #endif
25 
26 #include "utils.hpp"
27 
28 #include <iomanip>
29 #include <numeric>
30 #include <vulkan/vulkan.hpp>
31 #if defined( VULKAN_HPP_NO_TO_STRING )
33 #endif
35 
36 #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
38 #endif
39 
40 namespace vk
41 {
42  namespace su
43  {
45  vk::PhysicalDeviceMemoryProperties const & memoryProperties,
46  vk::MemoryRequirements const & memoryRequirements,
47  vk::MemoryPropertyFlags memoryPropertyFlags )
48  {
49  uint32_t memoryTypeIndex = findMemoryType( memoryProperties, memoryRequirements.memoryTypeBits, memoryPropertyFlags );
50 
51  return device.allocateMemory( vk::MemoryAllocateInfo( memoryRequirements.size, memoryTypeIndex ) );
52  }
53 
54  bool contains( std::vector<vk::ExtensionProperties> const & extensionProperties, std::string const & extensionName )
55  {
56  auto propertyIterator = std::find_if( extensionProperties.begin(),
57  extensionProperties.end(),
58  [&extensionName]( vk::ExtensionProperties const & ep ) { return extensionName == ep.extensionName; } );
59  return ( propertyIterator != extensionProperties.end() );
60  }
61 
62  vk::DescriptorPool createDescriptorPool( vk::Device const & device, std::vector<vk::DescriptorPoolSize> const & poolSizes )
63  {
64  assert( !poolSizes.empty() );
65  uint32_t maxSets =
66  std::accumulate( poolSizes.begin(), poolSizes.end(), 0, []( uint32_t sum, vk::DescriptorPoolSize const & dps ) { return sum + dps.descriptorCount; } );
67  assert( 0 < maxSets );
68 
69  vk::DescriptorPoolCreateInfo descriptorPoolCreateInfo( vk::DescriptorPoolCreateFlagBits::eFreeDescriptorSet, maxSets, poolSizes );
70  return device.createDescriptorPool( descriptorPoolCreateInfo );
71  }
72 
74  std::vector<std::tuple<vk::DescriptorType, uint32_t, vk::ShaderStageFlags>> const & bindingData,
76  {
77  std::vector<vk::DescriptorSetLayoutBinding> bindings( bindingData.size() );
78  for ( size_t i = 0; i < bindingData.size(); i++ )
79  {
80  bindings[i] = vk::DescriptorSetLayoutBinding(
81  checked_cast<uint32_t>( i ), std::get<0>( bindingData[i] ), std::get<1>( bindingData[i] ), std::get<2>( bindingData[i] ) );
82  }
83  return device.createDescriptorSetLayout( vk::DescriptorSetLayoutCreateInfo( flags, bindings ) );
84  }
85 
86  vk::Device createDevice( vk::PhysicalDevice const & physicalDevice,
87  uint32_t queueFamilyIndex,
88  std::vector<std::string> const & extensions,
89  vk::PhysicalDeviceFeatures const * physicalDeviceFeatures,
90  void const * pNext )
91  {
92  std::vector<char const *> enabledExtensions;
93  enabledExtensions.reserve( extensions.size() );
94  for ( auto const & ext : extensions )
95  {
96  enabledExtensions.push_back( ext.data() );
97  }
98 
99  float queuePriority = 0.0f;
100  vk::DeviceQueueCreateInfo deviceQueueCreateInfo( {}, queueFamilyIndex, 1, &queuePriority );
101  vk::DeviceCreateInfo deviceCreateInfo( {}, deviceQueueCreateInfo, {}, enabledExtensions, physicalDeviceFeatures, pNext );
102 
103  vk::Device device = physicalDevice.createDevice( deviceCreateInfo );
104 #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
105  // initialize function pointers for instance
106  VULKAN_HPP_DEFAULT_DISPATCHER.init( device );
107 #endif
108  return device;
109  }
110 
111  std::vector<vk::Framebuffer> createFramebuffers( vk::Device const & device,
112  vk::RenderPass & renderPass,
113  std::vector<vk::ImageView> const & imageViews,
114  vk::ImageView const & depthImageView,
115  vk::Extent2D const & extent )
116  {
117  vk::ImageView attachments[2];
118  attachments[1] = depthImageView;
119 
120  vk::FramebufferCreateInfo framebufferCreateInfo(
121  vk::FramebufferCreateFlags(), renderPass, depthImageView ? 2 : 1, attachments, extent.width, extent.height, 1 );
122  std::vector<vk::Framebuffer> framebuffers;
123  framebuffers.reserve( imageViews.size() );
124  for ( auto const & view : imageViews )
125  {
126  attachments[0] = view;
127  framebuffers.push_back( device.createFramebuffer( framebufferCreateInfo ) );
128  }
129 
130  return framebuffers;
131  }
132 
134  vk::PipelineCache const & pipelineCache,
135  std::pair<vk::ShaderModule, vk::SpecializationInfo const *> const & vertexShaderData,
136  std::pair<vk::ShaderModule, vk::SpecializationInfo const *> const & fragmentShaderData,
137  uint32_t vertexStride,
138  std::vector<std::pair<vk::Format, uint32_t>> const & vertexInputAttributeFormatOffset,
139  vk::FrontFace frontFace,
140  bool depthBuffered,
141  vk::PipelineLayout const & pipelineLayout,
142  vk::RenderPass const & renderPass )
143  {
144  std::array<vk::PipelineShaderStageCreateInfo, 2> pipelineShaderStageCreateInfos = {
146  vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eVertex, vertexShaderData.first, "main", vertexShaderData.second ),
148  vk::PipelineShaderStageCreateFlags(), vk::ShaderStageFlagBits::eFragment, fragmentShaderData.first, "main", fragmentShaderData.second )
149  };
150 
151  std::vector<vk::VertexInputAttributeDescription> vertexInputAttributeDescriptions;
152  vk::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo;
153  vk::VertexInputBindingDescription vertexInputBindingDescription( 0, vertexStride );
154 
155  if ( 0 < vertexStride )
156  {
157  vertexInputAttributeDescriptions.reserve( vertexInputAttributeFormatOffset.size() );
158  for ( uint32_t i = 0; i < vertexInputAttributeFormatOffset.size(); i++ )
159  {
160  vertexInputAttributeDescriptions.emplace_back( i, 0, vertexInputAttributeFormatOffset[i].first, vertexInputAttributeFormatOffset[i].second );
161  }
162  pipelineVertexInputStateCreateInfo.setVertexBindingDescriptions( vertexInputBindingDescription );
163  pipelineVertexInputStateCreateInfo.setVertexAttributeDescriptions( vertexInputAttributeDescriptions );
164  }
165 
168 
169  vk::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo( vk::PipelineViewportStateCreateFlags(), 1, nullptr, 1, nullptr );
170 
172  false,
173  false,
176  frontFace,
177  false,
178  0.0f,
179  0.0f,
180  0.0f,
181  1.0f );
182 
183  vk::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo( {}, vk::SampleCountFlagBits::e1 );
184 
186  vk::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo(
187  vk::PipelineDepthStencilStateCreateFlags(), depthBuffered, depthBuffered, vk::CompareOp::eLessOrEqual, false, false, stencilOpState, stencilOpState );
188 
191  vk::PipelineColorBlendAttachmentState pipelineColorBlendAttachmentState( false,
198  colorComponentFlags );
199  vk::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo(
200  vk::PipelineColorBlendStateCreateFlags(), false, vk::LogicOp::eNoOp, pipelineColorBlendAttachmentState, { { 1.0f, 1.0f, 1.0f, 1.0f } } );
201 
202  std::array<vk::DynamicState, 2> dynamicStates = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
203  vk::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo( vk::PipelineDynamicStateCreateFlags(), dynamicStates );
204 
205  vk::GraphicsPipelineCreateInfo graphicsPipelineCreateInfo( vk::PipelineCreateFlags(),
206  pipelineShaderStageCreateInfos,
207  &pipelineVertexInputStateCreateInfo,
208  &pipelineInputAssemblyStateCreateInfo,
209  nullptr,
210  &pipelineViewportStateCreateInfo,
211  &pipelineRasterizationStateCreateInfo,
212  &pipelineMultisampleStateCreateInfo,
213  &pipelineDepthStencilStateCreateInfo,
214  &pipelineColorBlendStateCreateInfo,
215  &pipelineDynamicStateCreateInfo,
216  pipelineLayout,
217  renderPass );
218 
219  auto result = device.createGraphicsPipeline( pipelineCache, graphicsPipelineCreateInfo );
220  assert( result.result == vk::Result::eSuccess );
221  return result.value;
222  }
223 
224  std::vector<char const *> gatherExtensions( std::vector<std::string> const & extensions
225 #if !defined( NDEBUG )
226  ,
227  std::vector<vk::ExtensionProperties> const & extensionProperties
228 #endif
229  )
230  {
231  std::vector<char const *> enabledExtensions;
232  enabledExtensions.reserve( extensions.size() );
233  for ( auto const & ext : extensions )
234  {
235  assert( std::any_of(
236  extensionProperties.begin(), extensionProperties.end(), [ext]( vk::ExtensionProperties const & ep ) { return ext == ep.extensionName; } ) );
237  enabledExtensions.push_back( ext.data() );
238  }
239 #if !defined( NDEBUG )
240  if ( std::none_of(
241  extensions.begin(), extensions.end(), []( std::string const & extension ) { return extension == VK_EXT_DEBUG_UTILS_EXTENSION_NAME; } ) &&
242  std::any_of( extensionProperties.begin(),
243  extensionProperties.end(),
244  []( vk::ExtensionProperties const & ep ) { return ( strcmp( VK_EXT_DEBUG_UTILS_EXTENSION_NAME, ep.extensionName ) == 0 ); } ) )
245  {
246  enabledExtensions.push_back( VK_EXT_DEBUG_UTILS_EXTENSION_NAME );
247  }
248 #endif
249  return enabledExtensions;
250  }
251 
252  std::vector<char const *> gatherLayers( std::vector<std::string> const & layers
253 #if !defined( NDEBUG )
254  ,
255  std::vector<vk::LayerProperties> const & layerProperties
256 #endif
257  )
258  {
259  std::vector<char const *> enabledLayers;
260  enabledLayers.reserve( layers.size() );
261  for ( auto const & layer : layers )
262  {
263  assert( std::any_of( layerProperties.begin(), layerProperties.end(), [layer]( vk::LayerProperties const & lp ) { return layer == lp.layerName; } ) );
264  enabledLayers.push_back( layer.data() );
265  }
266 #if !defined( NDEBUG )
267  // Enable standard validation layer to find as much errors as possible!
268  if ( std::none_of( layers.begin(), layers.end(), []( std::string const & layer ) { return layer == "VK_LAYER_KHRONOS_validation"; } ) &&
269  std::any_of( layerProperties.begin(),
270  layerProperties.end(),
271  []( vk::LayerProperties const & lp ) { return ( strcmp( "VK_LAYER_KHRONOS_validation", lp.layerName ) == 0 ); } ) )
272  {
273  enabledLayers.push_back( "VK_LAYER_KHRONOS_validation" );
274  }
275 #endif
276  return enabledLayers;
277  }
278 
279  vk::Instance createInstance( std::string const & appName,
280  std::string const & engineName,
281  std::vector<std::string> const & layers,
282  std::vector<std::string> const & extensions,
283  uint32_t apiVersion )
284  {
285 #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
287 #endif
288 
289  vk::ApplicationInfo applicationInfo( appName.c_str(), 1, engineName.c_str(), 1, apiVersion );
290  std::vector<char const *> enabledLayers = vk::su::gatherLayers( layers
291 #if !defined( NDEBUG )
292  ,
294 #endif
295  );
296  std::vector<char const *> enabledExtensions = vk::su::gatherExtensions( extensions
297 #if !defined( NDEBUG )
298  ,
300 #endif
301  );
302 
303  vk::Instance instance =
304  vk::createInstance( makeInstanceCreateInfoChain( applicationInfo, enabledLayers, enabledExtensions ).get<vk::InstanceCreateInfo>() );
305 
306 #if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
307  // initialize function pointers for instance
308  VULKAN_HPP_DEFAULT_DISPATCHER.init( instance );
309 #endif
310 
311  return instance;
312  }
313 
315  vk::Device const & device, vk::Format colorFormat, vk::Format depthFormat, vk::AttachmentLoadOp loadOp, vk::ImageLayout colorFinalLayout )
316  {
317  std::vector<vk::AttachmentDescription> attachmentDescriptions;
318  assert( colorFormat != vk::Format::eUndefined );
319  attachmentDescriptions.emplace_back( vk::AttachmentDescriptionFlags(),
320  colorFormat,
322  loadOp,
327  colorFinalLayout );
328  if ( depthFormat != vk::Format::eUndefined )
329  {
330  attachmentDescriptions.emplace_back( vk::AttachmentDescriptionFlags(),
331  depthFormat,
333  loadOp,
339  }
344  {},
345  colorAttachment,
346  {},
347  ( depthFormat != vk::Format::eUndefined ) ? &depthAttachment : nullptr );
348  return device.createRenderPass( vk::RenderPassCreateInfo( vk::RenderPassCreateFlags(), attachmentDescriptions, subpassDescription ) );
349  }
350 
352  VkDebugUtilsMessageTypeFlagsEXT messageTypes,
353  VkDebugUtilsMessengerCallbackDataEXT const * pCallbackData,
354  void * /*pUserData*/ )
355  {
356 #if !defined( NDEBUG )
357  if ( static_cast<uint32_t>( pCallbackData->messageIdNumber ) == 0x822806fa )
358  {
359  // Validation Warning: vkCreateInstance(): to enable extension VK_EXT_debug_utils, but this extension is intended to support use by applications when
360  // debugging and it is strongly recommended that it be otherwise avoided.
361  return vk::False;
362  }
363  else if ( static_cast<uint32_t>( pCallbackData->messageIdNumber ) == 0xe8d1a9fe )
364  {
365  // Validation Performance Warning: Using debug builds of the validation layers *will* adversely affect performance.
366  return vk::False;
367  }
368 #endif
369 
370  std::cerr << vk::to_string( static_cast<vk::DebugUtilsMessageSeverityFlagBitsEXT>( messageSeverity ) ) << ": "
371  << vk::to_string( static_cast<vk::DebugUtilsMessageTypeFlagsEXT>( messageTypes ) ) << ":\n";
372  std::cerr << std::string( "\t" ) << "messageIDName = <" << pCallbackData->pMessageIdName << ">\n";
373  std::cerr << std::string( "\t" ) << "messageIdNumber = " << pCallbackData->messageIdNumber << "\n";
374  std::cerr << std::string( "\t" ) << "message = <" << pCallbackData->pMessage << ">\n";
375  if ( 0 < pCallbackData->queueLabelCount )
376  {
377  std::cerr << std::string( "\t" ) << "Queue Labels:\n";
378  for ( uint32_t i = 0; i < pCallbackData->queueLabelCount; i++ )
379  {
380  std::cerr << std::string( "\t\t" ) << "labelName = <" << pCallbackData->pQueueLabels[i].pLabelName << ">\n";
381  }
382  }
383  if ( 0 < pCallbackData->cmdBufLabelCount )
384  {
385  std::cerr << std::string( "\t" ) << "CommandBuffer Labels:\n";
386  for ( uint32_t i = 0; i < pCallbackData->cmdBufLabelCount; i++ )
387  {
388  std::cerr << std::string( "\t\t" ) << "labelName = <" << pCallbackData->pCmdBufLabels[i].pLabelName << ">\n";
389  }
390  }
391  if ( 0 < pCallbackData->objectCount )
392  {
393  std::cerr << std::string( "\t" ) << "Objects:\n";
394  for ( uint32_t i = 0; i < pCallbackData->objectCount; i++ )
395  {
396  std::cerr << std::string( "\t\t" ) << "Object " << i << "\n";
397  std::cerr << std::string( "\t\t\t" ) << "objectType = " << vk::to_string( static_cast<vk::ObjectType>( pCallbackData->pObjects[i].objectType ) )
398  << "\n";
399  std::cerr << std::string( "\t\t\t" ) << "objectHandle = " << pCallbackData->pObjects[i].objectHandle << "\n";
400  if ( pCallbackData->pObjects[i].pObjectName )
401  {
402  std::cerr << std::string( "\t\t\t" ) << "objectName = <" << pCallbackData->pObjects[i].pObjectName << ">\n";
403  }
404  }
405  }
406  return vk::False;
407  }
408 
409  uint32_t findGraphicsQueueFamilyIndex( std::vector<vk::QueueFamilyProperties> const & queueFamilyProperties )
410  {
411  // get the first index into queueFamiliyProperties which supports graphics
412  std::vector<vk::QueueFamilyProperties>::const_iterator graphicsQueueFamilyProperty =
413  std::find_if( queueFamilyProperties.begin(),
414  queueFamilyProperties.end(),
415  []( vk::QueueFamilyProperties const & qfp ) { return qfp.queueFlags & vk::QueueFlagBits::eGraphics; } );
416  assert( graphicsQueueFamilyProperty != queueFamilyProperties.end() );
417  return static_cast<uint32_t>( std::distance( queueFamilyProperties.begin(), graphicsQueueFamilyProperty ) );
418  }
419 
420  std::pair<uint32_t, uint32_t> findGraphicsAndPresentQueueFamilyIndex( vk::PhysicalDevice physicalDevice, vk::SurfaceKHR const & surface )
421  {
422  std::vector<vk::QueueFamilyProperties> queueFamilyProperties = physicalDevice.getQueueFamilyProperties();
423  assert( queueFamilyProperties.size() < std::numeric_limits<uint32_t>::max() );
424 
425  uint32_t graphicsQueueFamilyIndex = findGraphicsQueueFamilyIndex( queueFamilyProperties );
426  if ( physicalDevice.getSurfaceSupportKHR( graphicsQueueFamilyIndex, surface ) )
427  {
428  return std::make_pair( graphicsQueueFamilyIndex,
429  graphicsQueueFamilyIndex ); // the first graphicsQueueFamilyIndex does also support presents
430  }
431 
432  // the graphicsQueueFamilyIndex doesn't support present -> look for an other family index that supports both
433  // graphics and present
434  for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
435  {
436  if ( ( queueFamilyProperties[i].queueFlags & vk::QueueFlagBits::eGraphics ) &&
437  physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), surface ) )
438  {
439  return std::make_pair( static_cast<uint32_t>( i ), static_cast<uint32_t>( i ) );
440  }
441  }
442 
443  // there's nothing like a single family index that supports both graphics and present -> look for an other family
444  // index that supports present
445  for ( size_t i = 0; i < queueFamilyProperties.size(); i++ )
446  {
447  if ( physicalDevice.getSurfaceSupportKHR( static_cast<uint32_t>( i ), surface ) )
448  {
449  return std::make_pair( graphicsQueueFamilyIndex, static_cast<uint32_t>( i ) );
450  }
451  }
452 
453  throw std::runtime_error( "Could not find queues for both graphics or present -> terminating" );
454  }
455 
456  uint32_t findMemoryType( vk::PhysicalDeviceMemoryProperties const & memoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirementsMask )
457  {
458  uint32_t typeIndex = uint32_t( ~0 );
459  for ( uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++ )
460  {
461  if ( ( typeBits & 1 ) && ( ( memoryProperties.memoryTypes[i].propertyFlags & requirementsMask ) == requirementsMask ) )
462  {
463  typeIndex = i;
464  break;
465  }
466  typeBits >>= 1;
467  }
468  assert( typeIndex != uint32_t( ~0 ) );
469  return typeIndex;
470  }
471 
472  std::vector<std::string> getDeviceExtensions()
473  {
475  }
476 
477  std::vector<std::string> getInstanceExtensions()
478  {
479  std::vector<std::string> extensions;
480  extensions.push_back( VK_KHR_SURFACE_EXTENSION_NAME );
481 #if defined( VK_USE_PLATFORM_ANDROID_KHR )
482  extensions.push_back( VK_KHR_ANDROID_SURFACE_EXTENSION_NAME );
483 #elif defined( VK_USE_PLATFORM_IOS_MVK )
484  extensions.push_back( VK_MVK_IOS_SURFACE_EXTENSION_NAME );
485 #elif defined( VK_USE_PLATFORM_MACOS_MVK )
486  extensions.push_back( VK_MVK_MACOS_SURFACE_EXTENSION_NAME );
487 #elif defined( VK_USE_PLATFORM_MIR_KHR )
488  extensions.push_back( VK_KHR_MIR_SURFACE_EXTENSION_NAME );
489 #elif defined( VK_USE_PLATFORM_VI_NN )
490  extensions.push_back( VK_NN_VI_SURFACE_EXTENSION_NAME );
491 #elif defined( VK_USE_PLATFORM_WAYLAND_KHR )
492  extensions.push_back( VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME );
493 #elif defined( VK_USE_PLATFORM_WIN32_KHR )
494  extensions.push_back( VK_KHR_WIN32_SURFACE_EXTENSION_NAME );
495 #elif defined( VK_USE_PLATFORM_XCB_KHR )
496  extensions.push_back( VK_KHR_XCB_SURFACE_EXTENSION_NAME );
497 #elif defined( VK_USE_PLATFORM_XLIB_KHR )
498  extensions.push_back( VK_KHR_XLIB_SURFACE_EXTENSION_NAME );
499 #elif defined( VK_USE_PLATFORM_XLIB_XRANDR_EXT )
500  extensions.push_back( VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME );
501 #endif
502  return extensions;
503  }
504 
506  {
507  std::vector<vk::Format> candidates = { vk::Format::eD32Sfloat, vk::Format::eD32SfloatS8Uint, vk::Format::eD24UnormS8Uint };
508  for ( vk::Format format : candidates )
509  {
510  vk::FormatProperties props = physicalDevice.getFormatProperties( format );
511 
513  {
514  return format;
515  }
516  }
517  throw std::runtime_error( "failed to find supported format!" );
518  }
519 
520  vk::PresentModeKHR pickPresentMode( std::vector<vk::PresentModeKHR> const & presentModes )
521  {
523  for ( const auto & presentMode : presentModes )
524  {
525  if ( presentMode == vk::PresentModeKHR::eMailbox )
526  {
527  pickedMode = presentMode;
528  break;
529  }
530 
531  if ( presentMode == vk::PresentModeKHR::eImmediate )
532  {
533  pickedMode = presentMode;
534  }
535  }
536  return pickedMode;
537  }
538 
539  vk::SurfaceFormatKHR pickSurfaceFormat( std::vector<vk::SurfaceFormatKHR> const & formats )
540  {
541  assert( !formats.empty() );
542  vk::SurfaceFormatKHR pickedFormat = formats[0];
543  if ( formats.size() == 1 )
544  {
545  if ( formats[0].format == vk::Format::eUndefined )
546  {
547  pickedFormat.format = vk::Format::eB8G8R8A8Unorm;
549  }
550  }
551  else
552  {
553  // request several formats, the first found will be used
556  for ( size_t i = 0; i < sizeof( requestedFormats ) / sizeof( requestedFormats[0] ); i++ )
557  {
558  vk::Format requestedFormat = requestedFormats[i];
559  auto it = std::find_if( formats.begin(),
560  formats.end(),
561  [requestedFormat, requestedColorSpace]( vk::SurfaceFormatKHR const & f )
562  { return ( f.format == requestedFormat ) && ( f.colorSpace == requestedColorSpace ); } );
563  if ( it != formats.end() )
564  {
565  pickedFormat = *it;
566  break;
567  }
568  }
569  }
570  assert( pickedFormat.colorSpace == vk::ColorSpaceKHR::eSrgbNonlinear );
571  return pickedFormat;
572  }
573 
575  vk::CommandBuffer const & commandBuffer, vk::Image image, vk::Format format, vk::ImageLayout oldImageLayout, vk::ImageLayout newImageLayout )
576  {
577  vk::AccessFlags sourceAccessMask;
578  switch ( oldImageLayout )
579  {
582  case vk::ImageLayout::eGeneral: // sourceAccessMask is empty
583  case vk::ImageLayout::eUndefined: break;
584  default: assert( false ); break;
585  }
586 
587  vk::PipelineStageFlags sourceStage;
588  switch ( oldImageLayout )
589  {
594  default: assert( false ); break;
595  }
596 
597  vk::AccessFlags destinationAccessMask;
598  switch ( newImageLayout )
599  {
603  break;
604  case vk::ImageLayout::eGeneral: // empty destinationAccessMask
607  case vk::ImageLayout::eTransferSrcOptimal: destinationAccessMask = vk::AccessFlagBits::eTransferRead; break;
609  default: assert( false ); break;
610  }
611 
612  vk::PipelineStageFlags destinationStage;
613  switch ( newImageLayout )
614  {
617  case vk::ImageLayout::eGeneral: destinationStage = vk::PipelineStageFlagBits::eHost; break;
622  default: assert( false ); break;
623  }
624 
625  vk::ImageAspectFlags aspectMask;
626  if ( newImageLayout == vk::ImageLayout::eDepthStencilAttachmentOptimal )
627  {
628  aspectMask = vk::ImageAspectFlagBits::eDepth;
629  if ( format == vk::Format::eD32SfloatS8Uint || format == vk::Format::eD24UnormS8Uint )
630  {
631  aspectMask |= vk::ImageAspectFlagBits::eStencil;
632  }
633  }
634  else
635  {
636  aspectMask = vk::ImageAspectFlagBits::eColor;
637  }
638 
639  vk::ImageSubresourceRange imageSubresourceRange( aspectMask, 0, 1, 0, 1 );
640  vk::ImageMemoryBarrier imageMemoryBarrier( sourceAccessMask,
641  destinationAccessMask,
642  oldImageLayout,
643  newImageLayout,
646  image,
647  imageSubresourceRange );
648  return commandBuffer.pipelineBarrier( sourceStage, destinationStage, {}, nullptr, nullptr, imageMemoryBarrier );
649  }
650 
651  void submitAndWait( vk::Device const & device, vk::Queue const & queue, vk::CommandBuffer const & commandBuffer )
652  {
653  vk::Fence fence = device.createFence( vk::FenceCreateInfo() );
654  queue.submit( vk::SubmitInfo( 0, nullptr, nullptr, 1, &commandBuffer ), fence );
655  while ( vk::Result::eTimeout == device.waitForFences( fence, VK_TRUE, vk::su::FenceTimeout ) )
656  ;
657  device.destroyFence( fence );
658  }
659 
660  void updateDescriptorSets( vk::Device const & device,
661  vk::DescriptorSet const & descriptorSet,
662  std::vector<std::tuple<vk::DescriptorType, vk::Buffer const &, vk::DeviceSize, vk::BufferView const &>> const & bufferData,
663  vk::su::TextureData const & textureData,
664  uint32_t bindingOffset )
665  {
666  std::vector<vk::DescriptorBufferInfo> bufferInfos;
667  bufferInfos.reserve( bufferData.size() );
668 
669  std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
670  writeDescriptorSets.reserve( bufferData.size() + 1 );
671  uint32_t dstBinding = bindingOffset;
672  for ( auto const & bd : bufferData )
673  {
674  bufferInfos.emplace_back( std::get<1>( bd ), 0, std::get<2>( bd ) );
675  writeDescriptorSets.emplace_back( descriptorSet, dstBinding++, 0, 1, std::get<0>( bd ), nullptr, &bufferInfos.back(), &std::get<3>( bd ) );
676  }
677 
678  vk::DescriptorImageInfo imageInfo( textureData.sampler, textureData.imageData->imageView, vk::ImageLayout::eShaderReadOnlyOptimal );
679  writeDescriptorSets.emplace_back( descriptorSet, dstBinding, 0, vk::DescriptorType::eCombinedImageSampler, imageInfo, nullptr, nullptr );
680 
681  device.updateDescriptorSets( writeDescriptorSets, nullptr );
682  }
683 
684  void updateDescriptorSets( vk::Device const & device,
685  vk::DescriptorSet const & descriptorSet,
686  std::vector<std::tuple<vk::DescriptorType, vk::Buffer const &, vk::DeviceSize, vk::BufferView const &>> const & bufferData,
687  std::vector<vk::su::TextureData> const & textureData,
688  uint32_t bindingOffset )
689  {
690  std::vector<vk::DescriptorBufferInfo> bufferInfos;
691  bufferInfos.reserve( bufferData.size() );
692 
693  std::vector<vk::WriteDescriptorSet> writeDescriptorSets;
694  writeDescriptorSets.reserve( bufferData.size() + ( textureData.empty() ? 0 : 1 ) );
695  uint32_t dstBinding = bindingOffset;
696  for ( auto const & bd : bufferData )
697  {
698  bufferInfos.emplace_back( std::get<1>( bd ), 0, std::get<2>( bd ) );
699  writeDescriptorSets.emplace_back( descriptorSet, dstBinding++, 0, 1, std::get<0>( bd ), nullptr, &bufferInfos.back(), &std::get<3>( bd ) );
700  }
701 
702  std::vector<vk::DescriptorImageInfo> imageInfos;
703  if ( !textureData.empty() )
704  {
705  imageInfos.reserve( textureData.size() );
706  for ( auto const & td : textureData )
707  {
708  imageInfos.emplace_back( td.sampler, td.imageData->imageView, vk::ImageLayout::eShaderReadOnlyOptimal );
709  }
710  writeDescriptorSets.emplace_back( descriptorSet,
711  dstBinding,
712  0,
713  checked_cast<uint32_t>( imageInfos.size() ),
715  imageInfos.data(),
716  nullptr,
717  nullptr );
718  }
719 
720  device.updateDescriptorSets( writeDescriptorSets, nullptr );
721  }
722 
724  vk::Device const & device,
725  vk::DeviceSize size,
726  vk::BufferUsageFlags usage,
727  vk::MemoryPropertyFlags propertyFlags )
728 #if !defined( NDEBUG )
729  : m_size( size ), m_usage( usage ), m_propertyFlags( propertyFlags )
730 #endif
731  {
732  buffer = device.createBuffer( vk::BufferCreateInfo( vk::BufferCreateFlags(), size, usage ) );
733  deviceMemory = vk::su::allocateDeviceMemory( device, physicalDevice.getMemoryProperties(), device.getBufferMemoryRequirements( buffer ), propertyFlags );
734  device.bindBufferMemory( buffer, deviceMemory, 0 );
735  }
736 
737  DepthBufferData::DepthBufferData( vk::PhysicalDevice const & physicalDevice, vk::Device const & device, vk::Format format, vk::Extent2D const & extent )
738  : ImageData( physicalDevice,
739  device,
740  format,
741  extent,
747  {
748  }
749 
750  ImageData::ImageData( vk::PhysicalDevice const & physicalDevice,
751  vk::Device const & device,
752  vk::Format format_,
753  vk::Extent2D const & extent,
754  vk::ImageTiling tiling,
755  vk::ImageUsageFlags usage,
756  vk::ImageLayout initialLayout,
757  vk::MemoryPropertyFlags memoryProperties,
758  vk::ImageAspectFlags aspectMask )
759  : format( format_ )
760  {
761  vk::ImageCreateInfo imageCreateInfo( vk::ImageCreateFlags(),
763  format,
764  vk::Extent3D( extent, 1 ),
765  1,
766  1,
768  tiling,
771  {},
772  initialLayout );
773  image = device.createImage( imageCreateInfo );
774 
775  deviceMemory = vk::su::allocateDeviceMemory( device, physicalDevice.getMemoryProperties(), device.getImageMemoryRequirements( image ), memoryProperties );
776 
777  device.bindImageMemory( image, deviceMemory, 0 );
778 
779  vk::ImageViewCreateInfo imageViewCreateInfo( {}, image, vk::ImageViewType::e2D, format, {}, { aspectMask, 0, 1, 0, 1 } );
780  imageView = device.createImageView( imageViewCreateInfo );
781  }
782 
783  SurfaceData::SurfaceData( vk::Instance const & instance, std::string const & windowName, vk::Extent2D const & extent_ )
784  : extent( extent_ ), window( vk::su::createWindow( windowName, extent ) )
785  {
786  VkSurfaceKHR _surface;
787  VkResult err = glfwCreateWindowSurface( static_cast<VkInstance>( instance ), window.handle, nullptr, &_surface );
788  if ( err != VK_SUCCESS )
789  throw std::runtime_error( "Failed to create window!" );
790  surface = vk::SurfaceKHR( _surface );
791  }
792 
794  vk::Device const & device,
795  vk::SurfaceKHR const & surface,
796  vk::Extent2D const & extent,
797  vk::ImageUsageFlags usage,
798  vk::SwapchainKHR const & oldSwapChain,
799  uint32_t graphicsQueueFamilyIndex,
800  uint32_t presentQueueFamilyIndex )
801  {
802  vk::SurfaceFormatKHR surfaceFormat = vk::su::pickSurfaceFormat( physicalDevice.getSurfaceFormatsKHR( surface ) );
803  colorFormat = surfaceFormat.format;
804 
805  vk::SurfaceCapabilitiesKHR surfaceCapabilities = physicalDevice.getSurfaceCapabilitiesKHR( surface );
806  vk::Extent2D swapchainExtent;
807  if ( surfaceCapabilities.currentExtent.width == std::numeric_limits<uint32_t>::max() )
808  {
809  // If the surface size is undefined, the size is set to the size of the images requested.
810  swapchainExtent.width = clamp( extent.width, surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width );
811  swapchainExtent.height = clamp( extent.height, surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height );
812  }
813  else
814  {
815  // If the surface size is defined, the swap chain size must match
816  swapchainExtent = surfaceCapabilities.currentExtent;
817  }
820  : surfaceCapabilities.currentTransform;
821  vk::CompositeAlphaFlagBitsKHR compositeAlpha =
826  vk::PresentModeKHR presentMode = vk::su::pickPresentMode( physicalDevice.getSurfacePresentModesKHR( surface ) );
827  vk::SwapchainCreateInfoKHR swapChainCreateInfo( {},
828  surface,
829  vk::su::clamp( 3u, surfaceCapabilities.minImageCount, surfaceCapabilities.maxImageCount ),
830  colorFormat,
831  surfaceFormat.colorSpace,
832  swapchainExtent,
833  1,
834  usage,
836  {},
837  preTransform,
838  compositeAlpha,
839  presentMode,
840  true,
841  oldSwapChain );
842  if ( graphicsQueueFamilyIndex != presentQueueFamilyIndex )
843  {
844  uint32_t queueFamilyIndices[2] = { graphicsQueueFamilyIndex, presentQueueFamilyIndex };
845  // If the graphics and present queues are from different queue families, we either have to explicitly transfer
846  // ownership of images between the queues, or we have to create the swapchain with imageSharingMode as
847  // vk::SharingMode::eConcurrent
848  swapChainCreateInfo.imageSharingMode = vk::SharingMode::eConcurrent;
849  swapChainCreateInfo.queueFamilyIndexCount = 2;
850  swapChainCreateInfo.pQueueFamilyIndices = queueFamilyIndices;
851  }
852  swapChain = device.createSwapchainKHR( swapChainCreateInfo );
853 
855 
856  imageViews.reserve( images.size() );
857  vk::ImageViewCreateInfo imageViewCreateInfo( {}, {}, vk::ImageViewType::e2D, colorFormat, {}, { vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1 } );
858  for ( auto image : images )
859  {
860  imageViewCreateInfo.image = image;
861  imageViews.push_back( device.createImageView( imageViewCreateInfo ) );
862  }
863  }
864 
865  CheckerboardImageGenerator::CheckerboardImageGenerator( std::array<uint8_t, 3> const & rgb0, std::array<uint8_t, 3> const & rgb1 )
866  : m_rgb0( rgb0 ), m_rgb1( rgb1 )
867  {
868  }
869 
870  void CheckerboardImageGenerator::operator()( void * data, vk::Extent2D & extent ) const
871  {
872  // Checkerboard of 16x16 pixel squares
873  uint8_t * pImageMemory = static_cast<uint8_t *>( data );
874  for ( uint32_t row = 0; row < extent.height; row++ )
875  {
876  for ( uint32_t col = 0; col < extent.width; col++ )
877  {
878  std::array<uint8_t, 3> const & rgb = ( ( ( row & 0x10 ) == 0 ) ^ ( ( col & 0x10 ) == 0 ) ) ? m_rgb1 : m_rgb0;
879  pImageMemory[0] = rgb[0];
880  pImageMemory[1] = rgb[1];
881  pImageMemory[2] = rgb[2];
882  pImageMemory[3] = 255;
883  pImageMemory += 4;
884  }
885  }
886  }
887 
888  MonochromeImageGenerator::MonochromeImageGenerator( std::array<unsigned char, 3> const & rgb ) : m_rgb( rgb ) {}
889 
890  void MonochromeImageGenerator::operator()( void * data, vk::Extent2D const & extent ) const
891  {
892  // fill in with the monochrome color
893  unsigned char * pImageMemory = static_cast<unsigned char *>( data );
894  for ( uint32_t row = 0; row < extent.height; row++ )
895  {
896  for ( uint32_t col = 0; col < extent.width; col++ )
897  {
898  pImageMemory[0] = m_rgb[0];
899  pImageMemory[1] = m_rgb[1];
900  pImageMemory[2] = m_rgb[2];
901  pImageMemory[3] = 255;
902  pImageMemory += 4;
903  }
904  }
905  }
906 
907  PixelsImageGenerator::PixelsImageGenerator( vk::Extent2D const & extent, size_t channels, unsigned char const * pixels )
908  : m_extent( extent ), m_channels( channels ), m_pixels( pixels )
909  {
910  assert( m_channels == 4 );
911  }
912 
913  void PixelsImageGenerator::operator()( void * data, vk::Extent2D const & extent ) const
914  {
915  assert( extent == m_extent );
916  memcpy( data, m_pixels, extent.width * extent.height * m_channels );
917  }
918 
920  vk::Device const & device,
921  vk::Extent2D const & extent_,
922  vk::ImageUsageFlags usageFlags,
923  vk::FormatFeatureFlags formatFeatureFlags,
924  bool anisotropyEnable,
925  bool forceStaging )
926  : format( vk::Format::eR8G8B8A8Unorm ), extent( extent_ )
927  {
928  vk::FormatProperties formatProperties = physicalDevice.getFormatProperties( format );
929 
930  formatFeatureFlags |= vk::FormatFeatureFlagBits::eSampledImage;
931  needsStaging = forceStaging || ( ( formatProperties.linearTilingFeatures & formatFeatureFlags ) != formatFeatureFlags );
932  vk::ImageTiling imageTiling;
933  vk::ImageLayout initialLayout;
934  vk::MemoryPropertyFlags requirements;
935  if ( needsStaging )
936  {
937  assert( ( formatProperties.optimalTilingFeatures & formatFeatureFlags ) == formatFeatureFlags );
939  std::unique_ptr<BufferData>( new BufferData( physicalDevice, device, extent.width * extent.height * 4, vk::BufferUsageFlagBits::eTransferSrc ) );
940  imageTiling = vk::ImageTiling::eOptimal;
942  initialLayout = vk::ImageLayout::eUndefined;
943  }
944  else
945  {
946  imageTiling = vk::ImageTiling::eLinear;
947  initialLayout = vk::ImageLayout::ePreinitialized;
949  }
950  imageData = std::unique_ptr<ImageData>( new ImageData( physicalDevice,
951  device,
952  format,
953  extent,
954  imageTiling,
956  initialLayout,
957  requirements,
959 
967  0.0f,
968  anisotropyEnable,
969  16.0f,
970  false,
972  0.0f,
973  0.0f,
975  }
976 
977  UUID::UUID( uint8_t const data[VK_UUID_SIZE] )
978  {
979  memcpy( m_data, data, VK_UUID_SIZE * sizeof( uint8_t ) );
980  }
981 
982  WindowData::WindowData( GLFWwindow * wnd, std::string const & name, vk::Extent2D const & extent ) : handle{ wnd }, name{ name }, extent{ extent } {}
983 
984  WindowData::WindowData( WindowData && other ) : handle{}, name{}, extent{}
985  {
986  std::swap( handle, other.handle );
987  std::swap( name, other.name );
988  std::swap( extent, other.extent );
989  }
990 
992  {
993  glfwDestroyWindow( handle );
994  }
995 
996  WindowData createWindow( std::string const & windowName, vk::Extent2D const & extent )
997  {
998  struct glfwContext
999  {
1000  glfwContext()
1001  {
1002  glfwInit();
1003  glfwSetErrorCallback(
1004  []( int error, const char * msg )
1005  {
1006  std::cerr << "glfw: "
1007  << "(" << error << ") " << msg << std::endl;
1008  } );
1009  }
1010 
1011  ~glfwContext()
1012  {
1013  glfwTerminate();
1014  }
1015  };
1016 
1017  static auto glfwCtx = glfwContext();
1018  (void)glfwCtx;
1019 
1020  glfwWindowHint( GLFW_CLIENT_API, GLFW_NO_API );
1021  GLFWwindow * window = glfwCreateWindow( extent.width, extent.height, windowName.c_str(), nullptr, nullptr );
1022  return WindowData( window, windowName, extent );
1023  }
1024 
1026  {
1027  return { {},
1032  }
1033 
1034 #if defined( NDEBUG )
1036 #else
1038 #endif
1040  std::vector<char const *> const & layers,
1041  std::vector<char const *> const & extensions )
1042  {
1043 #if defined( NDEBUG )
1044  // in non-debug mode just use the InstanceCreateInfo for instance creation
1045  vk::StructureChain<vk::InstanceCreateInfo> instanceCreateInfo( { {}, &applicationInfo, layers, extensions } );
1046 #else
1047  // in debug mode, addionally use the debugUtilsMessengerCallback in instance creation!
1053  { {}, &applicationInfo, layers, extensions }, { {}, severityFlags, messageTypeFlags, &vk::su::debugUtilsMessengerCallback } );
1054 #endif
1055  return instanceCreateInfo;
1056  }
1057 
1058  } // namespace su
1059 } // namespace vk
1060 
1061 std::ostream & operator<<( std::ostream & os, vk::su::UUID const & uuid )
1062 {
1063  os << std::setfill( '0' ) << std::hex;
1064  for ( uint32_t j = 0; j < VK_UUID_SIZE; ++j )
1065  {
1066  os << std::setw( 2 ) << static_cast<uint32_t>( uuid.m_data[j] );
1067  if ( j == 3 || j == 5 || j == 7 || j == 9 )
1068  {
1069  std::cout << '-';
1070  }
1071  }
1072  os << std::setfill( ' ' ) << std::dec;
1073  return os;
1074 }
void cout(vk::SurfaceCapabilitiesKHR const &surfaceCapabilities)
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
VULKAN_HPP_NODISCARD ResultValue< vk::Pipeline > createGraphicsPipeline(vk::PipelineCache pipelineCache, const vk::GraphicsPipelineCreateInfo &createInfo, Optional< const vk::AllocationCallbacks > allocator VULKAN_HPP_DEFAULT_ARGUMENT_NULLPTR_ASSIGNMENT, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const
void updateDescriptorSets(uint32_t descriptorWriteCount, const vk::WriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount, const vk::CopyDescriptorSet *pDescriptorCopies, 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_WHEN_NO_EXCEPTIONS ResultValueType< void >::type bindBufferMemory(vk::Buffer buffer, vk::DeviceMemory memory, vk::DeviceSize memoryOffset, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const
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
VULKAN_HPP_NODISCARD Result createRenderPass(const vk::RenderPassCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::RenderPass *pRenderPass, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createSampler(const vk::SamplerCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Sampler *pSampler, 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 createBuffer(const vk::BufferCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Buffer *pBuffer, Dispatch const &d VULKAN_HPP_DEFAULT_DISPATCHER_ASSIGNMENT) const VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD Result createDescriptorSetLayout(const vk::DescriptorSetLayoutCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::DescriptorSetLayout *pSetLayout, 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 getBufferMemoryRequirements(vk::Buffer buffer, vk::MemoryRequirements *pMemoryRequirements, 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 createFramebuffer(const vk::FramebufferCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Framebuffer *pFramebuffer, 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
VULKAN_HPP_NODISCARD Result createDescriptorPool(const vk::DescriptorPoolCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::DescriptorPool *pDescriptorPool, 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 getFormatProperties(vk::Format format, vk::FormatProperties *pFormatProperties, 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 getSurfacePresentModesKHR(vk::SurfaceKHR surface, uint32_t *pPresentModeCount, vk::PresentModeKHR *pPresentModes, 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 createDevice(const vk::DeviceCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Device *pDevice, 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
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
CheckerboardImageGenerator(std::array< uint8_t, 3 > const &rgb0={ { 0, 0, 0 } }, std::array< uint8_t, 3 > const &rgb1={ { 255, 255, 255 } })
Definition: utils.cpp:865
void operator()(void *data, vk::Extent2D &extent) const
Definition: utils.cpp:870
MonochromeImageGenerator(std::array< unsigned char, 3 > const &rgb)
Definition: utils.cpp:888
void operator()(void *data, vk::Extent2D const &extent) const
Definition: utils.cpp:890
void operator()(void *data, vk::Extent2D const &extent) const
Definition: utils.cpp:913
PixelsImageGenerator(vk::Extent2D const &extent, size_t channels, unsigned char const *pixels)
Definition: utils.cpp:907
uint32_t findGraphicsQueueFamilyIndex(std::vector< vk::QueueFamilyProperties > const &queueFamilyProperties)
Definition: utils.cpp:409
std::vector< vk::Framebuffer > createFramebuffers(vk::Device const &device, vk::RenderPass &renderPass, std::vector< vk::ImageView > const &imageViews, vk::ImageView const &depthImageView, vk::Extent2D const &extent)
Definition: utils.cpp:111
vk::DebugUtilsMessengerCreateInfoEXT makeDebugUtilsMessengerCreateInfoEXT()
Definition: utils.cpp:1025
vk::DeviceMemory allocateDeviceMemory(vk::Device const &device, vk::PhysicalDeviceMemoryProperties const &memoryProperties, vk::MemoryRequirements const &memoryRequirements, vk::MemoryPropertyFlags memoryPropertyFlags)
Definition: utils.cpp:44
vk::RenderPass createRenderPass(vk::Device const &device, vk::Format colorFormat, vk::Format depthFormat, vk::AttachmentLoadOp loadOp, vk::ImageLayout colorFinalLayout)
Definition: utils.cpp:314
vk::Pipeline createGraphicsPipeline(vk::Device const &device, vk::PipelineCache const &pipelineCache, std::pair< vk::ShaderModule, vk::SpecializationInfo const * > const &vertexShaderData, std::pair< vk::ShaderModule, vk::SpecializationInfo const * > const &fragmentShaderData, uint32_t vertexStride, std::vector< std::pair< vk::Format, uint32_t >> const &vertexInputAttributeFormatOffset, vk::FrontFace frontFace, bool depthBuffered, vk::PipelineLayout const &pipelineLayout, vk::RenderPass const &renderPass)
Definition: utils.cpp:133
vk::StructureChain< vk::InstanceCreateInfo, vk::DebugUtilsMessengerCreateInfoEXT > makeInstanceCreateInfoChain(vk::ApplicationInfo const &applicationInfo, std::vector< char const * > const &layers, std::vector< char const * > const &extensions)
Definition: utils.cpp:1039
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
VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsMessengerCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes, VkDebugUtilsMessengerCallbackDataEXT const *pCallbackData, void *)
Definition: utils.cpp:351
vk::DescriptorSetLayout createDescriptorSetLayout(vk::Device const &device, std::vector< std::tuple< vk::DescriptorType, uint32_t, vk::ShaderStageFlags >> const &bindingData, vk::DescriptorSetLayoutCreateFlags flags)
Definition: utils.cpp:73
WindowData createWindow(std::string const &windowName, vk::Extent2D const &extent)
Definition: utils.cpp:996
std::vector< char const * > gatherLayers(std::vector< std::string > const &layers, std::vector< vk::LayerProperties > const &layerProperties)
Definition: utils.cpp:252
std::pair< uint32_t, uint32_t > findGraphicsAndPresentQueueFamilyIndex(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR const &surface)
Definition: utils.cpp:420
void submitAndWait(vk::Device const &device, vk::Queue const &queue, vk::CommandBuffer const &commandBuffer)
Definition: utils.cpp:651
std::vector< char const * > gatherExtensions(std::vector< std::string > const &extensions, std::vector< vk::ExtensionProperties > const &extensionProperties)
Definition: utils.cpp:224
std::vector< std::string > getInstanceExtensions()
Definition: utils.cpp:477
void updateDescriptorSets(vk::Device const &device, vk::DescriptorSet const &descriptorSet, std::vector< std::tuple< vk::DescriptorType, vk::Buffer const &, vk::DeviceSize, vk::BufferView const & >> const &bufferData, vk::su::TextureData const &textureData, uint32_t bindingOffset)
Definition: utils.cpp:660
vk::DescriptorPool createDescriptorPool(vk::Device const &device, std::vector< vk::DescriptorPoolSize > const &poolSizes)
Definition: utils.cpp:62
bool contains(std::vector< vk::ExtensionProperties > const &extensionProperties, std::string const &extensionName)
Definition: utils.cpp:54
vk::Format pickDepthFormat(vk::PhysicalDevice const &physicalDevice)
Definition: utils.cpp:505
vk::PresentModeKHR pickPresentMode(std::vector< vk::PresentModeKHR > const &presentModes)
Definition: utils.cpp:520
vk::SurfaceFormatKHR pickSurfaceFormat(std::vector< vk::SurfaceFormatKHR > const &formats)
Definition: utils.cpp:539
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
Definition: vulkan.cppm:23
VULKAN_HPP_CONSTEXPR_INLINE uint32_t False
Definition: vulkan.hpp:6771
@ eDepthStencilAttachmentOptimal
VULKAN_HPP_INLINE void swap(UniqueHandle< Type, Dispatch > &lhs, UniqueHandle< Type, Dispatch > &rhs) VULKAN_HPP_NOEXCEPT
Definition: vulkan.hpp:997
SurfaceTransformFlagBitsKHR
VULKAN_HPP_INLINE std::string to_string(FormatFeatureFlags value)
ImageUsageFlagBits
CompositeAlphaFlagBitsKHR
ImageAspectFlagBits
MemoryPropertyFlagBits
VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE Result enumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pPropertyCount, vk::ExtensionProperties *pProperties, Dispatch const &d) VULKAN_HPP_NOEXCEPT
VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE Result createInstance(const vk::InstanceCreateInfo *pCreateInfo, const vk::AllocationCallbacks *pAllocator, vk::Instance *pInstance, Dispatch const &d) VULKAN_HPP_NOEXCEPT
uint64_t DeviceSize
Definition: vulkan.hpp:6122
PresentModeKHR
AttachmentLoadOp
VULKAN_HPP_NODISCARD VULKAN_HPP_INLINE Result enumerateInstanceLayerProperties(uint32_t *pPropertyCount, vk::LayerProperties *pProperties, Dispatch const &d) VULKAN_HPP_NOEXCEPT
const char * pLabelName
const VkDebugUtilsLabelEXT * pCmdBufLabels
const VkDebugUtilsLabelEXT * pQueueLabels
const VkDebugUtilsObjectNameInfoEXT * pObjects
vk::FormatFeatureFlags optimalTilingFeatures
vk::FormatFeatureFlags linearTilingFeatures
vk::ArrayWrapper1D< vk::MemoryType, VK_MAX_MEMORY_TYPES > memoryTypes
PipelineVertexInputStateCreateInfo & setVertexAttributeDescriptions(vk::ArrayProxyNoTemporaries< const vk::VertexInputAttributeDescription > const &vertexAttributeDescriptions_) VULKAN_HPP_NOEXCEPT
PipelineVertexInputStateCreateInfo & setVertexBindingDescriptions(vk::ArrayProxyNoTemporaries< const vk::VertexInputBindingDescription > const &vertexBindingDescriptions_) VULKAN_HPP_NOEXCEPT
vk::SurfaceTransformFlagsKHR supportedTransforms
vk::SurfaceTransformFlagBitsKHR currentTransform
vk::CompositeAlphaFlagsKHR supportedCompositeAlpha
vk::ColorSpaceKHR colorSpace
BufferData(vk::PhysicalDevice const &physicalDevice, vk::Device const &device, vk::DeviceSize size, vk::BufferUsageFlags usage, vk::MemoryPropertyFlags propertyFlags=vk::MemoryPropertyFlagBits::eHostVisible|vk::MemoryPropertyFlagBits::eHostCoherent)
Definition: utils.cpp:723
DepthBufferData(vk::PhysicalDevice const &physicalDevice, vk::Device const &device, vk::Format format, vk::Extent2D const &extent)
Definition: utils.cpp:737
vk::DeviceMemory deviceMemory
Definition: utils.hpp:190
vk::ImageView imageView
Definition: utils.hpp:191
ImageData(vk::PhysicalDevice const &physicalDevice, vk::Device const &device, vk::Format format, vk::Extent2D const &extent, vk::ImageTiling tiling, vk::ImageUsageFlags usage, vk::ImageLayout initialLayout, vk::MemoryPropertyFlags memoryProperties, vk::ImageAspectFlags aspectMask)
Definition: utils.cpp:750
vk::Image image
Definition: utils.hpp:189
vk::Format format
Definition: utils.hpp:188
SurfaceData(vk::Instance const &instance, std::string const &windowName, vk::Extent2D const &extent)
Definition: utils.cpp:783
WindowData window
Definition: utils.hpp:204
vk::SurfaceKHR surface
Definition: utils.hpp:205
vk::SwapchainKHR swapChain
Definition: utils.hpp:231
std::vector< vk::ImageView > imageViews
Definition: utils.hpp:233
vk::Format colorFormat
Definition: utils.hpp:230
SwapChainData(vk::PhysicalDevice const &physicalDevice, vk::Device const &device, vk::SurfaceKHR const &surface, vk::Extent2D const &extent, vk::ImageUsageFlags usage, vk::SwapchainKHR const &oldSwapChain, uint32_t graphicsFamilyIndex, uint32_t presentFamilyIndex)
Definition: utils.cpp:793
std::vector< vk::Image > images
Definition: utils.hpp:232
std::unique_ptr< BufferData > stagingBufferData
Definition: utils.hpp:327
vk::Extent2D extent
Definition: utils.hpp:325
vk::Format format
Definition: utils.hpp:324
vk::Sampler sampler
Definition: utils.hpp:329
std::unique_ptr< ImageData > imageData
Definition: utils.hpp:328
TextureData(vk::PhysicalDevice const &physicalDevice, vk::Device const &device, vk::Extent2D const &extent_={ 256, 256 }, vk::ImageUsageFlags usageFlags={}, vk::FormatFeatureFlags formatFeatureFlags={}, bool anisotropyEnable=false, bool forceStaging=false)
Definition: utils.cpp:919
UUID(uint8_t const data[VK_UUID_SIZE])
Definition: utils.cpp:977
uint8_t m_data[VK_UUID_SIZE]
Definition: utils.hpp:337
GLFWwindow * handle
Definition: utils.hpp:87
vk::Extent2D extent
Definition: utils.hpp:89
WindowData(GLFWwindow *wnd, std::string const &name, vk::Extent2D const &extent)
Definition: utils.cpp:982
std::string name
Definition: utils.hpp:88
~WindowData() noexcept
Definition: utils.cpp:991
std::ostream & operator<<(std::ostream &os, vk::su::UUID const &uuid)
Definition: utils.cpp:1061
uint64_t VkSurfaceKHR
Definition: vulkan_core.h:7513
#define VK_TRUE
Definition: vulkan_core.h:131
#define VK_KHR_SURFACE_EXTENSION_NAME
Definition: vulkan_core.h:7515
struct VkInstance_T * VkInstance
Definition: vulkan_core.h:101
VkFlags VkDebugUtilsMessageTypeFlagsEXT
#define VK_UUID_SIZE
Definition: vulkan_core.h:135
#define VK_EXT_DEBUG_UTILS_EXTENSION_NAME
VkResult
Definition: vulkan_core.h:140
@ VK_SUCCESS
Definition: vulkan_core.h:141
uint32_t VkBool32
Definition: vulkan_core.h:94
#define VK_KHR_SWAPCHAIN_EXTENSION_NAME
Definition: vulkan_core.h:7630
#define VK_QUEUE_FAMILY_IGNORED
Definition: vulkan_core.h:127
VkDebugUtilsMessageSeverityFlagBitsEXT
#define VULKAN_HPP_DEFAULT_DISPATCHER
#define VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE