MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
VKDevice.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "VKInstance.hpp"
4
5namespace MayaFlux::Core {
6
7struct GraphicsBackendInfo;
8
9/**
10 * @struct QueueFamilyIndices
11 * @brief Stores indices of queue families we need
12 *
13 * Immutable after VKDevice::create_logical_device. Presentation is a property
14 * of the device, the family, and the platform, resolved once at device
15 * selection, so present_family_mask is never renegotiated per surface.
16 */
18 static constexpr uint32_t MAX_TRACKED_FAMILIES = 32; ///< Width of present_family_mask
19
20 std::optional<uint32_t> graphics_family;
21 std::optional<uint32_t> compute_family;
22 std::optional<uint32_t> transfer_family;
23
24 /** @brief Bit i set when family i passed the surfaceless presentation probe. */
26
27 [[nodiscard]] bool is_complete() const
28 {
29 return graphics_family.has_value();
30 }
31
32 /** @brief Whether family @p index can present. */
33 [[nodiscard]] bool can_present(uint32_t index) const
34 {
35 return index < MAX_TRACKED_FAMILIES && (present_family_mask & (1U << index)) != 0;
36 }
37
38 /**
39 * @brief Family the engine presents on by default.
40 * @return The graphics family when it can present, otherwise the lowest
41 * presentation-capable family, otherwise empty.
42 */
43 [[nodiscard]] std::optional<uint32_t> preferred_present_family() const
44 {
45 if (graphics_family.has_value() && can_present(graphics_family.value()))
46 return graphics_family;
47
48 for (uint32_t i = 0; i < MAX_TRACKED_FAMILIES; ++i) {
49 if (can_present(i))
50 return i;
51 }
52 return std::nullopt;
53 }
54};
55
56/**
57 * @class VKDevice
58 * @brief Manages Vulkan physical device selection and logical device creation
59 *
60 * Handles GPU selection and creates the logical device interface
61 * for executing commands.
62 */
63class VKDevice {
64public:
65 VKDevice() = default;
66 ~VKDevice();
67
68 VKDevice(const VKDevice&) = delete;
69 VKDevice& operator=(const VKDevice&) = delete;
70 VKDevice(VKDevice&&) noexcept;
71 VKDevice& operator=(VKDevice&&) noexcept;
72
73 /**
74 * @brief Select a physical device and create the logical device
75 * @param instance Vulkan instance
76 * @param backend_info Graphics backend configuration, including device selection
77 * @return true if initialization succeeded
78 */
79 bool initialize(vk::Instance instance, const GraphicsBackendInfo& backend_info);
80
81 /**
82 * @brief Cleanup device resources
83 */
84 void cleanup();
85
86 /**
87 * @brief Get physical device handle
88 */
89 [[nodiscard]] vk::PhysicalDevice get_physical_device() const { return m_physical_device; }
90
91 /**
92 * @brief Get logical device handle
93 */
94 [[nodiscard]] vk::Device get_device() const { return m_logical_device; }
95
96 /**
97 * @brief Get graphics queue
98 */
99 [[nodiscard]] vk::Queue get_graphics_queue() const { return m_graphics_queue; }
100
101 /**
102 * @brief Get compute queue (may be same as graphics)
103 */
104 [[nodiscard]] vk::Queue get_compute_queue() const { return m_compute_queue; }
105
106 /**
107 * @brief Get transfer queue (may be same as graphics)
108 */
109 [[nodiscard]] vk::Queue get_transfer_queue() const { return m_transfer_queue; }
110
111 /**
112 * @brief Get queue family indices
113 */
114 [[nodiscard]] const QueueFamilyIndices& get_queue_families() const { return m_queue_families; }
115
116 /** @brief Name of the selected physical device */
117 [[nodiscard]] const std::string& get_device_name() const { return m_device_name; }
118
119 /** @brief Whether the graphics queue family passed the surfaceless presentation probe */
120 [[nodiscard]] bool graphics_family_presents() const { return m_graphics_presents; }
121
122 /**
123 * @brief Confirm the graphics family presents to a concrete surface
124 * @param surface Surface to check
125 * @return true if presentation is supported
126 *
127 * Device selection already guarantees this when require_presentation is
128 * set; this confirms the surfaceless probe against a real surface. Const
129 * and non-mutating, so it is safe from any thread.
130 */
131 [[nodiscard]] bool graphics_family_can_present(vk::SurfaceKHR surface) const;
132
133 /**
134 * @brief Queue for a presentation-capable family
135 * @param family_index Family index, must be set in present_family_mask
136 * @return Queue handle, or null if the family has no presentation support
137 *
138 * A queue is created for every family in the mask, not only the one the
139 * engine's default present path uses, so a caller driving its own
140 * presentation has a queue available without recreating the device.
141 */
142 [[nodiscard]] vk::Queue get_present_queue(uint32_t family_index) const;
143
144 /**
145 * @brief Queue for the preferred presentation family
146 * @return Queue handle, or null when no family can present
147 */
148 [[nodiscard]] vk::Queue get_preferred_present_queue() const;
149
150 /**
151 * @brief Wait for the device to become idle
152 */
153 void wait_idle() const
154 {
155 if (m_logical_device) {
156 m_logical_device.waitIdle();
157 }
158 }
159
160 /**
161 * @brief Query and log supported device extensions
162 */
164
165 /**
166 * @brief Check if the device supports mesh shaders
167 * @return true if mesh shaders are supported
168 */
169 [[nodiscard]] bool supports_mesh_shaders() const { return m_supports_mesh_shaders; }
170
171private:
172 vk::PhysicalDevice m_physical_device; ///< Selected physical device (GPU)
173 vk::Device m_logical_device; ///< Logical device handle
174
175 vk::Queue m_graphics_queue; ///< Graphics queue handle
176 vk::Queue m_compute_queue; ///< Compute queue handle
177 vk::Queue m_transfer_queue; ///< Transfer queue handle
178
179 QueueFamilyIndices m_queue_families; ///< Indices of required queue families
180
181 /**
182 * @brief Select a physical device by config selector or score
183 * @param instance Vulkan instance
184 * @param backend_info Graphics backend configuration
185 * @return true if a suitable device was found
186 */
187 bool pick_physical_device(vk::Instance instance, const GraphicsBackendInfo& backend_info);
188
189 /**
190 * @brief Find queue families on the given physical device
191 * @param device Physical device to query
192 * @return QueueFamilyIndices with found queue family indices
193 */
194 static QueueFamilyIndices find_queue_families(vk::PhysicalDevice device);
195
196 /**
197 * @brief Create the logical device and retrieve queue handles
198 * @param instance Vulkan instance
199 * @param backend_info Graphics backend configuration
200
201 * @return true if logical device creation succeeded
202 */
203 bool create_logical_device(vk::Instance instance, const GraphicsBackendInfo& backend_info);
204
205 bool m_graphics_presents {}; ///< Graphics family passed the surfaceless presentation probe
206 std::unordered_map<uint32_t, vk::Queue> m_present_queues; ///< One queue per presentation-capable family
207 std::string m_device_name; ///< Selected device name, cached for logging
208 std::array<uint8_t, VK_UUID_SIZE> m_device_uuid {}; ///< Selected device UUID
209 bool m_supports_mesh_shaders {}; ///< Whether the device supports mesh shaders
210};
211}
vk::PhysicalDevice device
Definition VKDevice.cpp:141
vk::Instance instance
Definition VKDevice.cpp:50
uint32_t index
Definition VKDevice.cpp:142
vk::PhysicalDevice get_physical_device() const
Get physical device handle.
Definition VKDevice.hpp:89
static QueueFamilyIndices find_queue_families(vk::PhysicalDevice device)
Find queue families on the given physical device.
Definition VKDevice.cpp:558
void query_supported_extensions()
Query and log supported device extensions.
Definition VKDevice.cpp:614
const std::string & get_device_name() const
Name of the selected physical device.
Definition VKDevice.hpp:117
std::array< uint8_t, VK_UUID_SIZE > m_device_uuid
Selected device UUID.
Definition VKDevice.hpp:208
bool graphics_family_presents() const
Whether the graphics queue family passed the surfaceless presentation probe.
Definition VKDevice.hpp:120
const QueueFamilyIndices & get_queue_families() const
Get queue family indices.
Definition VKDevice.hpp:114
bool graphics_family_can_present(vk::SurfaceKHR surface) const
Confirm the graphics family presents to a concrete surface.
Definition VKDevice.cpp:592
void cleanup()
Cleanup device resources.
Definition VKDevice.cpp:266
bool m_supports_mesh_shaders
Whether the device supports mesh shaders.
Definition VKDevice.hpp:209
bool pick_physical_device(vk::Instance instance, const GraphicsBackendInfo &backend_info)
Select a physical device by config selector or score.
Definition VKDevice.cpp:285
VKDevice & operator=(const VKDevice &)=delete
VKDevice(const VKDevice &)=delete
vk::PhysicalDevice m_physical_device
Selected physical device (GPU)
Definition VKDevice.hpp:172
vk::Queue get_preferred_present_queue() const
Queue for the preferred presentation family.
Definition VKDevice.cpp:608
vk::Queue m_compute_queue
Compute queue handle.
Definition VKDevice.hpp:176
bool create_logical_device(vk::Instance instance, const GraphicsBackendInfo &backend_info)
Create the logical device and retrieve queue handles.
Definition VKDevice.cpp:625
vk::Queue m_transfer_queue
Transfer queue handle.
Definition VKDevice.hpp:177
vk::Device m_logical_device
Logical device handle.
Definition VKDevice.hpp:173
bool m_graphics_presents
Graphics family passed the surfaceless presentation probe.
Definition VKDevice.hpp:205
vk::Device get_device() const
Get logical device handle.
Definition VKDevice.hpp:94
std::unordered_map< uint32_t, vk::Queue > m_present_queues
One queue per presentation-capable family.
Definition VKDevice.hpp:206
std::string m_device_name
Selected device name, cached for logging.
Definition VKDevice.hpp:207
vk::Queue get_present_queue(uint32_t family_index) const
Queue for a presentation-capable family.
Definition VKDevice.cpp:602
vk::Queue m_graphics_queue
Graphics queue handle.
Definition VKDevice.hpp:175
vk::Queue get_graphics_queue() const
Get graphics queue.
Definition VKDevice.hpp:99
vk::Queue get_compute_queue() const
Get compute queue (may be same as graphics)
Definition VKDevice.hpp:104
vk::Queue get_transfer_queue() const
Get transfer queue (may be same as graphics)
Definition VKDevice.hpp:109
bool supports_mesh_shaders() const
Check if the device supports mesh shaders.
Definition VKDevice.hpp:169
QueueFamilyIndices m_queue_families
Indices of required queue families.
Definition VKDevice.hpp:179
void wait_idle() const
Wait for the device to become idle.
Definition VKDevice.hpp:153
Manages Vulkan physical device selection and logical device creation.
Definition VKDevice.hpp:63
void initialize()
Definition main.cpp:11
Configuration for graphics API backend (Vulkan/OpenGL/etc.)
static constexpr uint32_t MAX_TRACKED_FAMILIES
Width of present_family_mask.
Definition VKDevice.hpp:18
bool can_present(uint32_t index) const
Whether family index can present.
Definition VKDevice.hpp:33
std::optional< uint32_t > transfer_family
Definition VKDevice.hpp:22
std::optional< uint32_t > graphics_family
Definition VKDevice.hpp:20
uint32_t present_family_mask
Bit i set when family i passed the surfaceless presentation probe.
Definition VKDevice.hpp:25
std::optional< uint32_t > preferred_present_family() const
Family the engine presents on by default.
Definition VKDevice.hpp:43
std::optional< uint32_t > compute_family
Definition VKDevice.hpp:21
Stores indices of queue families we need.
Definition VKDevice.hpp:17