UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
vulkan_context.cpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2021-2023 CESNET, z. s. p. o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include "vulkan_context.hpp"
39#include <cassert>
40#include <iostream>
41
42using namespace vulkan_display_detail;
43using namespace vulkan_display;
44
45namespace {
46
47VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
48 [[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
49 [[maybe_unused]] VkDebugUtilsMessageTypeFlagsEXT message_type,
50 const VkDebugUtilsMessengerCallbackDataEXT* callback_data,
51 [[maybe_unused]] void* user_data)
52{
53 LogLevel level = LogLevel::notice;
54 if (VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT & message_severity) level = LogLevel::error;
55 else if (VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT & message_severity) level = LogLevel::warning;
56 else if (VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT & message_severity) level = LogLevel::info;
57 else if (VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT & message_severity) level = LogLevel::verbose;
58
59 vulkan_log_msg(level, "validation layer: "s + callback_data->pMessage);
60
61 if (message_type != VkDebugUtilsMessageTypeFlagBitsEXT::VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT){
62 //assert(false);
63 }
64
65 return VK_FALSE;
66}
67
68void check_validation_layers(const std::vector<const char*>& required_layers) {
69 std::vector<vk::LayerProperties> layers = vk::enumerateInstanceLayerProperties();
70 //for (auto& l : layers) puts(l.layerName);
71
72 for (const auto& req_layer : required_layers) {
73 auto layer_equals = [req_layer](auto const &layer) { return strcmp(req_layer, layer.layerName) == 0; };
74 bool found = std::any_of(layers.begin(), layers.end(), layer_equals);
75 if (!found) {
76 throw VulkanError{"Layer "s + req_layer + " is not supported."};
77 }
78 }
79}
80
81void check_instance_extensions(const std::vector<const char*>& required_extensions) {
82 std::vector<vk::ExtensionProperties> extensions = vk::enumerateInstanceExtensionProperties(nullptr);
83
84 for (const auto& req_exten : required_extensions) {
85 auto extension_equals = [req_exten](auto const &exten) { return strcmp(req_exten, exten.extensionName) == 0; };
86 bool found = std::any_of(extensions.begin(), extensions.end(), extension_equals);
87 if (!found) {
88 throw VulkanError{"Instance extension "s + req_exten + " is not supported."};
89 }
90 }
91}
92
93bool check_device_extensions(bool propagate_error,
94 const std::vector<const char*>& required_extensions, const vk::PhysicalDevice& device)
95{
96 std::vector<vk::ExtensionProperties> extensions = device.enumerateDeviceExtensionProperties(nullptr);
97
98 for (const auto& req_exten : required_extensions) {
99 auto extension_equals = [req_exten](auto const &exten) { return strcmp(req_exten, exten.extensionName) == 0; };
100 bool found = std::any_of(extensions.begin(), extensions.end(), extension_equals);
101 if (!found) {
102 if (propagate_error) {
103 throw VulkanError{"Device extension "s + req_exten + " is not supported."};
104 }
105 return false;
106 }
107 }
108 return true;
109}
110
111uint32_t choose_queue_family_index(vk::PhysicalDevice gpu, vk::SurfaceKHR surface) {
112 assert(gpu);
113
114 std::vector<vk::QueueFamilyProperties> families = gpu.getQueueFamilyProperties();
115
116 for (uint32_t i = 0; i < families.size(); i++) {
117 VkBool32 surface_supported = true;
118 if (surface) {
119 surface_supported = gpu.getSurfaceSupportKHR(i, surface);
120 }
121
122 if (surface_supported &&
123 (families[i].queueFlags & vk::QueueFlagBits::eGraphics) &&
124 (families[i].queueFlags & vk::QueueFlagBits::eCompute))
125 {
126 return i;
127 }
128 }
130}
131
132const std::vector required_gpu_extensions = { "VK_KHR_swapchain" };
133
134bool is_gpu_suitable(bool propagate_error, vk::PhysicalDevice gpu, vk::SurfaceKHR surface = nullptr) {
135 bool result = check_device_extensions(propagate_error, required_gpu_extensions, gpu);
136 if (!result) {
137 return false;
138 }
139 uint32_t index = choose_queue_family_index(gpu, surface);
140 return index != no_queue_index_found;
141}
142
143vk::PhysicalDevice choose_suitable_GPU(const std::vector<vk::PhysicalDevice>& gpus, vk::SurfaceKHR surface, uint32_t req_device_type) {
144 assert(surface);
145 for (const auto& gpu : gpus) {
146 auto properties = gpu.getProperties();
147 if (properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
148 if (is_gpu_suitable(false, gpu, surface) && (req_device_type == vulkan_display::gpu_discrete
149 || req_device_type == vulkan_display::no_gpu_selected)) {
150 return gpu;
151 }
152 }
153 }
154
155 for (const auto& gpu : gpus) {
156 auto properties = gpu.getProperties();
157 if (properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu) {
158 if (is_gpu_suitable(false, gpu, surface) && (req_device_type == vulkan_display::gpu_integrated
159 || req_device_type == vulkan_display::no_gpu_selected)) {
160 return gpu;
161 }
162 }
163 }
164
165 for (const auto& gpu : gpus) {
166 if (is_gpu_suitable(false, gpu, surface) && req_device_type == vulkan_display::no_gpu_selected) {
167 return gpu;
168 }
169 }
170
171 throw VulkanError{"No suitable gpu found."};
172}
173
174vk::PhysicalDevice choose_gpu_by_index(const std::vector<vk::PhysicalDevice>& gpus, uint32_t gpu_index) {
175 if (gpu_index >= gpus.size()) {
176 throw VulkanError{"GPU index is not valid."};
177 }
178 std::vector<std::pair<std::string, vk::PhysicalDevice>> gpu_names;
179 gpu_names.reserve(gpus.size());
180
181 auto get_gpu_name = [](auto gpu) -> std::pair<std::string, vk::PhysicalDevice> {
182 return { gpu.getProperties().deviceName, gpu };
183 };
184
185 std::transform(gpus.begin(), gpus.end(), std::back_inserter(gpu_names), get_gpu_name);
186
187 std::sort(gpu_names.begin(), gpu_names.end());
188 return gpu_names[gpu_index].second;
189}
190
191vk::CompositeAlphaFlagBitsKHR get_composite_alpha(vk::CompositeAlphaFlagsKHR capabilities) {
192 uint32_t result = 1;
193 while (!(result & static_cast<uint32_t>(capabilities))) {
194 result <<= 1u;
195 }
196 return static_cast<vk::CompositeAlphaFlagBitsKHR>(result);
197}
198
199template<typename T>
200bool contains(const std::vector<T>& vec, const T& key){
201 return std::find(vec.begin(), vec.end(), key) != vec.end();
202}
203
204vk::SurfaceFormatKHR get_surface_format(vk::PhysicalDevice gpu, vk::SurfaceKHR surface) {
205 std::vector<vk::SurfaceFormatKHR> available_formats = gpu.getSurfaceFormatsKHR(surface);
206
207 std::array<vk::SurfaceFormatKHR, 5> preferred_formats {{
208 {vk::Format::eA2B10G10R10UnormPack32, vk::ColorSpaceKHR::eSrgbNonlinear},
209 {vk::Format::eB8G8R8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear},
210 {vk::Format::eR8G8B8A8Unorm, vk::ColorSpaceKHR::eSrgbNonlinear},
211 }};
212
213 for(auto& format: preferred_formats){
214 if (contains(available_formats, format)) {
215 return format;
216 }
217 }
218
219 return available_formats[0];
220}
221
222vk::PresentModeKHR get_present_mode(vk::PhysicalDevice gpu, vk::SurfaceKHR surface, vk::PresentModeKHR preferred_present_mode) {
223 std::vector<vk::PresentModeKHR> modes = gpu.getSurfacePresentModesKHR(surface);
224
225 vk::PresentModeKHR preferred = preferred_present_mode;
226 if (contains(modes, preferred)) {
227 return preferred;
228 }
229
230 // Mailbox is alternative to Immediate, Fifo to everything else
231 auto alternative = (preferred == vk::PresentModeKHR::eImmediate
232 ? vk::PresentModeKHR::eMailbox
233 : vk::PresentModeKHR::eFifo);
234
235 if (contains(modes, alternative)) {
236 return alternative;
237 }
238
239 return modes[0];
240}
241
242void log_gpu_info(vk::PhysicalDeviceProperties const &gpu_properties, uint32_t vulkan_version){
243 vulkan_log_msg(LogLevel::info, "Vulkan uses GPU called: "s + &gpu_properties.deviceName[0]);
244 std::string msg = concat(32, std::array{
245 "Used Vulkan API: "s,
246 std::to_string(VK_VERSION_MAJOR(vulkan_version)),
247 "."s,
248 std::to_string(VK_VERSION_MINOR(vulkan_version))
249 });
250 vulkan_log_msg(LogLevel::info, msg);
251}
252
253vk::PhysicalDevice create_physical_device(vk::Instance instance, vk::SurfaceKHR surface, uint32_t gpu_index) {
254 assert(instance);
255 assert(surface);
256 std::vector<vk::PhysicalDevice> gpus = instance.enumeratePhysicalDevices();
257
258 if (gpu_index >= vulkan_display::gpu_macro_min) {
259 return choose_suitable_GPU(gpus, surface, gpu_index);
260 } else {
261 auto gpu = choose_gpu_by_index(gpus, gpu_index);
262 is_gpu_suitable(true, gpu, surface);
263 return gpu;
264 }
265}
266
267void create_swapchain_views(vk::Device device, vk::SwapchainKHR swapchain, vk::Format format, std::vector<SwapchainImage>& swapchain_images) {
268 std::vector<vk::Image> images = device.getSwapchainImagesKHR(swapchain);
269 auto image_count = static_cast<uint32_t>(images.size());
270
271 vk::ImageViewCreateInfo image_view_info =
273
274 swapchain_images.resize(image_count);
275 for (uint32_t i = 0; i < image_count; i++) {
276 SwapchainImage& swapchain_image = swapchain_images[i];
277 swapchain_image.image = images[i];
278
279 image_view_info.setImage(swapchain_image.image);
280 swapchain_image.view = device.createImageView(image_view_info);
281 }
282}
283
284} //namespace ------------------------------------------------------------------------
285
286
287namespace vulkan_display {
288
289void VulkanInstance::init(std::vector<const char*>& required_extensions, bool enable_validation, std::function<void(LogLevel, std::string_view sv)> logging_function) {
290 vulkan_log_msg = std::move(logging_function);
291 std::vector<const char*> validation_layers{};
292 if (enable_validation) {
293 validation_layers.push_back("VK_LAYER_KHRONOS_validation");
294 check_validation_layers(validation_layers);
295
296 const char* debug_extension = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
297 required_extensions.push_back(debug_extension);
298 }
299
300 check_instance_extensions(required_extensions);
301
302 vk::ApplicationInfo app_info{};
303 app_info.setApiVersion(VK_API_VERSION_1_1);
304 vulkan_version = VK_API_VERSION_1_1;
305
306 vk::InstanceCreateInfo instance_info{};
307 instance_info
308 .setPApplicationInfo(&app_info)
309 .setEnabledLayerCount(static_cast<uint32_t>(validation_layers.size()))
310 .setPpEnabledLayerNames(validation_layers.data())
311 .setEnabledExtensionCount(static_cast<uint32_t>(required_extensions.size()))
312 .setPpEnabledExtensionNames(required_extensions.data());
313 auto result = vk::createInstance(&instance_info, nullptr, &instance);
314
315 switch (result) {
316 case vk::Result::eSuccess:
317 break;
318 case vk::Result::eErrorIncompatibleDriver:
319 app_info.apiVersion = VK_API_VERSION_1_0;
320 vulkan_version = VK_API_VERSION_1_0;
321 result = vk::createInstance(&instance_info, nullptr, &instance);
322 if(result != vk::Result::eSuccess){
323 throw VulkanError{"Vulkan instance cannot be created: "s + vk::to_string(result)};
324 }
325 break;
326 default:
327 throw VulkanError{"Vulkan instance cannot be created: "s + vk::to_string(result)};
328 }
329
330 if (enable_validation) {
331 dynamic_dispatcher = std::make_unique<vk::DispatchLoaderDynamic>((VkInstance) instance, vkGetInstanceProcAddr);
333 }
334}
335
337 vk::DebugUtilsMessengerCreateInfoEXT messenger_info{};
338 using Severity = vk::DebugUtilsMessageSeverityFlagBitsEXT;
339 using Type = vk::DebugUtilsMessageTypeFlagBitsEXT;
340 messenger_info
341 .setMessageSeverity(Severity::eError | Severity::eInfo | Severity::eWarning) // severity::eInfo |
342 .setMessageType(Type::eGeneral | Type::ePerformance | Type::eValidation)
343 .setPfnUserCallback(debug_callback)
344 .setPUserData(nullptr);
345 messenger = instance.createDebugUtilsMessengerEXT(messenger_info, nullptr, *dynamic_dispatcher);
346}
347
348void VulkanInstance::get_available_gpus(std::vector<std::pair<std::string, bool>>& gpus) {
349 assert(instance);
350
351 std::vector<vk::PhysicalDevice> physical_devices = instance.enumeratePhysicalDevices();
352 gpus.clear();
353 gpus.reserve(physical_devices.size());
354 for (const auto& gpu : physical_devices) {
355 auto properties = gpu.getProperties();
356 gpus.emplace_back(properties.deviceName, true);
357 }
358 std::sort(gpus.begin(), gpus.end());
359}
360
362 if (instance) {
363 instance.destroy();
364 if (messenger) {
365 instance.destroy(messenger, nullptr, *dynamic_dispatcher);
366 }
367 dynamic_dispatcher = nullptr;
368 instance = nullptr;
369 }
370}
371
372
373} // namespace vulkan_display ----------------------------------------------------------------------------
374
375
376namespace vulkan_display_detail { //------------------------------------------------------------------------
377
379 assert(gpu);
381
382 constexpr std::array priorities = { 1.0f };
383 vk::DeviceQueueCreateInfo queue_info{};
384 queue_info
385 .setQueueFamilyIndex(queue_family_index)
386 .setPQueuePriorities(priorities.data())
387 .setQueueCount(1);
388
389 vk::DeviceCreateInfo device_info{};
391 .setPNext(nullptr)
392 .setQueueCreateInfoCount(1)
393 .setPQueueCreateInfos(&queue_info)
394 .setEnabledExtensionCount(static_cast<uint32_t>(required_gpu_extensions.size()))
395 .setPpEnabledExtensionNames(required_gpu_extensions.data());
396
397 vk::PhysicalDeviceFeatures2 features2{};
398 vk::PhysicalDeviceSamplerYcbcrConversionFeatures yCbCr_feature{};
399 if (vulkan_version == VK_API_VERSION_1_1) {
400 features2.setPNext(&yCbCr_feature);
401 gpu.getFeatures2(&features2);
402 if (yCbCr_feature.samplerYcbcrConversion) {
403 yCbCr_supported = true;
404 device_info.setPNext(&features2);
405 vulkan_log_msg(LogLevel::info, "yCbCr feature supported.");
406 }
407 }
408
409 //reset features
410 features2 = vk::PhysicalDeviceFeatures2{};
411 features2.setPNext(&yCbCr_feature);
412
413 device = gpu.createDevice(device_info);
414}
415
416void VulkanContext::create_swap_chain(vk::SwapchainKHR&& old_swapchain) {
417 constexpr int initialization_attempts = 3;
418 for (int attempt = 0; attempt < initialization_attempts; attempt++) {
419 auto& capabilities = swapchain_atributes.capabilities;
420 capabilities = gpu.getSurfaceCapabilitiesKHR(surface);
421
422 swapchain_atributes.format = get_surface_format(gpu, surface);
423 swapchain_atributes.mode = get_present_mode(gpu, surface, preferred_present_mode);
424
425 vk::Extent2D swapchain_image_size;
426 swapchain_image_size.width = std::clamp(window_parameters.width,
427 capabilities.minImageExtent.width,
428 capabilities.maxImageExtent.width);
429 swapchain_image_size.height = std::clamp(window_parameters.height,
430 capabilities.minImageExtent.height,
431 capabilities.maxImageExtent.height);
432 swapchain_atributes.image_size = swapchain_image_size;
433
434 uint32_t image_count = std::max(uint32_t{2}, capabilities.minImageCount);
435 if (capabilities.maxImageCount != 0) {
436 image_count = std::min(image_count, capabilities.maxImageCount);
437 }
438
439 auto msg = concat(64, std::array{
440 "Recreating swapchain, size: "s,
441 std::to_string(swapchain_image_size.width),
442 "x"s,
443 std::to_string(swapchain_image_size.height),
444 ", format: "s,
445 vk::to_string(swapchain_atributes.format.format)
446 });
447 vulkan_log_msg(LogLevel::info, msg);
448
449 //assert(capabilities.supportedUsageFlags & vk::ImageUsageFlagBits::eTransferDst);
450 vk::SwapchainCreateInfoKHR swapchain_info{};
451 swapchain_info
452 .setSurface(surface)
453 .setImageFormat(swapchain_atributes.format.format)
454 .setImageColorSpace(swapchain_atributes.format.colorSpace)
455 .setPresentMode(swapchain_atributes.mode)
456 .setMinImageCount(image_count)
457 .setImageExtent(swapchain_image_size)
458 .setImageArrayLayers(1)
459 .setImageUsage(vk::ImageUsageFlagBits::eColorAttachment)
460 .setImageSharingMode(vk::SharingMode::eExclusive)
461 .setPreTransform(swapchain_atributes.capabilities.currentTransform)
462 .setCompositeAlpha(get_composite_alpha(swapchain_atributes.capabilities.supportedCompositeAlpha))
463 .setClipped(true)
464 .setOldSwapchain(old_swapchain);
465 try{
466 swapchain = device.createSwapchainKHR(swapchain_info);
467 device.destroy(old_swapchain);
468 old_swapchain = nullptr;
469 return;
470 }
471 catch(std::exception& err){
472 vulkan_log_msg(LogLevel::info, "Recreation unsuccesful: "s + err.what());
473 device.destroy(old_swapchain);
474 old_swapchain = nullptr;
475 if(attempt + 1 == initialization_attempts){
476 throw err;
477 }
478 }
479 }
480 assert(false);
481}
482
484 WindowParameters parameters, uint32_t gpu_index, vk::PresentModeKHR preferredMode)
485{
486 assert(!this->instance);
487 this->instance = instance.instance;
488 this->dynamic_dispatcher = std::move(instance.dynamic_dispatcher);
489 this->messenger = instance.messenger;
490 this->vulkan_version = instance.vulkan_version;
491 instance.instance = nullptr;
492 instance.messenger = nullptr;
493
494 this->surface = surface;
495 this->preferred_present_mode = preferredMode;
496 window_parameters = parameters;
497
498 gpu = create_physical_device(this->instance, surface, gpu_index);
499
500 queue_family_index = choose_queue_family_index(gpu, surface);
502
504 auto properties = gpu.getProperties();
505 if (properties.apiVersion < VK_API_VERSION_1_1) {
506 vulkan_version = VK_API_VERSION_1_0;
507 }
508
509 log_gpu_info(properties, vulkan_version);
510
511 queue = device.getQueue(queue_family_index, 0);
513 create_swapchain_views(device, swapchain, swapchain_atributes.format.format, swapchain_images);
514}
515
516void VulkanContext::create_framebuffers(vk::RenderPass render_pass) {
517 vk::FramebufferCreateInfo framebuffer_info;
518 framebuffer_info
519 .setRenderPass(render_pass)
520 .setWidth(swapchain_atributes.image_size.width)
521 .setHeight(swapchain_atributes.image_size.height)
522 .setLayers(1);
523
524 for(auto& swapchain_image : swapchain_images){
525 framebuffer_info
526 .setAttachmentCount(1)
527 .setPAttachments(&swapchain_image.view);
528 swapchain_image.framebuffer = device.createFramebuffer(framebuffer_info);
529 }
530}
531
532void VulkanContext::recreate_swapchain(WindowParameters parameters, vk::RenderPass render_pass) {
533 window_parameters = parameters;
534
535 device.waitIdle();
536
539 vk::SwapchainKHR old_swap_chain = swapchain;
540 create_swap_chain(std::move(old_swap_chain));
541 create_swapchain_views(device, swapchain, swapchain_atributes.format.format, swapchain_images);
542 create_framebuffers(render_pass);
543}
544
545uint32_t VulkanContext::acquire_next_swapchain_image(vk::Semaphore acquire_semaphore) const {
546 constexpr uint64_t timeout = 1'000'000'000; // 1s = 1 000 000 000 nanoseconds
547 uint32_t image_index;
548 auto acquired = device.acquireNextImageKHR(swapchain, timeout, acquire_semaphore, nullptr, &image_index);
549 switch (acquired) {
550 case vk::Result::eSuccess:
551 break;
552 case vk::Result::eSuboptimalKHR: [[fallthrough]];
553 case vk::Result::eErrorOutOfDateKHR:
554 image_index = swapchain_image_out_of_date;
555 break;
556 case vk::Result::eTimeout:
557 image_index = swapchain_image_timeout;
558 break;
559 default:
560 throw VulkanError{"Next swapchain image cannot be acquired."s + vk::to_string(acquired)};
561 }
562 return image_index;
563}
564
566 if (device) {
567 // static_cast to silence nodiscard warning
568 device.waitIdle();
571 device.destroy(swapchain);
572 device.destroy();
573 }
574 if (instance) {
575 instance.destroy(surface);
576 if (messenger) {
577 instance.destroy(messenger, nullptr, *dynamic_dispatcher);
578 }
579 instance.destroy();
580 }
581 dynamic_dispatcher = nullptr;
582}
583
584
585} //vulkan_display_detail
586
friend void vulkan_display_detail::VulkanContext::init(VulkanInstance &&, vk::SurfaceKHR, vulkan_display::WindowParameters, uint32_t, vk::PresentModeKHR)
void get_available_gpus(std::vector< std::pair< std::string, bool > > &gpus)
returns all available grafhics cards first parameter is gpu name, second parameter is true only if th...
vk::DebugUtilsMessengerEXT messenger
std::unique_ptr< vk::DispatchLoaderDynamic > dynamic_dispatcher
void create_swap_chain(vk::SwapchainKHR &&old_swap_chain=vk::SwapchainKHR{})
struct vulkan_display_detail::VulkanContext::@94 swapchain_atributes
void recreate_swapchain(vulkan_display::WindowParameters parameters, vk::RenderPass render_pass)
vk::DebugUtilsMessengerEXT messenger
std::vector< SwapchainImage > swapchain_images
std::unique_ptr< vk::DispatchLoaderDynamic > dynamic_dispatcher
uint32_t acquire_next_swapchain_image(vk::Semaphore acquire_semaphore) const
void create_framebuffers(vk::RenderPass render_pass)
void init(vulkan_display::VulkanInstance &&instance, vk::SurfaceKHR surface, vulkan_display::WindowParameters window_parameters, uint32_t gpu_index, vk::PresentModeKHR preferred_mode)
vulkan_display::WindowParameters window_parameters
vk::SurfaceCapabilitiesKHR capabilities
std::string concat(size_t expected_result_size, std::array< std::string, count > const &strings)
std::function< void(vulkan_display::LogLevel, std::string_view)> vulkan_log_msg
vk::ImageViewCreateInfo default_image_view_create_info(vk::Format format)
constexpr uint32_t swapchain_image_out_of_date
constexpr uint32_t no_queue_index_found
constexpr uint32_t swapchain_image_timeout
constexpr uint32_t gpu_macro_min
constexpr uint32_t gpu_integrated
constexpr uint32_t gpu_discrete
constexpr uint32_t no_gpu_selected
const char * key
Definition cineform.cpp:125
static class worker_pool instance
Definition worker.cpp:250