GCC Code Coverage Report


Directory: ./
File: src/tide/dependencies/vkbootstrap/VkBootstrap.h
Date: 2023-04-27 00:55:30
Exec Total Coverage
Lines: 0 3 0.0%
Functions: 0 64 0.0%
Branches: 0 2 0.0%

Line Branch Exec Source
1 /*
2 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
3 * documentation files (the “Software”), to deal in the Software without restriction, including without
4 * limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
5 * of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 *
7 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 *
9 * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
10 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
11 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
12 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13 *
14 * Copyright © 2020 Charles Giessen (charles@lunarg.com)
15 */
16
17 #pragma once
18
19 #include <cassert>
20
21 #include <vector>
22 #include <system_error>
23
24 #include <vulkan/vulkan.h>
25
26
27 namespace vkb {
28
29 namespace detail {
30
31 struct Error {
32 std::error_code type;
33 VkResult vk_result = VK_SUCCESS; // optional error value if a vulkan call failed
34 };
35
36 template <typename T> class Result {
37 public:
38 Result (const T& value) : m_value{ value }, m_init{ true } {}
39 Result (T&& value) : m_value{ std::move (value) }, m_init{ true } {}
40
41 Result (Error error) : m_error{ error }, m_init{ false } {}
42
43 Result (std::error_code error_code, VkResult result = VK_SUCCESS)
44 : m_error{ error_code, result }, m_init{ false } {}
45
46 ~Result () { destroy (); }
47 Result (Result const& expected) : m_init (expected.m_init) {
48 if (m_init)
49 new (&m_value) T{ expected.m_value };
50 else
51 m_error = expected.m_error;
52 }
53 Result (Result&& expected) : m_init (expected.m_init) {
54 if (m_init)
55 new (&m_value) T{ std::move (expected.m_value) };
56 else
57 m_error = std::move (expected.m_error);
58 expected.destroy ();
59 }
60
61 Result& operator= (const T& expect) {
62 destroy ();
63 m_init = true;
64 new (&m_value) T{ expect };
65 return *this;
66 }
67 Result& operator= (T&& expect) {
68 destroy ();
69 m_init = true;
70 new (&m_value) T{ std::move (expect) };
71 return *this;
72 }
73 Result& operator= (const Error& error) {
74 destroy ();
75 m_init = false;
76 m_error = error;
77 return *this;
78 }
79 Result& operator= (Error&& error) {
80 destroy ();
81 m_init = false;
82 m_error = error;
83 return *this;
84 }
85 // clang-format off
86 const T* operator-> () const { assert (m_init); return &m_value; }
87 T* operator-> () { assert (m_init); return &m_value; }
88 const T& operator* () const& { assert (m_init); return m_value; }
89 T& operator* () & { assert (m_init); return m_value; }
90 T&& operator* () && { assert (m_init); return std::move (m_value); }
91 const T& value () const& { assert (m_init); return m_value; }
92 T& value () & { assert (m_init); return m_value; }
93 const T&& value () const&& { assert (m_init); return std::move (m_value); }
94 T&& value () && { assert (m_init); return std::move (m_value); }
95
96 std::error_code error() const { assert (!m_init); return m_error.type; }
97 VkResult vk_result() const { assert (!m_init); return m_error.vk_result; }
98 // clang-format on
99
100
101 bool has_value () const { return m_init; }
102 explicit operator bool () const { return m_init; }
103
104 private:
105 void destroy () {
106 if (m_init) m_value.~T ();
107 }
108 union {
109 T m_value;
110 Error m_error;
111 };
112 bool m_init;
113 };
114
115 } // namespace detail
116
117 enum class InstanceError {
118 vulkan_unavailable,
119 vulkan_version_unavailable,
120 vulkan_version_1_1_unavailable,
121 vulkan_version_1_2_unavailable,
122 failed_create_instance,
123 failed_create_debug_messenger,
124 requested_layers_not_present,
125 requested_extensions_not_present,
126 windowing_extensions_not_present,
127 };
128 enum class PhysicalDeviceError {
129 no_surface_provided,
130 failed_enumerate_physical_devices,
131 no_physical_devices_found,
132 no_suitable_device,
133 };
134 enum class QueueError {
135 present_unavailable,
136 graphics_unavailable,
137 compute_unavailable,
138 transfer_unavailable,
139 queue_index_out_of_range,
140 invalid_queue_family_index
141 };
142 enum class DeviceError {
143 failed_create_device,
144 };
145 enum class SwapchainError {
146 surface_handle_not_provided,
147 failed_query_surface_support_details,
148 failed_create_swapchain,
149 failed_get_swapchain_images,
150 failed_create_swapchain_image_views,
151 };
152
153 std::error_code make_error_code (InstanceError instance_error);
154 std::error_code make_error_code (PhysicalDeviceError physical_device_error);
155 std::error_code make_error_code (QueueError queue_error);
156 std::error_code make_error_code (DeviceError device_error);
157 std::error_code make_error_code (SwapchainError swapchain_error);
158
159 const char* to_string_message_severity (VkDebugUtilsMessageSeverityFlagBitsEXT s);
160 const char* to_string_message_type (VkDebugUtilsMessageTypeFlagsEXT s);
161
162 const char* to_string (InstanceError err);
163 const char* to_string (PhysicalDeviceError err);
164 const char* to_string (QueueError err);
165 const char* to_string (DeviceError err);
166 const char* to_string (SwapchainError err);
167
168 // Gathers useful information about the available vulkan capabilities, like layers and instance extensions.
169 // Use this for enabling features conditionally, ie if you would like an extension but can use a fallback if
170 // it isn't supported but need to know if support is available first.
171 struct SystemInfo {
172 private:
173 SystemInfo ();
174
175 public:
176 // Use get_system_info to create a SystemInfo struct. This is because loading vulkan could fail.
177 static detail::Result<SystemInfo> get_system_info ();
178 static detail::Result<SystemInfo> get_system_info (PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr);
179
180 // Returns true if a layer is available
181 bool is_layer_available (const char* layer_name) const;
182 // Returns true if an extension is available
183 bool is_extension_available (const char* extension_name) const;
184
185 std::vector<VkLayerProperties> available_layers;
186 std::vector<VkExtensionProperties> available_extensions;
187 bool validation_layers_available = false;
188 bool debug_utils_available = false;
189 };
190
191
192 class InstanceBuilder;
193 class PhysicalDeviceSelector;
194
195 struct Instance {
196 VkInstance instance = VK_NULL_HANDLE;
197 VkDebugUtilsMessengerEXT debug_messenger = VK_NULL_HANDLE;
198 VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
199
200 PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr;
201
202 private:
203 bool headless = false;
204 uint32_t instance_version = VK_MAKE_VERSION (1, 0, 0);
205
206 friend class InstanceBuilder;
207 friend class PhysicalDeviceSelector;
208 };
209
210 void destroy_instance (Instance instance); // release instance resources
211
212 class InstanceBuilder {
213 public:
214 // Default constructor, will load vulkan.
215 explicit InstanceBuilder ();
216 // Optional: Can use your own PFN_vkGetInstanceProcAddr
217 explicit InstanceBuilder (PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr);
218
219 // Create a VkInstance. Return an error if it failed.
220 detail::Result<Instance> build () const;
221
222 // Sets the name of the application. Defaults to "" if none is provided.
223 InstanceBuilder& set_app_name (const char* app_name);
224 // Sets the name of the engine. Defaults to "" if none is provided.
225 InstanceBuilder& set_engine_name (const char* engine_name);
226 // Sets the (major, minor, patch) version of the application.
227 InstanceBuilder& set_app_version (uint32_t major, uint32_t minor, uint32_t patch = 0);
228 // Sets the (major, minor, patch) version of the engine.
229 InstanceBuilder& set_engine_version (uint32_t major, uint32_t minor, uint32_t patch = 0);
230 // Require a vulkan instance API version. Will fail to create if this version isn't available.
231 InstanceBuilder& require_api_version (uint32_t major, uint32_t minor, uint32_t patch = 0);
232 // Prefer a vulkan instance API version. If the desired version isn't available, it will use the highest version available.
233 InstanceBuilder& desire_api_version (uint32_t major, uint32_t minor, uint32_t patch = 0);
234
235 // Adds a layer to be enabled. Will fail to create an instance if the layer isn't available.
236 InstanceBuilder& enable_layer (const char* layer_name);
237 // Adds an extension to be enabled. Will fail to create an instance if the extension isn't available.
238 InstanceBuilder& enable_extension (const char* extension_name);
239
240 // Headless Mode does not load the required extensions for presentation. Defaults to true.
241 InstanceBuilder& set_headless (bool headless = true);
242
243 // Enables the validation layers. Will fail to create an instance if the validation layers aren't available.
244 InstanceBuilder& enable_validation_layers (bool require_validation = true);
245 // Checks if the validation layers are available and loads them if they are.
246 InstanceBuilder& request_validation_layers (bool enable_validation = true);
247
248 // Use a default debug callback that prints to standard out.
249 InstanceBuilder& use_default_debug_messenger ();
250 // Provide a user defined debug callback.
251 InstanceBuilder& set_debug_callback (PFN_vkDebugUtilsMessengerCallbackEXT callback);
252 // Set what message severity is needed to trigger the callback.
253 InstanceBuilder& set_debug_messenger_severity (VkDebugUtilsMessageSeverityFlagsEXT severity);
254 // Add a message severity to the list that triggers the callback.
255 InstanceBuilder& add_debug_messenger_severity (VkDebugUtilsMessageSeverityFlagsEXT severity);
256 // Set what message type triggers the callback.
257 InstanceBuilder& set_debug_messenger_type (VkDebugUtilsMessageTypeFlagsEXT type);
258 // Add a message type to the list of that triggers the callback.
259 InstanceBuilder& add_debug_messenger_type (VkDebugUtilsMessageTypeFlagsEXT type);
260
261 // Disable some validation checks.
262 // Checks: All, and Shaders
263 InstanceBuilder& add_validation_disable (VkValidationCheckEXT check);
264
265 // Enables optional parts of the validation layers.
266 // Parts: best practices, gpu assisted, and gpu assisted reserve binding slot.
267 InstanceBuilder& add_validation_feature_enable (VkValidationFeatureEnableEXT enable);
268
269 // Disables sections of the validation layers.
270 // Options: All, shaders, thread safety, api parameters, object lifetimes, core checks, and unique handles.
271 InstanceBuilder& add_validation_feature_disable (VkValidationFeatureDisableEXT disable);
272
273 // Provide custom allocation callbacks.
274 InstanceBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
275
276 private:
277 struct InstanceInfo {
278 // VkApplicationInfo
279 const char* app_name = nullptr;
280 const char* engine_name = nullptr;
281 uint32_t application_version = 0;
282 uint32_t engine_version = 0;
283 uint32_t required_api_version = VK_MAKE_VERSION (1, 0, 0);
284 uint32_t desired_api_version = VK_MAKE_VERSION (1, 0, 0);
285
286 // VkInstanceCreateInfo
287 std::vector<const char*> layers;
288 std::vector<const char*> extensions;
289 VkInstanceCreateFlags flags = 0;
290 std::vector<VkBaseOutStructure*> pNext_elements;
291
292 // debug callback
293 PFN_vkDebugUtilsMessengerCallbackEXT debug_callback = nullptr;
294 VkDebugUtilsMessageSeverityFlagsEXT debug_message_severity =
295 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
296 VkDebugUtilsMessageTypeFlagsEXT debug_message_type =
297 VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
298 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
299
300 // validation features
301 std::vector<VkValidationCheckEXT> disabled_validation_checks;
302 std::vector<VkValidationFeatureEnableEXT> enabled_validation_features;
303 std::vector<VkValidationFeatureDisableEXT> disabled_validation_features;
304
305 // Custom allocator
306 VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
307
308 bool request_validation_layers = false;
309 bool enable_validation_layers = false;
310 bool use_debug_messenger = false;
311 bool headless_context = false;
312
313 PFN_vkGetInstanceProcAddr fp_vkGetInstanceProcAddr = nullptr;
314 } info;
315 };
316
317 VKAPI_ATTR VkBool32 VKAPI_CALL default_debug_callback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
318 VkDebugUtilsMessageTypeFlagsEXT messageType,
319 const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
320 void* pUserData);
321
322 void destroy_debug_utils_messenger(VkInstance const instance, VkDebugUtilsMessengerEXT const messenger, VkAllocationCallbacks* allocation_callbacks = nullptr);
323
324 // ---- Physical Device ---- //
325 class PhysicalDeviceSelector;
326 class DeviceBuilder;
327
328 struct PhysicalDevice {
329 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
330 VkSurfaceKHR surface = VK_NULL_HANDLE;
331
332 VkPhysicalDeviceFeatures features{};
333 VkPhysicalDeviceProperties properties{};
334 VkPhysicalDeviceMemoryProperties memory_properties{};
335
336 // Has a queue family that supports compute operations but not graphics nor transfer.
337 bool has_dedicated_compute_queue () const;
338 // Has a queue family that supports transfer operations but not graphics nor compute.
339 bool has_dedicated_transfer_queue () const;
340
341 // Has a queue family that supports transfer operations but not graphics.
342 bool has_separate_compute_queue () const;
343 // Has a queue family that supports transfer operations but not graphics.
344 bool has_separate_transfer_queue () const;
345
346 // Advanced: Get the VkQueueFamilyProperties of the device if special queue setup is needed
347 std::vector<VkQueueFamilyProperties> get_queue_families () const;
348
349 private:
350 std::vector<const char*> extensions_to_enable;
351 std::vector<VkQueueFamilyProperties> queue_families;
352 bool defer_surface_initialization = false;
353 friend class PhysicalDeviceSelector;
354 friend class DeviceBuilder;
355 };
356
357 enum class PreferredDeviceType {
358 other = 0,
359 integrated = 1,
360 discrete = 2,
361 virtual_gpu = 3,
362 cpu = 4
363 };
364
365 class PhysicalDeviceSelector {
366 public:
367 // Requires a vkb::Instance to construct, needed to pass instance creation info.
368 explicit PhysicalDeviceSelector (Instance const& instance);
369
370 detail::Result<PhysicalDevice> select () const;
371
372 // Set the surface in which the physical device should render to.
373 PhysicalDeviceSelector& set_surface (VkSurfaceKHR surface);
374 // Set the desired physical device type to select. Defaults to PreferredDeviceType::discrete.
375 PhysicalDeviceSelector& prefer_gpu_device_type (PreferredDeviceType type = PreferredDeviceType::discrete);
376 // Allow selection of a gpu device type that isn't the preferred physical device type. Defaults to true.
377 PhysicalDeviceSelector& allow_any_gpu_device_type (bool allow_any_type = true);
378
379 // Require that a physical device supports presentation. Defaults to true.
380 PhysicalDeviceSelector& require_present (bool require = true);
381
382 // Require a queue family that supports compute operations but not graphics nor transfer.
383 PhysicalDeviceSelector& require_dedicated_compute_queue ();
384 // Require a queue family that supports transfer operations but not graphics nor compute.
385 PhysicalDeviceSelector& require_dedicated_transfer_queue ();
386
387 // Require a queue family that supports compute operations but not graphics.
388 PhysicalDeviceSelector& require_separate_compute_queue ();
389 // Require a queue family that supports transfer operations but not graphics.
390 PhysicalDeviceSelector& require_separate_transfer_queue ();
391
392 // Require a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available.
393 PhysicalDeviceSelector& required_device_memory_size (VkDeviceSize size);
394 // Prefer a memory heap from VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT with `size` memory available.
395 PhysicalDeviceSelector& desired_device_memory_size (VkDeviceSize size);
396
397 // Require a physical device which supports a specific extension.
398 PhysicalDeviceSelector& add_required_extension (const char* extension);
399 // Require a physical device which supports a set of extensions.
400 PhysicalDeviceSelector& add_required_extensions (std::vector<const char*> extensions);
401
402 // Prefer a physical device which supports a specific extension.
403 PhysicalDeviceSelector& add_desired_extension (const char* extension);
404 // Prefer a physical device which supports a set of extensions.
405 PhysicalDeviceSelector& add_desired_extensions (std::vector<const char*> extensions);
406
407 // Prefer a physical device that supports a (major, minor) version of vulkan.
408 PhysicalDeviceSelector& set_desired_version (uint32_t major, uint32_t minor);
409 // Require a physical device that supports a (major, minor) version of vulkan.
410 PhysicalDeviceSelector& set_minimum_version (uint32_t major, uint32_t minor);
411
412 // Require a physical device which supports the features in VkPhysicalDeviceFeatures.
413 PhysicalDeviceSelector& set_required_features (VkPhysicalDeviceFeatures features);
414
415 // Used when surface creation happens after physical device selection.
416 // Warning: This disables checking if the physical device supports a given surface.
417 PhysicalDeviceSelector& defer_surface_initialization ();
418
419 // Ignore all criteria and choose the first physical device that is available.
420 // Only use when: The first gpu in the list may be set by global user preferences and an application may wish to respect it.
421 PhysicalDeviceSelector& select_first_device_unconditionally (bool unconditionally = true);
422
423 private:
424 struct SystemInfo {
425 VkInstance instance = VK_NULL_HANDLE;
426 VkSurfaceKHR surface = VK_NULL_HANDLE;
427 bool headless = false;
428 } system_info;
429
430 struct PhysicalDeviceDesc {
431 VkPhysicalDevice phys_device = VK_NULL_HANDLE;
432 std::vector<VkQueueFamilyProperties> queue_families;
433
434 VkPhysicalDeviceFeatures device_features{};
435 VkPhysicalDeviceProperties device_properties{};
436 VkPhysicalDeviceMemoryProperties mem_properties{};
437 };
438 PhysicalDeviceDesc populate_device_details (VkPhysicalDevice phys_device) const;
439
440 struct SelectionCriteria {
441 PreferredDeviceType preferred_type = PreferredDeviceType::discrete;
442 bool allow_any_type = true;
443 bool require_present = true;
444 bool require_dedicated_transfer_queue = false;
445 bool require_dedicated_compute_queue = false;
446 bool require_separate_transfer_queue = false;
447 bool require_separate_compute_queue = false;
448 VkDeviceSize required_mem_size = 0;
449 VkDeviceSize desired_mem_size = 0;
450
451 std::vector<const char*> required_extensions;
452 std::vector<const char*> desired_extensions;
453
454 uint32_t required_version = VK_MAKE_VERSION (1, 0, 0);
455 uint32_t desired_version = VK_MAKE_VERSION (1, 0, 0);
456
457 VkPhysicalDeviceFeatures required_features{};
458
459 bool defer_surface_initialization = false;
460 bool use_first_gpu_unconditionally = false;
461 } criteria;
462
463 enum class Suitable { yes, partial, no };
464
465 Suitable is_device_suitable (PhysicalDeviceDesc phys_device) const;
466 };
467
468 // ---- Queue ---- //
469 enum class QueueType { present, graphics, compute, transfer };
470
471 // ---- Device ---- //
472
473 struct Device {
474 VkDevice device = VK_NULL_HANDLE;
475 PhysicalDevice physical_device;
476 VkSurfaceKHR surface = VK_NULL_HANDLE;
477 std::vector<VkQueueFamilyProperties> queue_families;
478 VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
479
480 detail::Result<uint32_t> get_queue_index (QueueType type) const;
481 // Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue index
482 detail::Result<uint32_t> get_dedicated_queue_index (QueueType type) const;
483
484 detail::Result<VkQueue> get_queue (QueueType type) const;
485 // Only a compute or transfer queue type is valid. All other queue types do not support a 'dedicated' queue
486 detail::Result<VkQueue> get_dedicated_queue (QueueType type) const;
487 };
488
489 // For advanced device queue setup
490 struct CustomQueueDescription {
491 explicit CustomQueueDescription (uint32_t index, uint32_t count, std::vector<float> priorities);
492 uint32_t index = 0;
493 uint32_t count = 0;
494 std::vector<float> priorities;
495 };
496
497 void destroy_device (Device device);
498
499 class DeviceBuilder {
500 public:
501 // Any features and extensions that are requested/required in PhysicalDeviceSelector are automatically enabled.
502 explicit DeviceBuilder (PhysicalDevice physical_device);
503
504 detail::Result<Device> build () const;
505
506 // For Advanced Users: specify the exact list of VkDeviceQueueCreateInfo's needed for the application.
507 // If a custom queue setup is provided, getting the queues and queue indexes is up to the application.
508 DeviceBuilder& custom_queue_setup (std::vector<CustomQueueDescription> queue_descriptions);
509
510 // Add a structure to the pNext chain of VkDeviceCreateInfo.
511 // The structure must be valid when DeviceBuilder::build() is called.
512 template <typename T> DeviceBuilder& add_pNext (T* structure) {
513 info.pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (structure));
514 return *this;
515 }
516
517 // Provide custom allocation callbacks.
518 DeviceBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
519
520 private:
521 struct DeviceInfo {
522 VkDeviceCreateFlags flags = 0;
523 std::vector<VkBaseOutStructure*> pNext_chain;
524 PhysicalDevice physical_device;
525 VkSurfaceKHR surface = VK_NULL_HANDLE;
526 bool defer_surface_initialization = false;
527 std::vector<VkQueueFamilyProperties> queue_families;
528 VkPhysicalDeviceFeatures features{};
529 std::vector<const char*> extensions_to_enable;
530 std::vector<CustomQueueDescription> queue_descriptions;
531 VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
532 } info;
533 };
534
535 // ---- Swapchain ---- //
536 struct Swapchain {
537 VkDevice device = VK_NULL_HANDLE;
538 VkSwapchainKHR swapchain = VK_NULL_HANDLE;
539 uint32_t image_count = 0;
540 VkFormat image_format = VK_FORMAT_UNDEFINED;
541 VkExtent2D extent = { 0, 0 };
542 VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
543
544 // Returns a vector of VkImage handles to the swapchain.
545 detail::Result<std::vector<VkImage>> get_images ();
546
547 // Returns a vector of VkImageView's to the VkImage's of the swapchain.
548 // VkImageViews must be destroyed.
549 detail::Result<std::vector<VkImageView>> get_image_views ();
550 void destroy_image_views (std::vector<VkImageView> const& image_views);
551 };
552
553 void destroy_swapchain (Swapchain const& swapchain);
554
555 class SwapchainBuilder {
556 public:
557 explicit SwapchainBuilder (Device const& device);
558 explicit SwapchainBuilder (Device const& device, VkSurfaceKHR const surface);
559 explicit SwapchainBuilder (VkPhysicalDevice const physical_device, VkDevice const device, VkSurfaceKHR const surface, int32_t graphics_queue_index = -1, int32_t present_queue_index = -1);
560
561 detail::Result<Swapchain> build () const;
562
563 // Set the oldSwapchain member of VkSwapchainCreateInfoKHR.
564 // For use in rebuilding a swapchain.
565 SwapchainBuilder& set_old_swapchain (VkSwapchainKHR old_swapchain);
566 SwapchainBuilder& set_old_swapchain (Swapchain const& swapchain);
567
568
569 // Desired size of the swapchain. By default, the swapchain will use the size
570 // of the window being drawn to.
571 SwapchainBuilder& set_desired_extent (uint32_t width, uint32_t height);
572
573 // When determining the surface format, make this the first to be used if supported.
574 SwapchainBuilder& set_desired_format (VkSurfaceFormatKHR format);
575 // Add this swapchain format to the end of the list of formats selected from.
576 SwapchainBuilder& add_fallback_format (VkSurfaceFormatKHR format);
577 // Use the default swapchain formats. This is done if no formats are provided.
578 SwapchainBuilder& use_default_format_selection ();
579
580 // When determining the present mode, make this the first to be used if supported.
581 SwapchainBuilder& set_desired_present_mode (VkPresentModeKHR present_mode);
582 // Add this present mode to the end of the list of present modes selected from.
583 SwapchainBuilder& add_fallback_present_mode (VkPresentModeKHR present_mode);
584 // Use the default presentation mode. This is done if no present modes are provided.
585 SwapchainBuilder& use_default_present_mode_selection ();
586
587 // Set the bitmask of the image usage for acquired swapchain images.
588 SwapchainBuilder& set_image_usage_flags (VkImageUsageFlags usage_flags);
589 // Add a image usage to the bitmask for acquired swapchain images.
590 SwapchainBuilder& add_image_usage_flags (VkImageUsageFlags usage_flags);
591 // Use the default image usage bitmask values. This is the default if no image usages
592 // are provided. The default is VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
593 SwapchainBuilder& use_default_image_usage_flags ();
594
595 // Set the number of views in for multiview/stereo surface
596 SwapchainBuilder& set_image_array_layer_count (uint32_t array_layer_count);
597
598 // Set whether the Vulkan implementation is allowed to discard rendering operations that
599 // affect regions of the surface that are not visible. Default is true.
600 // Note: Applications should use the default of true if they do not expect to read back the content
601 // of presentable images before presenting them or after reacquiring them, and if their fragment
602 // shaders do not have any side effects that require them to run for all pixels in the presentable image.
603 SwapchainBuilder& set_clipped (bool clipped = true);
604
605 // Set the VkSwapchainCreateFlagBitsKHR.
606 SwapchainBuilder& set_create_flags (VkSwapchainCreateFlagBitsKHR create_flags);
607 // Set the transform to be applied, like a 90 degree rotation. Default is the current transform.
608 SwapchainBuilder& set_pre_transform_flags (VkSurfaceTransformFlagBitsKHR pre_transform_flags);
609 // Set the alpha channel to be used with other windows in on the system. Default is VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR.
610 SwapchainBuilder& set_composite_alpha_flags (VkCompositeAlphaFlagBitsKHR composite_alpha_flags);
611
612 // Add a structure to the pNext chain of VkSwapchainCreateInfoKHR.
613 // The structure must be valid when SwapchainBuilder::build() is called.
614 template <typename T> SwapchainBuilder& add_pNext (T* structure) {
615 info.pNext_chain.push_back (reinterpret_cast<VkBaseOutStructure*> (structure));
616 return *this;
617 }
618
619 // Provide custom allocation callbacks.
620 SwapchainBuilder& set_allocation_callbacks (VkAllocationCallbacks* callbacks);
621
622 private:
623 void add_desired_formats (std::vector<VkSurfaceFormatKHR>& formats) const;
624 void add_desired_present_modes (std::vector<VkPresentModeKHR>& modes) const;
625
626 struct SwapchainInfo {
627 VkPhysicalDevice physical_device = VK_NULL_HANDLE;
628 VkDevice device = VK_NULL_HANDLE;
629 std::vector<VkBaseOutStructure*> pNext_chain;
630 VkSwapchainCreateFlagBitsKHR create_flags = static_cast<VkSwapchainCreateFlagBitsKHR> (0);
631 VkSurfaceKHR surface = VK_NULL_HANDLE;
632 std::vector<VkSurfaceFormatKHR> desired_formats;
633 uint32_t desired_width = 256;
634 uint32_t desired_height = 256;
635 uint32_t array_layer_count = 1;
636 VkImageUsageFlags image_usage_flags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
637 uint32_t graphics_queue_index = 0;
638 uint32_t present_queue_index = 0;
639 VkSurfaceTransformFlagBitsKHR pre_transform = static_cast<VkSurfaceTransformFlagBitsKHR> (0);
640 VkCompositeAlphaFlagBitsKHR composite_alpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
641 std::vector<VkPresentModeKHR> desired_present_modes;
642 bool clipped = true;
643 VkSwapchainKHR old_swapchain = VK_NULL_HANDLE;
644 VkAllocationCallbacks* allocation_callbacks = VK_NULL_HANDLE;
645 } info;
646 };
647
648 } // namespace vkb
649
650
651 namespace std {
652 template <> struct is_error_code_enum<vkb::InstanceError> : true_type {};
653 template <> struct is_error_code_enum<vkb::PhysicalDeviceError> : true_type {};
654 template <> struct is_error_code_enum<vkb::QueueError> : true_type {};
655 template <> struct is_error_code_enum<vkb::DeviceError> : true_type {};
656 template <> struct is_error_code_enum<vkb::SwapchainError> : true_type {};
657 } // namespace std
658