UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
vulkan_context.hpp
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#pragma once
39
40#include <vulkan/vulkan.hpp>
41static_assert(VK_HEADER_VERSION > 100); // minimum Vulkan SDK version is 1.1.101
42//Newer versions can be downloaded from the official website:
43//https://vulkan.lunarg.com/sdk/home
44
45//remove leaking macros
46#undef min
47#undef max
48
49#include <exception>
50#include <functional>
51#include <iostream>
52#include <memory>
53#include <string>
54
55namespace vulkan_display {
56
58
59struct VulkanError : public std::runtime_error {
60 explicit VulkanError(const std::string& msg) :
61 std::runtime_error{ msg } { }
62};
63
65 uint32_t width = 0;
66 uint32_t height = 0;
67
68 constexpr bool operator==(const WindowParameters& other) const {
69 return width == other.width &&
70 height == other.height;
71 }
72 constexpr bool operator!=(const WindowParameters& other) const {
73 return !(*this == other);
74 }
75 constexpr bool is_minimized() const {
76 return width * height == 0;
77 }
78};
79
80constexpr uint32_t no_gpu_selected = UINT32_MAX;
81constexpr uint32_t gpu_integrated = UINT32_MAX - 1;
82constexpr uint32_t gpu_discrete = UINT32_MAX - 2;
83constexpr uint32_t gpu_macro_min = gpu_discrete;
84
85class VulkanInstance;
86
87} // namespace vulkan_display ---------------------------------------------
88
89
90namespace vulkan_display_detail {
91
92// todo C++20 - replace with std::format
93template<size_t count>
94std::string concat(size_t expected_result_size, std::array<std::string, count> const &strings){
95 std::string result;
96 result.reserve(expected_result_size);
97
98 for(auto const &sv: strings){
99 result+= sv;
100 }
101 return result;
102}
103
104constexpr bool is_yCbCr_format(vk::Format format) {
105 auto f = static_cast<VkFormat>(format);
106 return VK_FORMAT_G8B8G8R8_422_UNORM <= f && f <= VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM;
107}
108
109using namespace std::literals;
110
111constexpr uint32_t no_queue_index_found = UINT32_MAX;
112constexpr uint32_t swapchain_image_out_of_date = UINT32_MAX;
113constexpr uint32_t swapchain_image_timeout = UINT32_MAX - 1;
114
115inline std::function<void(vulkan_display::LogLevel, std::string_view)> vulkan_log_msg;
116
117inline vk::ImageViewCreateInfo default_image_view_create_info(vk::Format format) {
118 vk::ImageViewCreateInfo image_view_info{ {}, {}, vk::ImageViewType::e2D, format };
119 image_view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
120 image_view_info.subresourceRange.levelCount = 1;
121 image_view_info.subresourceRange.layerCount = 1;
122 return image_view_info;
123}
124
126 vk::Image image;
127 vk::ImageView view;
128 vk::Framebuffer framebuffer;
129};
130
132 vk::Instance instance;
133 std::unique_ptr<vk::DispatchLoaderDynamic> dynamic_dispatcher{};
134 vk::DebugUtilsMessengerEXT messenger;
135 uint32_t vulkan_version{};
136
137 vk::PhysicalDevice gpu;
138 vk::Device device;
139 bool yCbCr_supported = false;
140
142 vk::Queue queue;
143
144 vk::SurfaceKHR surface;
145 vk::SwapchainKHR swapchain;
146 struct {
147 vk::SurfaceCapabilitiesKHR capabilities;
148 vk::SurfaceFormatKHR format;
149 vk::PresentModeKHR mode = vk::PresentModeKHR::eFifo;
150 vk::Extent2D image_size;
152
153 std::vector<SwapchainImage> swapchain_images{};
154 vk::PresentModeKHR preferred_present_mode{};
155
157public:
158 //getters
159 uint32_t get_vulkan_version() const { return vulkan_version; }
160 vk::PhysicalDevice get_gpu() { return gpu; }
161 vk::Device get_device() { return device; }
162 bool is_yCbCr_supported() const { return yCbCr_supported; }
164 vk::Queue get_queue() { return queue; }
165 vk::SwapchainKHR get_swapchain() { return swapchain; }
166 vk::Format get_swapchain_image_format() { return swapchain_atributes.format.format; };
167 size_t get_swapchain_image_count() { return swapchain_images.size(); }
168 vk::Extent2D get_render_area_size() { return swapchain_atributes.image_size; }
169private:
171
172 void create_swap_chain(vk::SwapchainKHR&& old_swap_chain = vk::SwapchainKHR{});
173
175 for (auto& image : swapchain_images) {
176 device.destroy(image.view);
177 image.view = nullptr;
178 }
179 }
180
182 for (auto& image : swapchain_images) {
183 device.destroy(image.framebuffer);
184 image.framebuffer = nullptr;
185 }
186 }
187
188public:
189 VulkanContext() = default;
190
192 vulkan_display::WindowParameters window_parameters, uint32_t gpu_index, vk::PresentModeKHR preferred_mode);
193
194 void destroy();
195
196 void create_framebuffers(vk::RenderPass render_pass);
197
198 uint32_t acquire_next_swapchain_image(vk::Semaphore acquire_semaphore) const;
199
200 vk::Framebuffer get_framebuffer(uint32_t framebuffer_id) {
201 return swapchain_images[framebuffer_id].framebuffer;
202 }
203
207
208 void recreate_swapchain(vulkan_display::WindowParameters parameters, vk::RenderPass render_pass);
209};
210
211}//namespace vulkan_display_detail ----------------------------------------------------------------
212
213
214namespace vulkan_display {
215
216namespace detail = vulkan_display_detail;
217
218inline void cout_msg([[maybe_unused]] LogLevel log_level, std::string_view msg) {
219 std::cout << msg << std::endl;
220}
221
223 vk::Instance instance{};
224 std::unique_ptr<vk::DispatchLoaderDynamic> dynamic_dispatcher = nullptr;
225 vk::DebugUtilsMessengerEXT messenger{};
226 uint32_t vulkan_version = VK_API_VERSION_1_1;
227
229
231 vk::SurfaceKHR, vulkan_display::WindowParameters, uint32_t, vk::PresentModeKHR);
232public:
233 VulkanInstance() = default;
234 VulkanInstance(const VulkanInstance& other) = delete;
235 VulkanInstance& operator=(const VulkanInstance& other) = delete;
238
240 destroy();
241 }
242
248 void init(std::vector<const char*>& required_extensions, bool enable_validation, std::function<void(LogLevel, std::string_view)> logging_function = cout_msg);
249
255 void get_available_gpus(std::vector<std::pair<std::string, bool>>& gpus);
256
257 vk::Instance& get_instance() {
258 return instance;
259 }
260
261 void destroy();
262};
263
264}
VulkanInstance(const VulkanInstance &other)=delete
friend void vulkan_display_detail::VulkanContext::init(VulkanInstance &&, vk::SurfaceKHR, vulkan_display::WindowParameters, uint32_t, vk::PresentModeKHR)
VulkanInstance(VulkanInstance &&other)=delete
VulkanInstance & operator=(const VulkanInstance &other)=delete
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
VulkanInstance & operator=(VulkanInstance &&other)=delete
vk::Framebuffer get_framebuffer(uint32_t framebuffer_id)
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
vulkan_display::WindowParameters get_window_parameters() 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
volatile int log_level
Definition debug.cpp:65
std::string concat(size_t expected_result_size, std::array< std::string, count > const &strings)
constexpr bool is_yCbCr_format(vk::Format format)
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
void cout_msg(LogLevel log_level, std::string_view msg)
constexpr uint32_t gpu_integrated
constexpr uint32_t gpu_discrete
constexpr uint32_t no_gpu_selected
VulkanError(const std::string &msg)
constexpr bool is_minimized() const
constexpr bool operator!=(const WindowParameters &other) const
constexpr bool operator==(const WindowParameters &other) const