Skip to content

Commit e149ed5

Browse files
committed
Add new base code
1 parent c28f366 commit e149ed5

File tree

11 files changed

+141
-105
lines changed

11 files changed

+141
-105
lines changed
1.07 MB
Binary file not shown.

docs/md/04/13_sync2.md

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,17 @@ m_device = m_physical_device.createDevice( create_info_chain.get() );
254254
现在我们有更语义化的表达, `None` 表示没有命令, `AllCommands` 表示所有命令:
255255

256256
```cpp
257-
// 等待管线的开始 曾经: dp.srcStageMask = vk::PipelineStageFlagBits::eTopOfPipe;
258-
dp.srcStageMask = vk::PipelineStageFlagBits2KHR::eNone; // 现在
259-
// 等待管线的结束 曾经:dp.srcStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
260-
dp.srcStageMask = vk::PipelineStageFlagBits2KHR::eAllCommands; // 现在,表示所有命令的结束
261-
// 等待完成后才能开始管线 曾经:dp.dstStageMask = vk::PipelineStageFlagBits::eTopOfPipe;
262-
dp.dstStageMask = vk::PipelineStageFlagBits2KHR::eAllCommands; // 现在,表示开始管线的所有任务
263-
// 等待完成后才能结束管线 曾经:dp.dstStageMask = vk::PipelineStageFlagBits::eBottomOfPipe;
264-
dp.dstStageMask = vk::PipelineStageFlagBits2KHR::eNone; // 现在
257+
// 等待管线的开始(不等待任何前置操作)
258+
dp.srcStageMask = vk::PipelineStageFlagBits2KHR::eNone;
259+
260+
// 等待管线的结束(等待所有命令完成)
261+
dp.srcStageMask = vk::PipelineStageFlagBits2KHR::eAllCommands;
262+
263+
// 等待完成后才能开始管线(允许所有后续命令)
264+
dp.dstStageMask = vk::PipelineStageFlagBits2KHR::eAllCommands;
265+
266+
// 等待完成后才能结束管线(不激活任何后续阶段)
267+
dp.dstStageMask = vk::PipelineStageFlagBits2KHR::eNone;
265268
```
266269

267270
此外,旧版本中 `AccessMask` 字段常使用 `{}` 来表示“无访问”,即只做阶段同步而不涉及资源(如等待所有任务完成)。
File renamed without changes.

docs/todo.md

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ comments: true
66
待重构与制作的内容:
77

88
```
9-
- 重要杂项:
10-
......
11-
- TODO: todo.md # 同步2.0语法 + 辅助命令缓冲
129
- 普通杂项:
13-
- 查询池: md/04/20_querypool.md # 待重构
1410
- 无图像帧缓冲: md/04/21_imageless.md # TODO
1511
- 动态渲染: md/04/22_dynamicrendering.md # TODO
1612
- 待重构:
@@ -19,9 +15,7 @@ comments: true
1915
- 延迟渲染: md/04/31_deferred.md # 待重构
2016
- 模板测试: md/04/32_stenciltest.md # TODO
2117
- 多线程渲染:
22-
- TODO: todo.md # 并行命令录制 + 队列并发
23-
- 离屏渲染:
24-
- TODO: todo.md # 离屏渲染 + 帧缓冲分离(多视图)
18+
- TODO: todo.md # 次级命令缓冲 + 并行命令录制 + 队列并发
2519
- 着色器进阶:
2620
- TODO: todo.md # 几何着色器 + 细分着色器 + 任务与网格着色器
2721
- 光线追踪:
@@ -30,6 +24,8 @@ comments: true
3024
- TODO: todo.md # 间接绘制 + 稀疏资源 + 内存分配库
3125
- 高级计算:
3226
- TODO: todo.md # 共享内存 + 原子操作 + 子组操作
27+
- 离屏渲染:
28+
- TODO: todo.md # 离屏渲染 + 帧缓冲分离(多视图)
3329
```
3430

3531
// TODO

