Skip to content

Commit 2068621

Browse files
committed
Add Specialization Constants
1 parent 5dad59f commit 2068621

21 files changed

+397
-46
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
module;
2+
3+
#include <memory>
4+
#include <vector>
5+
6+
export module GraphicsPipeline;
7+
8+
import vulkan_hpp;
9+
10+
import DataLoader;
11+
import Utility;
12+
import Device;
13+
import RenderPass;
14+
15+
export namespace vht {
16+
17+
/**
18+
* @brief 图形管线相关
19+
* @details
20+
* - 依赖:
21+
* - m_device: 逻辑设备与队列
22+
* - m_render_pass: 渲染通道
23+
* - 工作:
24+
* - 创建描述符集布局
25+
* - 创建图形管线布局和图形管线
26+
* - 可访问成员:
27+
* - descriptor_set_layout(): 描述符集布局
28+
* - pipeline_layout(): 管线布局
29+
* - pipeline(): 图形管线
30+
*/
31+
class GraphicsPipeline {
32+
std::shared_ptr<vht::Device> m_device;
33+
std::shared_ptr<vht::RenderPass> m_render_pass;
34+
vk::raii::DescriptorSetLayout m_descriptor_set_layout{ nullptr };
35+
vk::raii::PipelineLayout m_pipeline_layout{ nullptr };
36+
vk::raii::Pipeline m_pipeline{ nullptr };
37+
public:
38+
explicit GraphicsPipeline(std::shared_ptr<vht::Device> device, std::shared_ptr<vht::RenderPass> render_pass)
39+
: m_device(std::move(device)),
40+
m_render_pass(std::move(render_pass)) {
41+
init();
42+
}
43+
44+
[[nodiscard]]
45+
const vk::raii::DescriptorSetLayout& descriptor_set_layout() const { return m_descriptor_set_layout; }
46+
[[nodiscard]]
47+
const vk::raii::PipelineLayout& pipeline_layout() const { return m_pipeline_layout; }
48+
[[nodiscard]]
49+
const vk::raii::Pipeline& pipeline() const { return m_pipeline; }
50+
51+
private:
52+
void init() {
53+
create_descriptor_set_layout();
54+
create_graphics_pipeline();
55+
}
56+
// 创建描述符集布局
57+
void create_descriptor_set_layout() {
58+
vk::DescriptorSetLayoutBinding ubo_layout_binging;
59+
ubo_layout_binging.binding = 0;
60+
ubo_layout_binging.descriptorType = vk::DescriptorType::eUniformBuffer;
61+
ubo_layout_binging.descriptorCount = 1;
62+
ubo_layout_binging.stageFlags = vk::ShaderStageFlagBits::eVertex;
63+
64+
vk::DescriptorSetLayoutBinding sampler_layout_binding;
65+
sampler_layout_binding.binding = 1;
66+
sampler_layout_binding.descriptorType = vk::DescriptorType::eCombinedImageSampler;
67+
sampler_layout_binding.descriptorCount = 1;
68+
sampler_layout_binding.stageFlags = vk::ShaderStageFlagBits::eFragment;
69+
70+
auto bindings = { ubo_layout_binging, sampler_layout_binding };
71+
vk::DescriptorSetLayoutCreateInfo layoutInfo;
72+
layoutInfo.setBindings( bindings );
73+
74+
m_descriptor_set_layout = m_device->device().createDescriptorSetLayout( layoutInfo );
75+
}
76+
// 创建图形管线
77+
void create_graphics_pipeline() {
78+
const auto vertex_shader_code = vht::read_shader("shaders/vert.spv");
79+
const auto fragment_shader_code = vht::read_shader("shaders/frag.spv");
80+
const auto vertex_shader_module = vht::create_shader_module(m_device->device(), vertex_shader_code);
81+
const auto fragment_shader_module = vht::create_shader_module(m_device->device(), fragment_shader_code);
82+
vk::PipelineShaderStageCreateInfo vertex_shader_create_info;
83+
vertex_shader_create_info.stage = vk::ShaderStageFlagBits::eVertex;
84+
vertex_shader_create_info.module = vertex_shader_module;
85+
vertex_shader_create_info.pName = "main";
86+
87+
// 1. 数据源
88+
float my_color = 0.4f;
89+
// 2. 特化映射条目
90+
vk::SpecializationMapEntry mapEntry;
91+
mapEntry.constantID = 0; // 对应 GLSL 中的 constant_id 和 SPIR-V 中的 SpecId
92+
mapEntry.offset = 0; // 源数据的起始偏移量
93+
mapEntry.size = sizeof(float);
94+
// 3. 特化信息
95+
vk::SpecializationInfo specializationInfo;
96+
specializationInfo.setMapEntries(mapEntry);
97+
specializationInfo.setData<float>(my_color);
98+
// 此模板设置了 指针 和 数据大小 ,不能放右值
99+
100+
vk::PipelineShaderStageCreateInfo fragment_shader_create_info; // 片段着色器
101+
fragment_shader_create_info.stage = vk::ShaderStageFlagBits::eFragment;
102+
fragment_shader_create_info.module = fragment_shader_module;
103+
fragment_shader_create_info.pName = "main";
104+
fragment_shader_create_info.pSpecializationInfo = &specializationInfo; // 特化信息
105+
106+
const auto shader_stages = { vertex_shader_create_info, fragment_shader_create_info };
107+
108+
const auto dynamic_states = { vk::DynamicState::eViewport, vk::DynamicState::eScissor };
109+
vk::PipelineDynamicStateCreateInfo dynamic_state;
110+
dynamic_state.setDynamicStates(dynamic_states);
111+
112+
auto binding_description = vht::Vertex::get_binding_description();
113+
auto attribute_description = vht::Vertex::get_attribute_description();
114+
vk::PipelineVertexInputStateCreateInfo vertex_input;
115+
vertex_input.setVertexBindingDescriptions(binding_description);
116+
vertex_input.setVertexAttributeDescriptions(attribute_description);
117+
118+
vk::PipelineInputAssemblyStateCreateInfo input_assembly;
119+
input_assembly.topology = vk::PrimitiveTopology::eTriangleList;
120+
121+
vk::PipelineViewportStateCreateInfo viewport_state;
122+
viewport_state.viewportCount = 1;
123+
viewport_state.scissorCount = 1;
124+
125+
vk::PipelineDepthStencilStateCreateInfo depth_stencil;
126+
depth_stencil.depthTestEnable = true;
127+
depth_stencil.depthWriteEnable = true;
128+
depth_stencil.depthCompareOp = vk::CompareOp::eLess;
129+
depth_stencil.depthBoundsTestEnable = false; // Optional
130+
depth_stencil.stencilTestEnable = false; // Optional
131+
132+
vk::PipelineRasterizationStateCreateInfo rasterizer;
133+
rasterizer.depthClampEnable = false;
134+
rasterizer.rasterizerDiscardEnable = false;
135+
rasterizer.polygonMode = vk::PolygonMode::eFill;
136+
rasterizer.lineWidth = 1.0f;
137+
rasterizer.cullMode = vk::CullModeFlagBits::eBack;
138+
rasterizer.frontFace = vk::FrontFace::eCounterClockwise;
139+
rasterizer.depthBiasEnable = false;
140+
141+
vk::PipelineMultisampleStateCreateInfo multisampling;
142+
multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;
143+
multisampling.sampleShadingEnable = false; // default
144+
145+
vk::PipelineColorBlendAttachmentState color_blend_attachment;
146+
color_blend_attachment.blendEnable = false; // default
147+
color_blend_attachment.colorWriteMask = vk::FlagTraits<vk::ColorComponentFlagBits>::allFlags;
148+
149+
vk::PipelineColorBlendStateCreateInfo color_blend;
150+
color_blend.logicOpEnable = false;
151+
color_blend.logicOp = vk::LogicOp::eCopy;
152+
color_blend.setAttachments( color_blend_attachment );
153+
154+
vk::PipelineLayoutCreateInfo layout_create_info;
155+
layout_create_info.setSetLayouts( *m_descriptor_set_layout );
156+
m_pipeline_layout = m_device->device().createPipelineLayout( layout_create_info );
157+
158+
vk::GraphicsPipelineCreateInfo create_info;
159+
create_info.setStages( shader_stages );
160+
161+
create_info.layout = m_pipeline_layout;
162+
163+
164+
create_info.pVertexInputState = &vertex_input;
165+
create_info.pInputAssemblyState = &input_assembly;
166+
create_info.pDynamicState = &dynamic_state;
167+
create_info.pViewportState = &viewport_state;
168+
create_info.pDepthStencilState = &depth_stencil;
169+
create_info.pRasterizationState = &rasterizer;
170+
create_info.pMultisampleState = &multisampling;
171+
create_info.pColorBlendState = &color_blend;
172+
173+
create_info.renderPass = m_render_pass->render_pass();
174+
create_info.subpass = 0;
175+
176+
m_pipeline = m_device->device().createGraphicsPipeline( nullptr, create_info );
177+
}
178+
};
179+
}
180+
181+
Binary file not shown.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#version 450
2+
// 提供默认值 0.0
3+
layout (constant_id = 0) const float myColor = 0.0;
4+
5+
layout(binding = 1) uniform sampler2D texSampler;
6+
7+
layout(location = 0) in vec2 fragTexCoord;
8+
9+
layout(location = 0) out vec4 outColor;
10+
11+
void main() {
12+
outColor = vec4(texture(texSampler, fragTexCoord).xy, myColor, 1.0);
13+
}

