Skip to content

Commit 4b54866

Browse files
committed
Create Device
1 parent 6d6b4d6 commit 4b54866

File tree

4 files changed

+99
-0
lines changed

4 files changed

+99
-0
lines changed

guide/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
- [Vulkan Instance](initialization/instance.md)
1414
- [Vulkan Surface](initialization/surface.md)
1515
- [Vulkan Physical Device](initialization/gpu.md)
16+
- [Vulkan Device](initialization/device.md)

guide/src/initialization/device.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Vulkan Device
2+
3+
A [Vulkan Device](https://registry.khronos.org/vulkan/specs/latest/man/html/VkDevice.html) is a logical instance of a Physical Device, and will the primary interface for everything Vulkan now onwards. [Vulkan Queues](https://registry.khronos.org/vulkan/specs/latest/man/html/VkQueue.html) are owned by the Device, we will need one from the queue family stored in the `Gpu`, to submit recorded command buffers. We also need to explicitly declare all features we want to use, eg [Dynamic Rendering](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_dynamic_rendering.html) and [Synchronization2](https://registry.khronos.org/vulkan/specs/latest/man/html/VK_KHR_synchronization2.html).
4+
5+
Setup a `vk::QueueCreateInfo` object:
6+
7+
```cpp
8+
auto queue_ci = vk::DeviceQueueCreateInfo{};
9+
// since we use only one queue, it has the entire priority range, ie, 1.0
10+
static constexpr auto queue_priorities_v = std::array{1.0f};
11+
queue_ci.setQueueFamilyIndex(m_gpu.queue_family)
12+
.setQueueCount(1)
13+
.setQueuePriorities(queue_priorities_v);
14+
```
15+
16+
Setup the core device features:
17+
18+
```cpp
19+
auto enabled_features = vk::PhysicalDeviceFeatures{};
20+
enabled_features.fillModeNonSolid = m_gpu.features.fillModeNonSolid;
21+
enabled_features.wideLines = m_gpu.features.wideLines;
22+
enabled_features.samplerAnisotropy = m_gpu.features.samplerAnisotropy;
23+
enabled_features.sampleRateShading = m_gpu.features.sampleRateShading;
24+
```
25+
26+
Setup the additional features, using `setPNext()` to chain them:
27+
28+
```cpp
29+
auto sync_feature = vk::PhysicalDeviceSynchronization2Features{vk::True};
30+
auto dynamic_rendering_feature =
31+
vk::PhysicalDeviceDynamicRenderingFeatures{vk::True};
32+
sync_feature.setPNext(&dynamic_rendering_feature);
33+
```
34+
35+
Setup a `vk::DeviceCreateInfo` object:
36+
37+
```cpp
38+
auto device_ci = vk::DeviceCreateInfo{};
39+
static constexpr auto extensions_v =
40+
std::array{VK_KHR_SWAPCHAIN_EXTENSION_NAME};
41+
device_ci.setPEnabledExtensionNames(extensions_v)
42+
.setQueueCreateInfos(queue_ci)
43+
.setPEnabledFeatures(&enabled_features)
44+
.setPNext(&sync_feature);
45+
```
46+
47+
Declare a `vk::UniqueDevice` member after `m_gpu`, create it, and initialize the dispatcher against it:
48+
49+
```cpp
50+
m_device = m_gpu.device.createDeviceUnique(device_ci);
51+
VULKAN_HPP_DEFAULT_DISPATCHER.init(*m_device);
52+
```
53+
54+
Declare a `vk::Queue` member (order doesn't matter since it's just a handle, the actual Queue is owned by the Device) and initialize it:
55+
56+
```cpp
57+
static constexpr std::uint32_t queue_index_v{0};
58+
m_queue = m_device->getQueue(m_gpu.queue_family, queue_index_v);
59+
```

src/app.cpp

+36
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ void App::run() {
99
create_instance();
1010
create_surface();
1111
select_gpu();
12+
create_device();
1213

1314
main_loop();
1415
}
@@ -46,6 +47,41 @@ void App::select_gpu() {
4647
std::string_view{m_gpu.properties.deviceName});
4748
}
4849

50+
void App::create_device() {
51+
auto queue_ci = vk::DeviceQueueCreateInfo{};
52+
// since we use only one queue, it has the entire priority range, ie, 1.0
53+
static constexpr auto queue_priorities_v = std::array{1.0f};
54+
queue_ci.setQueueFamilyIndex(m_gpu.queue_family)
55+
.setQueueCount(1)
56+
.setQueuePriorities(queue_priorities_v);
57+
58+
auto enabled_features = vk::PhysicalDeviceFeatures{};
59+
enabled_features.fillModeNonSolid = m_gpu.features.fillModeNonSolid;
60+
enabled_features.wideLines = m_gpu.features.wideLines;
61+
enabled_features.samplerAnisotropy = m_gpu.features.samplerAnisotropy;
62+
enabled_features.sampleRateShading = m_gpu.features.sampleRateShading;
63+
64+
auto sync_feature = vk::PhysicalDeviceSynchronization2Features{vk::True};
65+
auto dynamic_rendering_feature =
66+
vk::PhysicalDeviceDynamicRenderingFeatures{vk::True};
67+
sync_feature.setPNext(&dynamic_rendering_feature);
68+
69+
auto device_ci = vk::DeviceCreateInfo{};
70+
static constexpr auto extensions_v =
71+
std::array{VK_KHR_SWAPCHAIN_EXTENSION_NAME};
72+
device_ci.setPEnabledExtensionNames(extensions_v)
73+
.setQueueCreateInfos(queue_ci)
74+
.setPEnabledFeatures(&enabled_features)
75+
.setPNext(&sync_feature);
76+
77+
m_device = m_gpu.device.createDeviceUnique(device_ci);
78+
VULKAN_HPP_DEFAULT_DISPATCHER.init(*m_device);
79+
static constexpr std::uint32_t queue_index_v{0};
80+
m_queue = m_device->getQueue(m_gpu.queue_family, queue_index_v);
81+
82+
// m_device_block.get() = *m_device;
83+
}
84+
4985
void App::main_loop() {
5086
while (glfwWindowShouldClose(m_window.get()) == GLFW_FALSE) {
5187
glfwPollEvents();

src/app.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ class App {
1313
void create_instance();
1414
void create_surface();
1515
void select_gpu();
16+
void create_device();
1617

1718
void main_loop();
1819

1920
glfw::Window m_window{};
2021
vk::UniqueInstance m_instance{};
2122
vk::UniqueSurfaceKHR m_surface{};
2223
Gpu m_gpu{};
24+
vk::UniqueDevice m_device{};
25+
vk::Queue m_queue{};
2326
};
2427
} // namespace lvk

0 commit comments

Comments
 (0)