mkdocs.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,16 @@ nav:
8787
- pNext与sType: md/04/12_pnext_stype.md
8888
- 新版同步: md/04/13_sync2.md
8989
- 查询池: md/04/14_querypool.md
90-
- TODO: todo.md # 辅助命令缓冲
9190
- 普通杂项:
9291
- 无图像帧缓冲: md/04/21_imageless.md
9392
- 动态渲染: md/04/22_dynamicrendering.md
9493
- 待重构:
9594
- 多管线渲染:
9695
- 阴影映射: md/04/30_shadowmap.md
9796
- 延迟渲染: md/04/31_deferred.md
98-
- 模板测试: md/04/32_stenciltest.md
97+
- 模板测试: md/04/32_stencil.md
9998
- 多线程渲染:
100-
- TODO: todo.md # 并行命令录制 + 队列并发
99+
- TODO: todo.md # 次级命令缓冲 + 并行命令录制 + 队列并发
101100
- 离屏渲染:
102101
- TODO: todo.md # 离屏渲染 + 帧缓冲分离(多视图)
103102
- 着色器进阶:

src/vht/Context.cppm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ export namespace vht {
4343
void init() {
4444
if ( !glfw::init() ) throw std::runtime_error("Failed to initialize GLFW");
4545
vk::ApplicationInfo app_info{
46-
"Vulkan", 1,
46+
"HelloVulkan", 1,
4747
"MyEngine", 1,
4848
vk::makeApiVersion(0, 1, 4, 0) // VK_API_VERSION_1_4
4949
};

src/vht/Device.cppm

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import vulkan_hpp;
66
import Context;
77
import Window;
88

9+
constexpr std::array<const char*, 1> DEVICE_EXTENSIONS { vk::KHRSwapchainExtensionName };
10+
911
export namespace vht {
1012
/**
1113
* @brief 队列族索引
@@ -104,7 +106,7 @@ export namespace vht {
104106
[[nodiscard]]
105107
bool is_device_suitable(const vk::raii::PhysicalDevice& physical_device) const {
106108
// 检查是否支持交换链扩展
107-
std::set<std::string> extension_set{ vk::KHRSwapchainExtensionName };
109+
std::set<std::string> extension_set( DEVICE_EXTENSIONS.begin(), DEVICE_EXTENSIONS.end() );
108110
for (const auto& it : physical_device.enumerateDeviceExtensionProperties()) {
109111
extension_set.erase(it.extensionName);
110112
}
@@ -174,15 +176,25 @@ export namespace vht {
174176
queue_create_infos.emplace_back( queue_create_info );
175177
}
176178

177-
vk::PhysicalDeviceFeatures features;
178-
features.samplerAnisotropy = true;
179-
vk::DeviceCreateInfo create_info;
180-
create_info.setQueueCreateInfos( queue_create_infos );
181-
create_info.setPEnabledFeatures( &features );
182-
constexpr std::array<const char*, 1> device_extensions { vk::KHRSwapchainExtensionName };
183-
create_info.setPEnabledExtensionNames( device_extensions );
179+
vk::StructureChain<
180+
vk::DeviceCreateInfo,
181+
vk::PhysicalDeviceFeatures2,
182+
vk::PhysicalDeviceVulkan11Features,
183+
vk::PhysicalDeviceVulkan12Features,
184+
vk::PhysicalDeviceVulkan13Features
185+
> device_create_info;
186+
187+
device_create_info.get()
188+
.setQueueCreateInfos( queue_create_infos )
189+
.setPEnabledExtensionNames( DEVICE_EXTENSIONS );
190+
device_create_info.get<vk::PhysicalDeviceFeatures2>().features
191+
.setSamplerAnisotropy( true );
192+
device_create_info.get<vk::PhysicalDeviceVulkan12Features>()
193+
.setTimelineSemaphore( true );
194+
device_create_info.get<vk::PhysicalDeviceVulkan13Features>()
195+
.setSynchronization2( true );
184196

185-
m_device = m_physical_device.createDevice( create_info );
197+
m_device = m_physical_device.createDevice( device_create_info.get() );
186198
m_graphics_queue = m_device.getQueue( graphics_family.value(), 0 );
187199
m_present_queue = m_device.getQueue( present_family.value(), 0 );
188200
}

src/vht/Drawer.cppm

Lines changed: 56 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ export namespace vht {
4747
std::shared_ptr<vht::InputAssembly> m_input_assembly{ nullptr };
4848
std::shared_ptr<vht::UniformBuffer> m_uniform_buffer{ nullptr };
4949
std::shared_ptr<vht::Descriptor> m_descriptor{ nullptr };
50-
std::vector<vk::raii::Semaphore> m_image_available_semaphores;
51-
std::vector<vk::raii::Semaphore> m_render_finished_semaphores;
52-
std::vector<vk::raii::Fence> m_in_flight_fences;
50+
std::vector<vk::raii::Semaphore> m_present_semaphores;
51+
std::vector<vk::raii::Semaphore> m_image_semaphores;
52+
std::vector<vk::raii::Semaphore> m_time_semaphores;
5353
std::vector<vk::raii::CommandBuffer> m_command_buffers;
5454
int m_current_frame = 0;
5555
public:
@@ -79,42 +79,65 @@ export namespace vht {
7979

8080

8181
void draw() {
82-
// 等待当前帧的栅栏,即确保上一个帧的绘制完成
83-
if( const auto res = m_device->device().waitForFences( *m_in_flight_fences[m_current_frame], true, std::numeric_limits<std::uint64_t>::max() );
84-
res != vk::Result::eSuccess
85-
) throw std::runtime_error{ "waitForFences in drawFrame was failed" };
82+
static std::array<std::uint64_t, MAX_FRAMES_IN_FLIGHT> time_counter{};
83+
84+
vk::SemaphoreWaitInfo first_wait;
85+
first_wait.setSemaphores( *m_time_semaphores[m_current_frame] ); // 需要 * 转换至少一次类型
86+
first_wait.setValues( time_counter[m_current_frame] );
87+
std::ignore = m_device->device().waitSemaphores( first_wait, std::numeric_limits<std::uint64_t>::max() );
8688

8789
// 获取交换链的下一个图像索引
8890
std::uint32_t image_index;
8991
try{
90-
auto [res, idx] = m_swapchain->swapchain().acquireNextImage(std::numeric_limits<std::uint64_t>::max(), m_image_available_semaphores[m_current_frame]);
92+
auto [res, idx] = m_swapchain->swapchain().acquireNextImage(
93+
std::numeric_limits<std::uint64_t>::max(), m_image_semaphores[m_current_frame]
94+
);
9195
image_index = idx;
9296
} catch (const vk::OutOfDateKHRError&){
9397
m_render_pass->recreate();
9498
return;
9599
}
96-
// 重置当前帧的栅栏,延迟到此处等待,防止上方 return 导致死锁
97-
m_device->device().resetFences( *m_in_flight_fences[m_current_frame] );
100+
98101
// 更新 uniform 缓冲区
99102
m_uniform_buffer->update_uniform_buffer(m_current_frame);
100103
// 重置当前帧的命令缓冲区,并记录新的命令
101104
m_command_buffers[m_current_frame].reset();
102105
record_command_buffer(m_command_buffers[m_current_frame], image_index);
103-
// 设置绘制命令的提交信息
104-
vk::SubmitInfo submit_info;
105-
submit_info.setWaitSemaphores( *m_image_available_semaphores[m_current_frame] );
106-
std::array<vk::PipelineStageFlags,1> waitStages = { vk::PipelineStageFlagBits::eColorAttachmentOutput };
107-
submit_info.setWaitDstStageMask( waitStages );
108-
submit_info.setCommandBuffers( *m_command_buffers[m_current_frame] );
109-
submit_info.setSignalSemaphores( *m_render_finished_semaphores[m_current_frame] );
106+
107+
++time_counter[m_current_frame]; // 增加计数器的值,以便在渲染完成时增加时间线信号量
108+
// 等待图像准备完成
109+
vk::SemaphoreSubmitInfo wait_image;
110+
wait_image.setSemaphore( m_image_semaphores[m_current_frame] );
111+
wait_image.setStageMask( vk::PipelineStageFlagBits2::eColorAttachmentOutput );
112+
// 二进制信号量,不需要设置值
113+
114+
// 渲染完成时发出信号
115+
std::array<vk::SemaphoreSubmitInfo,2> signal_infos;
116+
signal_infos[0].setSemaphore( m_time_semaphores[m_current_frame] ); // 更新时间线信号量
117+
// 渲染完成后,将时间线信号量的值设置为计数器的值,保证严格递增
118+
signal_infos[0].setValue( time_counter[m_current_frame] );
119+
// 触发呈现信号量,表示图像已经渲染完成,可用于呈现
120+
signal_infos[1].setSemaphore( m_present_semaphores[m_current_frame] );
121+
// 二进制信号量,不需要设置值
122+
123+
// 设置命令缓冲区提交信息
124+
vk::CommandBufferSubmitInfo command_info;
125+
command_info.setCommandBuffer( m_command_buffers[m_current_frame] );
126+
127+
vk::SubmitInfo2 submit_info;
128+
submit_info.setWaitSemaphoreInfos( wait_image );
129+
submit_info.setSignalSemaphoreInfos( signal_infos );
130+
submit_info.setCommandBufferInfos( command_info );
131+
110132
// 提交命令缓冲区到图形队列
111-
m_device->graphics_queue().submit(submit_info, m_in_flight_fences[m_current_frame]);
133+
m_device->graphics_queue().submit2( submit_info );
134+
112135
// 设置呈现信息
113136
vk::PresentInfoKHR present_info;
114-
present_info.setWaitSemaphores( *m_render_finished_semaphores[m_current_frame] );
137+
present_info.setWaitSemaphores( *m_present_semaphores[m_current_frame] );
115138
present_info.setSwapchains( *m_swapchain->swapchain() );
116139
present_info.pImageIndices = &image_index;
117-
// 提交呈现之类
140+
// 提交呈现命令
118141
try{
119142
if( m_device->present_queue().presentKHR(present_info) == vk::Result::eSuboptimalKHR ) {
120143
m_render_pass->recreate();
@@ -146,15 +169,20 @@ export namespace vht {
146169
}
147170
// 创建同步对象(信号量和栅栏)
148171
void create_sync_object() {
149-
vk::SemaphoreCreateInfo semaphore_create_info;
150-
vk::FenceCreateInfo fence_create_info{ vk::FenceCreateFlagBits::eSignaled };
151-
m_image_available_semaphores.reserve( MAX_FRAMES_IN_FLIGHT );
152-
m_render_finished_semaphores.reserve( MAX_FRAMES_IN_FLIGHT );
153-
m_in_flight_fences.reserve( MAX_FRAMES_IN_FLIGHT );
172+
vk::SemaphoreCreateInfo image_info;
173+
// 时间线信号量需要使用 pNext 链
174+
vk::StructureChain<vk::SemaphoreCreateInfo, vk::SemaphoreTypeCreateInfo> time_info;
175+
time_info.get<vk::SemaphoreTypeCreateInfo>()
176+
.setSemaphoreType( vk::SemaphoreType::eTimeline )
177+
.setInitialValue( 0 );
178+
179+
m_present_semaphores.reserve( MAX_FRAMES_IN_FLIGHT );
180+
m_image_semaphores.reserve( MAX_FRAMES_IN_FLIGHT );
181+
m_time_semaphores.reserve( MAX_FRAMES_IN_FLIGHT );
154182
for(std::size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; ++i){
155-
m_image_available_semaphores.emplace_back( m_device->device(), semaphore_create_info );
156-
m_render_finished_semaphores.emplace_back( m_device->device(), semaphore_create_info );
157-
m_in_flight_fences.emplace_back( m_device->device() , fence_create_info );
183+
m_present_semaphores.emplace_back( m_device->device().createSemaphore(image_info) );
184+
m_image_semaphores.emplace_back( m_device->device().createSemaphore(image_info) );
185+
m_time_semaphores.emplace_back( m_device->device().createSemaphore(time_info.get()) );
158186
}
159187
}
160188
// 记录命令缓冲区

src/vht/RenderPass.cppm

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export namespace vht {
8383
}
8484
// 创建渲染通道
8585
void create_render_pass() {
86-
vk::AttachmentDescription color_attachment;
86+
vk::AttachmentDescription2 color_attachment;
8787
color_attachment.format = m_swapchain->format();
8888
color_attachment.samples = vk::SampleCountFlagBits::e1;
8989
color_attachment.loadOp = vk::AttachmentLoadOp::eClear;
@@ -93,44 +93,49 @@ export namespace vht {
9393
color_attachment.initialLayout = vk::ImageLayout::eUndefined;
9494
color_attachment.finalLayout = vk::ImageLayout::ePresentSrcKHR;
9595

96-
vk::AttachmentReference color_attachment_ref;
96+
vk::AttachmentReference2 color_attachment_ref;
9797
color_attachment_ref.attachment = 0;
98-
color_attachment_ref.layout = vk::ImageLayout::eColorAttachmentOptimal;
98+
color_attachment_ref.layout = vk::ImageLayout::eAttachmentOptimal;
9999

100-
vk::AttachmentDescription depth_attachment;
100+
vk::AttachmentDescription2 depth_attachment;
101101
depth_attachment.format = m_depth_image->format();
102102
depth_attachment.samples = vk::SampleCountFlagBits::e1;
103103
depth_attachment.loadOp = vk::AttachmentLoadOp::eClear;
104104
depth_attachment.storeOp = vk::AttachmentStoreOp::eDontCare;
105105
depth_attachment.stencilLoadOp = vk::AttachmentLoadOp::eDontCare;
106106
depth_attachment.stencilStoreOp = vk::AttachmentStoreOp::eDontCare;
107107
depth_attachment.initialLayout = vk::ImageLayout::eUndefined;
108-
depth_attachment.finalLayout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
108+
depth_attachment.finalLayout = vk::ImageLayout::eAttachmentOptimal;
109109

110-
vk::AttachmentReference depth_attachment_ref;
110+
vk::AttachmentReference2 depth_attachment_ref;
111111
depth_attachment_ref.attachment = 1;
112-
depth_attachment_ref.layout = vk::ImageLayout::eDepthStencilAttachmentOptimal;
112+
depth_attachment_ref.layout = vk::ImageLayout::eAttachmentOptimal;
113113

114-
vk::SubpassDescription subpass;
114+
vk::SubpassDescription2 subpass;
115115
subpass.pipelineBindPoint = vk::PipelineBindPoint::eGraphics;
116116
subpass.setColorAttachments( color_attachment_ref );
117117
subpass.setPDepthStencilAttachment( &depth_attachment_ref );
118118

119-
vk::SubpassDependency dependency;
120-
dependency.srcSubpass = vk::SubpassExternal;
121-
dependency.srcStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests;
122-
dependency.srcAccessMask = {};
123-
dependency.dstSubpass = 0;
124-
dependency.dstStageMask = vk::PipelineStageFlagBits::eColorAttachmentOutput | vk::PipelineStageFlagBits::eEarlyFragmentTests;
125-
dependency.dstAccessMask = vk::AccessFlagBits::eColorAttachmentWrite | vk::AccessFlagBits::eDepthStencilAttachmentWrite;
119+
120+
vk::StructureChain<vk::SubpassDependency2, vk::MemoryBarrier2> dependency;
121+
122+
dependency.get() // 设置子通道依赖
123+
.setDependencyFlags(vk::DependencyFlagBits::eByRegion) // 局部依赖化,优化性能,可选
124+
.setSrcSubpass( vk::SubpassExternal ) // 只需要设置两个子通道序号
125+
.setDstSubpass( 0 );
126+
dependency.get<vk::MemoryBarrier2>() // 具体同步交给内存屏障
127+
.setSrcStageMask( vk::PipelineStageFlagBits2::eColorAttachmentOutput | vk::PipelineStageFlagBits2::eEarlyFragmentTests )
128+
.setSrcAccessMask( vk::AccessFlagBits2::eNone )
129+
.setDstStageMask( vk::PipelineStageFlagBits2::eColorAttachmentOutput | vk::PipelineStageFlagBits2::eEarlyFragmentTests )
130+
.setDstAccessMask( vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eDepthStencilAttachmentWrite );
126131

127132
const auto attachments = { color_attachment, depth_attachment };
128-
vk::RenderPassCreateInfo create_info;
133+
vk::RenderPassCreateInfo2 create_info;
129134
create_info.setAttachments( attachments );
130135
create_info.setSubpasses( subpass );
131-
create_info.setDependencies( dependency );
136+
create_info.setDependencies( dependency.get() );
132137

133-
m_render_pass = m_device->device().createRenderPass( create_info );
138+
m_render_pass = m_device->device().createRenderPass2( create_info );
134139
}
135140
// 创建帧缓冲区
136141
void create_framebuffers() {

src/vht/TextureSampler.cppm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export namespace vht {
122122
m_device->graphics_queue(),
123123
m_image,
124124
vk::ImageLayout::eTransferDstOptimal,
125-
vk::ImageLayout::eShaderReadOnlyOptimal
125+
vk::ImageLayout::eReadOnlyOptimal
126126
);
127127
}
128128
// 创建纹理图像视图

0 commit comments

Comments
 (0)