@@ -14,82 +14,81 @@ We wrap the actual Physical Device and a few other useful objects into `struct G
14
14
constexpr auto vk_version_v = VK_MAKE_VERSION(1 , 3 , 0 );
15
15
16
16
struct Gpu {
17
- vk::PhysicalDevice device{};
18
- vk::PhysicalDeviceProperties properties{};
19
- vk::PhysicalDeviceFeatures features{};
20
- std::uint32_t queue_family{};
17
+ vk::PhysicalDevice device{};
18
+ vk::PhysicalDeviceProperties properties{};
19
+ vk::PhysicalDeviceFeatures features{};
20
+ std::uint32_t queue_family{};
21
21
};
22
22
23
23
[[nodiscard]] auto get_suitable_gpu (vk::Instance instance,
24
- vk::SurfaceKHR surface) -> Gpu;
24
+ vk::SurfaceKHR surface) -> Gpu;
25
25
```
26
26
27
27
The implementation:
28
28
29
29
```cpp
30
30
auto lvk::get_suitable_gpu(vk::Instance const instance,
31
- vk::SurfaceKHR const surface) -> Gpu {
32
- auto const supports_swapchain = [](Gpu const& gpu) {
33
- static constexpr std::string_view name_v =
34
- VK_KHR_SWAPCHAIN_EXTENSION_NAME;
35
- static constexpr auto is_swapchain =
36
- [](vk::ExtensionProperties const& properties) {
37
- return properties.extensionName.data() == name_v;
38
- };
39
- auto const properties = gpu.device.enumerateDeviceExtensionProperties();
40
- auto const it = std::ranges::find_if(properties, is_swapchain);
41
- return it != properties.end();
42
- };
43
-
44
- auto const set_queue_family = [](Gpu& out_gpu) {
45
- static constexpr auto queue_flags_v =
46
- vk::QueueFlagBits::eGraphics | vk::QueueFlagBits::eTransfer;
47
- for (auto const [index, family] :
48
- std::views::enumerate(out_gpu.device.getQueueFamilyProperties())) {
49
- if ((family.queueFlags & queue_flags_v) == queue_flags_v) {
50
- out_gpu.queue_family = static_cast<std::uint32_t>(index);
51
- return true;
52
- }
53
- }
54
- return false;
55
- };
56
-
57
- auto const can_present = [surface](Gpu const& gpu) {
58
- return gpu.device.getSurfaceSupportKHR(gpu.queue_family, surface) ==
59
- vk::True;
60
- };
61
-
62
- auto fallback = Gpu{};
63
- for (auto const& device : instance.enumeratePhysicalDevices()) {
64
- auto gpu = Gpu{.device = device, .properties = device.getProperties()};
65
- if (gpu.properties.apiVersion < vk_version_v) { continue; }
66
- if (!supports_swapchain(gpu)) { continue; }
67
- if (!set_queue_family(gpu)) { continue; }
68
- if (!can_present(gpu)) { continue; }
69
- gpu.features = gpu.device.getFeatures();
70
- if (gpu.properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
71
- return gpu;
72
- }
73
- // keep iterating in case we find a Discrete Gpu later.
74
- fallback = gpu;
75
- }
76
- if (fallback.device) { return fallback; }
77
-
78
- throw std::runtime_error{"No suitable Vulkan Physical Devices"};
31
+ vk::SurfaceKHR const surface) -> Gpu {
32
+ auto const supports_swapchain = [](Gpu const& gpu) {
33
+ static constexpr std::string_view name_v =
34
+ VK_KHR_SWAPCHAIN_EXTENSION_NAME;
35
+ static constexpr auto is_swapchain =
36
+ [](vk::ExtensionProperties const& properties) {
37
+ return properties.extensionName.data() == name_v;
38
+ };
39
+ auto const properties = gpu.device.enumerateDeviceExtensionProperties();
40
+ auto const it = std::ranges::find_if(properties, is_swapchain);
41
+ return it != properties.end();
42
+ };
43
+
44
+ auto const set_queue_family = [](Gpu& out_gpu) {
45
+ static constexpr auto queue_flags_v =
46
+ vk::QueueFlagBits::eGraphics | vk::QueueFlagBits::eTransfer;
47
+ for (auto const [index, family] :
48
+ std::views::enumerate(out_gpu.device.getQueueFamilyProperties())) {
49
+ if ((family.queueFlags & queue_flags_v) == queue_flags_v) {
50
+ out_gpu.queue_family = static_cast<std::uint32_t>(index);
51
+ return true;
52
+ }
53
+ }
54
+ return false;
55
+ };
56
+
57
+ auto const can_present = [surface](Gpu const& gpu) {
58
+ return gpu.device.getSurfaceSupportKHR(gpu.queue_family, surface) ==
59
+ vk::True;
60
+ };
61
+
62
+ auto fallback = Gpu{};
63
+ for (auto const& device : instance.enumeratePhysicalDevices()) {
64
+ auto gpu = Gpu{.device = device, .properties = device.getProperties()};
65
+ if (gpu.properties.apiVersion < vk_version_v) { continue; }
66
+ if (!supports_swapchain(gpu)) { continue; }
67
+ if (!set_queue_family(gpu)) { continue; }
68
+ if (!can_present(gpu)) { continue; }
69
+ gpu.features = gpu.device.getFeatures();
70
+ if (gpu.properties.deviceType == vk::PhysicalDeviceType::eDiscreteGpu) {
71
+ return gpu;
72
+ }
73
+ // keep iterating in case we find a Discrete Gpu later.
74
+ fallback = gpu;
75
+ }
76
+ if (fallback.device) { return fallback; }
77
+
78
+ throw std::runtime_error{"No suitable Vulkan Physical Devices"};
79
79
}
80
80
```
81
81
82
82
Finally, add a ` Gpu ` member in ` App ` and initialize it after ` create_surface() ` :
83
83
84
84
``` cpp
85
- create_surface ();
86
- select_gpu ();
87
- // ...
88
-
85
+ create_surface ();
86
+ select_gpu ();
89
87
88
+ // ...
90
89
void App::select_gpu () {
91
- m_gpu = get_suitable_gpu(*m_instance, *m_surface);
92
- std::println ("Using GPU: {}",
93
- std::string_view{m_gpu.properties.deviceName});
90
+ m_gpu = get_suitable_gpu(* m_instance, * m_surface);
91
+ std::println ("Using GPU: {}",
92
+ std::string_view{m_gpu.properties.deviceName});
94
93
}
95
94
```
0 commit comments