docs/images/0411/blue_room.png

237 KB
Loading

docs/images/0411/yellow_room.png

237 KB
Loading

docs/index.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ comments: true
66

77
## **教程简介**
88

9-
本文档是 Vulkan 的入门教程,将系统讲解 Vulkan 图形与计算 API 的基础知识与实际应用。
9+
本文档是 Vulkan 的入门教程,将介绍 Vulkan 图形与计算 API 的基础知识与实际应用。
1010

11-
教程将使用 C++ 编写代码,借助 Vulkan-Hpp 封装,充分利用 RAII 等现代 C++ 特性,减少手动资源管理。
11+
文档以代码演示为主,你可以在 **[Vulkan Guide](https://docs.vulkan.org/guide/latest/index.html)** 等网站找到更详细的 Vulkan 规范和概念介绍。
12+
13+
教程将使用 C++ 编写代码, C++20 标准,使用 Vulkan-SDK 内含的 Vulkan-Hpp 封装,充分利用 RAII 等现代 C++ 特性。
1214

13-
> 注:Vulkan-Hpp 是 Vulkan SDK 的官方组成部分,非第三方库。
1415
> 如果你发现了文档的错误,请点击右上角前往Github仓库,提交 Issue 或 PR 。
1516
1617
## **代码说明**
1718

18-
教程将采用 C++20 标准,主要使用以下工具链:
19+
教程不限操作系统、代码编辑器与 C++ 编译器,主要使用以下工具链:
1920

2021
- [Vulkan SDK](https://lunarg.com/vulkan-sdk/)
2122
- [GLM](http://glm.g-truc.net/) 线性代数库
@@ -29,24 +30,34 @@ comments: true
2930

3031
`Vcpkg` 用于管理第三方库,主要用于安装 `glfw3``glm` 等依赖,这非常简单。
3132

33+
> 教程预期在 C++23 标准完全支持后,使用 23 标准重构内容。
34+
3235
## **其他说明**
3336

3437
Vulkan SDK 本身由 C 编写,因此具有更好的跨语言兼容性,可通过 C 接口供其他语言调用。
3538

3639
如果你更喜欢 C 风格的底层接口,或希望使用 Rust:
3740

38-
- 基于底层C接口的C++教程:[Vulkan-tutorial](https://vulkan-tutorial.com/)
41+
- 基于底层C接口的C++教程: [Vulkan-tutorial](https://vulkan-tutorial.com/)
3942

40-
- 基于Vulkano封装的Rust教程 [Vulkan-tutorial-rs](https://github.com/bwasty/vulkan-tutorial-rs)
43+
- 基于Vulkano封装的Rust教程 [Vulkan-tutorial-rs](https://github.com/bwasty/vulkan-tutorial-rs)
4144

4245
## **致谢**
4346

44-
项目文档与知识点参考以下内容:
47+
本文档内容参考了许多公开的资料以及课程,在此感谢:
48+
49+
- [Vulkan-Hpp](https://github.com/KhronosGroup/Vulkan-Hpp)
4550

46-
- [vulkan-hpp](https://github.com/KhronosGroup/Vulkan-Hpp)
51+
- [Vulkan-Guide](https://docs.vulkan.org/guide/latest/index.html)
4752

4853
- [Vulkan-Tutorial](https://github.com/Overv/VulkanTutorial)
4954

5055
- [EasyVulkan](https://easyvulkan.github.io/index.html)
5156

57+
- [GAMES101-现代计算机图形学入门\(闫令琪\)](https://www.bilibili.com/video/BV1X7411F744)
58+
59+
- [GAMES202-高质量实时渲染\(闫令琪\)](https://www.bilibili.com/video/BV1YK4y1T7yY)
60+
61+
- [GAMES104-现代游戏引擎:从入门到实践\(王希\)](https://games104.boomingtech.com/sc/)
62+
5263
---

docs/md/00/00_intro.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ comments: true
3232
## **学习前提**
3333

3434
### 硬件要求
35-
- 支持 Vulkan 的显卡(NVIDIA/AMD/Intel/Apple Silicon
35+
- 支持 Vulkan 的设备(大部分现代显卡都支持
3636
- 较新的显卡驱动
3737

3838
### 软件技能

docs/md/01/00_base.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ void cleanup() {
148148

149149
---
150150

151+
需要说明的是,基础部分的代码重点用于功能演示,因此可能忽略**可选**的 const 与 static 等 C++ 标识符细节。
152+
但进阶部分会提供尽量优雅的基础代码框架。
153+
151154
这个基础框架为后续开发奠定了良好基础,接下来可以开始初始化 Vulkan 实例和设备。
152155

153156
---

docs/md/01/01_instance.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ private:
2626
2727
现在直接构建与运行程序,请保证程序不出错。
2828
29-
> RAII机制参考“接口介绍”章节。
30-
29+
> 更加详细的 Loader 介绍可以参考 [Vulkan-Guide \[Loader\]](https://docs.vulkan.org/guide/latest/loader.html) 文档。
3130
3231
## **创建实例**
3332
@@ -150,9 +149,9 @@ createInfo.ppEnabledExtensionNames = requiredExtensions.data();
150149
### 2. 特殊setter函数说明
151150

152151
由于数组类型传参时会隐式退化成指针,底层C风格接口都使用“开始指针+元素数量”的方式引用数组。
153-
vulkan-hpp 需要调用底层C接口,所以这些配置信息采用相同的方式记录。
152+
Vulkan-Hpp 需要调用底层C接口,所以这些配置信息采用相同的方式记录。
154153

155-
vulkan-hpp 提供了一些特殊的 `setter` 成员函数,它们通过 `vk::ArrayProxyNoTemporaries` 模板参数简化了数组参数的设置,
154+
Vulkan-Hpp 提供了一些特殊的 `setter` 成员函数,它们通过 `vk::ArrayProxyNoTemporaries` 模板参数简化了数组参数的设置,
156155
这些函数能够自动处理数组参数:
157156

158157
- 接收任意连续容器(`std::vector``std::array`、原生数组)或初始化列表。

docs/md/01/02_validation.md

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,6 @@ Vulkan API 的设计理念: **尽量减少驱动程序开销**
1313

1414
Vulkan 引入了一个优雅的系统来实现程序检查,称为 **验证层\(Validation Layer\)**
1515

16-
它是 Vulkan 的核心调试工具,通过拦截API调用来实现:
17-
18-
- **参数验证**:检查参数合法性和规范符合性
19-
- **资源追踪**:监控资源生命周期和泄漏
20-
- **线程安全**:验证多线程调用合规性
21-
- **性能分析**:记录调用耗时和频率
22-
- **调试输出**:提供详细的运行时信息
23-
2416
以下是诊断验证层中函数实现的一个简化示例
2517

2618
```cpp
@@ -50,12 +42,7 @@ VkResult vkCreateInstance_WithValidation(
5042

5143
你可以**在调试时启用验证层**,在**发布时完全禁用它**,两全其美!!
5244

53-
> Vulkan 本身不附带任何内置的验证层,但 LunarG Vulkan SDK 提供了一组很好的验证层,用于检查常见错误。
54-
> 它们是完全开源的,你可以查看它们能够检查哪些的错误或做出贡献。
55-
>
56-
> Vulkan 以前有两种不同类型的验证层:实例特定和设备特定。
57-
> 设备特定层现在已被弃用,这意味着实例验证层适用于所有 Vulkan 调用。
58-
> 你依然可以启用设备级验证层,但它会被最新的 API 忽略。
45+
> Vulkan 本身不附带任何内置的验证层,但 LunarG Vulkan SDK 提供了一组开源的验证层,用于检查常见错误。
5946
6047
## **使用验证层**
6148

@@ -133,11 +120,13 @@ void createInstance() {
133120

134121
```cpp
135122
if (enableValidationLayers) {
123+
// 使用 setter 同时设置指针和数量两个成员变量
136124
createInfo.setPEnabledLayerNames( validationLayers );
137125
}
138126
```
139127

140-
> 我们用了上一节提到的 `setter` ,它实际设置了指针和数量这两个成员变量。
128+
> Vulkan 以前有两种不同类型的“层\(layer\)”:实例特定和设备特定。
129+
> 设备特定层现在已被弃用,这意味着实例验证层适用于所有 Vulkan 调用。
141130
142131
## **设置调试回调**
143132

@@ -195,7 +184,7 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageFunc(
195184
}
196185
```
197186
198-
此函数只做了一件事,把验证层反馈数据中的信息输出到标准错误流。
187+
此函数只做了一件事,把验证层反馈数据中的信息输出到标准错误流,你可以自行添加内容
199188
200189
### 3. 函数参数说明
201190

docs/md/01/03_physicaldevice.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ comments: true
44
---
55
# **物理设备与队列族**
66

7-
在创建实例之后,我们需要查找并选择系统中合适的物理设备\(通常指 GPU \)
7+
在创建实例之后,我们需要查找并选择系统中合适的物理设备\(常指显卡\)
88
实际上,我们可以选择任意数量的显卡并同时使用它们,但在本教程中,我们只使用第一张满足我们需求的显卡。
99

10+
> 相关概念:[Vulkan-Guide \[Querying Properties, Extensions, Features ...\]](https://docs.vulkan.org/guide/latest/querying_extensions_features.html)
11+
1012
## **选择物理设备**
1113

1214
### 1. 成员变量与辅助函数
@@ -143,12 +145,15 @@ bool isDeviceSuitable(const vk::raii::PhysicalDevice& physicalDevice) {
143145
144146
Vulkan 中的几乎每个操作,从绘制到上传纹理,都需要将命令提交到队列。
145147
146-
### 1. 队列查找函数
147148
148149
队列有不同的类型,这些类型源自不同的队列族,并且每个队列族仅允许一些特定的命令。
149150
例如,可能有一个队列族仅允许处理计算命令,或者一个队列族仅允许与内存传输相关的命令。
150151
151-
为此,我们将添加一个新函数 `findQueueFamilies` ,用于查找我们需要的所有队列族。
152+
> 更详细的概念:[Vulkan-Guide \[Queues\]](https://docs.vulkan.org/guide/latest/queues.html)
153+
154+
### 1. 队列查找函数
155+
156+
我们需要添加一个新函数 `findQueueFamilies` ,用于查找我们需要的所有队列族。
152157
153158
现在我们只打算查找支持图形命令的队列族,因此该函数可能如下所示:
154159

0 commit comments

Comments
 (0)