Skip to content

Commit b6a46a3

Browse files
committed
Add sync2
1 parent 9b8cc7d commit b6a46a3

18 files changed

+1704
-3
lines changed

docs/codes/04/11_pipelinecache/GraphicsPipeline.cppm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export namespace vht {
5959
if (std::ifstream in("pipeline_cache.data", std::ios::binary | std::ios::ate);
6060
in
6161
) {
62-
const size_t size = in.tellg();
62+
const std::size_t size = in.tellg();
6363
in.seekg(0);
6464
data.resize(size);
6565
in.read(data.data(), size);
Binary file not shown.

docs/codes/04/13_sync2/Device.cppm

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
export module Device;
2+
3+
import std;
4+
import vulkan_hpp;
5+
6+
import Context;
7+
import Window;
8+
9+
export namespace vht {
10+
/**
11+
* @brief 队列族索引
12+
* @details
13+
* - graphics_family: 图形队列族索引
14+
* - present_family: 呈现队列族索引
15+
* - is_complete(): 检查是否已找到所需的队列族索引
16+
*/
17+
struct QueueFamilyIndices {
18+
std::optional<std::uint32_t> graphics_family;
19+
std::optional<std::uint32_t> present_family;
20+
[[nodiscard]]
21+
bool is_complete() const {
22+
return graphics_family.has_value() && present_family.has_value();
23+
}
24+
};
25+
26+
/**
27+
* @brief 交换链支持的详细信息
28+
* @details
29+
* - capabilities: 交换链的能力
30+
* - formats: 支持的表面格式
31+
* - present_modes: 支持的呈现模式
32+
*/
33+
struct SwapchainSupportDetails {
34+
vk::SurfaceCapabilitiesKHR capabilities;
35+
std::vector<vk::SurfaceFormatKHR> formats;
36+
std::vector<vk::PresentModeKHR> present_modes;
37+
};
38+
/**
39+
* @brief 设备相关
40+
* @details
41+
* - 依赖:
42+
* - m_context: Vulkan上下文
43+
* - m_window: 窗口相关
44+
* - 工作:
45+
* - 选择合适的物理设备
46+
* - 创建逻辑设备和队列
47+
* - 可访问成员:
48+
* - physical_device(): 获取物理设备
49+
* - device(): 获取逻辑设备
50+
* - graphics_queue(): 获取图形队列
51+
* - present_queue(): 获取呈现队列
52+
* - swapchain_support(): 获取交换链支持的详细信息
53+
* - queue_family_indices(): 获取队列族索引
54+
*/
55+
class Device {
56+
std::shared_ptr<vht::Context> m_context{ nullptr };
57+
std::shared_ptr<vht::Window> m_window{ nullptr };
58+
vk::raii::PhysicalDevice m_physical_device{ nullptr };
59+
vk::raii::Device m_device{ nullptr };
60+
QueueFamilyIndices m_queue_family_indices{};
61+
vk::raii::Queue m_graphics_queue{ nullptr };
62+
vk::raii::Queue m_present_queue{ nullptr };
63+
public:
64+
explicit Device(std::shared_ptr<vht::Context> context, std::shared_ptr<vht::Window> window)
65+
: m_context(std::move(context)),
66+
m_window(std::move(window)) {
67+
pick_physical_device();
68+
create_device();
69+
}
70+
71+
[[nodiscard]]
72+
const vk::raii::PhysicalDevice& physical_device() const { return m_physical_device; }
73+
[[nodiscard]]
74+
const vk::raii::Device& device() const { return m_device; }
75+
[[nodiscard]]
76+
const vk::raii::Queue& graphics_queue() const { return m_graphics_queue; }
77+
[[nodiscard]]
78+
const vk::raii::Queue& present_queue() const { return m_present_queue; }
79+
[[nodiscard]]
80+
SwapchainSupportDetails swapchain_support() const { return query_swapchain_support(m_physical_device); }
81+
[[nodiscard]]
82+
QueueFamilyIndices queue_family_indices() const { return m_queue_family_indices; }
83+
private:
84+
/**
85+
* @brief 挑选物理设备
86+
*/
87+
void pick_physical_device() {
88+
const auto physical_devices = m_context->instance().enumeratePhysicalDevices();
89+
if (physical_devices.empty()) throw std::runtime_error("failed to enumerate physical devices");
90+
for (const auto& it : physical_devices) {
91+
if (is_device_suitable(it)) {
92+
m_physical_device = it;
93+
return;
94+
}
95+
}
96+
throw std::runtime_error("failed to get physical device");
97+
}
98+
99+
/**
100+
* @brief 判断物理设备是否可用
101+
* @param physical_device 物理设备
102+
* @return bool 是否适合使用
103+
*/
104+
[[nodiscard]]
105+
bool is_device_suitable(const vk::raii::PhysicalDevice& physical_device) const {
106+
// 检查是否支持交换链扩展
107+
std::set<std::string> extension_set{ vk::KHRSwapchainExtensionName };
108+
for (const auto& it : physical_device.enumerateDeviceExtensionProperties()) {
109+
extension_set.erase(it.extensionName);
110+
}
111+
if (!extension_set.empty()) return false;
112+
// 交换链格式支持
113+
if (const auto supports = query_swapchain_support(physical_device);
114+
supports.formats.empty() || supports.present_modes.empty()
115+
) return false;
116+
// 队列族支持
117+
const auto indices = find_queue_families(physical_device);
118+
return indices.is_complete();
119+
}
120+
121+
/**
122+
* @brief 获取交换链支持的详细信息
123+
* @param physical_device 物理设备
124+
* @return 交换链支持的详细信息
125+
*/
126+
[[nodiscard]]
127+
SwapchainSupportDetails query_swapchain_support(const vk::raii::PhysicalDevice& physical_device) const {
128+
return {
129+
physical_device.getSurfaceCapabilitiesKHR( m_window->surface() ),
130+
physical_device.getSurfaceFormatsKHR( m_window->surface() ),
131+
physical_device.getSurfacePresentModesKHR( m_window->surface() )
132+
};
133+
}
134+
135+
/**
136+
* @brief 查询需要的队列族索引
137+
* @param physical_device 物理设备
138+
* @return QueueFamilyIndices 队列族索引
139+
*/
140+
[[nodiscard]]
141+
QueueFamilyIndices find_queue_families(const vk::raii::PhysicalDevice& physical_device) const {
142+
QueueFamilyIndices indices{};
143+
const auto queue_families = physical_device.getQueueFamilyProperties();
144+
for (std::uint32_t i = 0; const auto& queue_family : queue_families) {
145+
if (queue_family.queueFlags & vk::QueueFlagBits::eGraphics) {
146+
indices.graphics_family = i;
147+
}
148+
if(physical_device.getSurfaceSupportKHR(i, m_window->surface())){
149+
indices.present_family = i;
150+
}
151+
if (indices.is_complete()) break;
152+
++i;
153+
}
154+
return indices;
155+
}
156+
157+
/**
158+
* @brief 创建逻辑设备与队列
159+
*/
160+
void create_device() {
161+
// 已在物理设备创建时保证内容不为空
162+
m_queue_family_indices = find_queue_families(m_physical_device);
163+
const auto [graphics_family, present_family] = m_queue_family_indices;
164+
165+
std::set<std::uint32_t> unique_queue_families { graphics_family.value(), present_family.value() };
166+
167+
std::vector<vk::DeviceQueueCreateInfo> queue_create_infos;
168+
queue_create_infos.reserve(unique_queue_families.size());
169+
float queue_priority = 1.0f;
170+
for (const std::uint32_t queue_family : unique_queue_families) {
171+
vk::DeviceQueueCreateInfo queue_create_info;
172+
queue_create_info.queueFamilyIndex = queue_family;
173+
queue_create_info.setQueuePriorities( queue_priority );
174+
queue_create_infos.emplace_back( queue_create_info );
175+
}
176+
177+
constexpr std::array<const char*, 1> device_extensions { vk::KHRSwapchainExtensionName };
178+
vk::StructureChain<
179+
vk::DeviceCreateInfo,
180+
vk::PhysicalDeviceFeatures2,
181+
vk::PhysicalDeviceVulkan12Features,
182+
vk::PhysicalDeviceVulkan13Features
183+
> create_info_chain;
184+
create_info_chain.get()
185+
.setQueueCreateInfos( queue_create_infos )
186+
.setPEnabledExtensionNames( device_extensions );
187+
create_info_chain.get<vk::PhysicalDeviceFeatures2>().features
188+
.setSamplerAnisotropy( true ); // 启用各向异性采样
189+
create_info_chain.get<vk::PhysicalDeviceVulkan12Features>()
190+
.setTimelineSemaphore( true ); // 启用时间线信号量
191+
create_info_chain.get<vk::PhysicalDeviceVulkan13Features>()
192+
.setSynchronization2( true ); // 启用同步2
193+
194+
m_device = m_physical_device.createDevice( create_info_chain.get() );
195+
196+
m_graphics_queue = m_device.getQueue( graphics_family.value(), 0 );
197+
m_present_queue = m_device.getQueue( present_family.value(), 0 );
198+
}
199+
200+
};
201+
}
202+

docs/codes/04/13_sync2/Device.diff

3.72 KB
Binary file not shown.

0 commit comments

Comments
 (0)