Skip to content

Commit 3994080

Browse files
committed
Improve 2
1 parent 3ae74f0 commit 3994080

9 files changed

+132
-120
lines changed

README.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,51 +31,55 @@
3131

3232
**文档网站:<https://mysvac.github.io/vulkan-hpp-tutorial>**
3333

34-
备用\(更新滞后\)<https://vulkan.mysvac.com>
34+
备用站点<https://vulkan.mysvac.com>
3535

36-
**注意:文档正在制作、重构与改善中。**
36+
> 注意:文档代码已经完善,部分文字描述正在改善中。
3737
3838
### 教程简介
3939

4040
本教程是 Vulkan 的入门教程,将系统讲解 Vulkan 图形与计算 API 的基础知识与实际应用。
4141

4242
教程将使用 C++ 编写代码,借助 Vulkan-Hpp 封装,充分利用 RAII 等现代 C++ 特性。
4343

44-
> 注:Vulkan-Hpp 是 Vulkan SDK 的官方组成部分,非第三方库
44+
> 注:Vulkan-Hpp 是 Vulkan SDK 的官方组成部分,非第三方库
4545
4646
**教程大致内容如下:**
4747

4848
1. 介绍基础概念
4949
2. 配置开发环境
5050
3. 绘制第一个三角形
51-
4. 实现高级功能
51+
4. 扩展基础功能
5252

5353
### 项目结构
54-
- `src` 中存放Cpp完整代码。
55-
- `shaders`中存放shader代码。
56-
- `docs` 中存放文档
57-
- `md` 中存放教程文档。
58-
- `images` 相关图片资源
59-
- `codes` 中存放每一节的代码和差异文件。
54+
55+
- `src` 存放C++完整代码
56+
- `shaders` 存放shader代码
57+
- `texture` 存放纹理图片
58+
- `models` 存放模型文件
59+
- `docs` 存放静态站点相关资源
60+
- `md` 存放教程文档
61+
- `images` 图片资源
62+
- `res` 其他资源
63+
- `codes` 每一节的代码和差异文件。
6064

6165

6266
### 代码说明
6367

64-
教程将使用 C++ 编写代码,使用C++20标准,并使用以下工具链:
68+
教程将使用 C++ 编写代码,采用C++20标准,并使用以下工具链:
6569

6670
- [Vulkan SDK](https://lunarg.com/vulkan-sdk/)
6771
- [GLM](http://glm.g-truc.net/) 线性代数库
6872
- [GLFW](http://www.glfw.org/) 窗口库
6973
- [CMake](https://cmake.org/) 构建系统
7074
- [vcpkg](https://vcpkg.io/) 依赖管理
7175

72-
正如教程名,我还会使用 Vulkan SDK 为C++提供的 `vulkan-hpp` 封装,且使用内部的 `raii` 封装,使用更加现代的C++接口。
76+
正如教程名,我们会使用 Vulkan SDK 为C++提供的 `vulkan-hpp` `raii` 封装,它提供了更现代的C++接口。
7377

7478

75-
虽然 `vulkan-hpp` 提供了模块支持,但是我们还需要使用 `glfw3` 库和 `glm` 库,将他们模块化是比较繁琐的
76-
这超出了本教程的目的,因此不使用C++20的模块功能。
79+
虽然 `vulkan-hpp` 提供了模块支持,但是我们还需要使用 `glfw3` 库和 `glm` 库,将它们模块化是比较繁琐的
80+
这超出了本教程的范围,因此不使用C++20的模块功能。
7781

78-
> C++23 的标准库模块与标准库头文件似乎是冲突的,这很可能导致显著延缓C++模块化的发展
82+
> C++23 的标准库模块与标准库头文件似乎是冲突的,这很可能显著延缓C++社区模块化的进度
7983
8084
`CMake` 用于项目构建,实现跨平台的项目,但要求读者了解CMake基础使用。
8185

@@ -93,7 +97,7 @@ Vulkan SDK本身由C编写,这带来更好的跨语言能力,可以其他语
9397

9498

9599

96-
### 参考资料
100+
### 项目参考资料
97101

98102
Vulkan-hpp文档 [vulkan-hpp](https://github.com/KhronosGroup/Vulkan-Hpp)
99103

docs/index.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
- [CMake](https://cmake.org/) 构建系统
2727
- [vcpkg](https://vcpkg.io/) 依赖管理
2828

29-
正如教程名,我会使用 Vulkan SDK 为C++提供的 `vulkan-hpp` 封装,且使用内部的 `raii` 封装,它提供了更现代的C++接口。
30-
29+
正如教程名,我们会使用 Vulkan SDK 为C++提供的 `vulkan-hpp``raii` 封装,它提供了更现代的C++接口。
3130

3231
虽然 `vulkan-hpp` 提供了模块支持,但是我们还需要使用 `glfw3` 库和 `glm` 库,将它们模块化是比较繁琐的,
3332
这超出了本教程的范围,因此不使用C++20的模块功能。

docs/md/0140_recreateswapchain.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
## **前言**
44

55
现在我们已经成功绘制了第一个三角形,但是还有些特殊情况没有处理。
6-
当窗口表面发送变化时,交换链可能不再适配窗口表面。一种可能的原因是窗口被调整,我们需要捕获此事件并重建交换链。
6+
当窗口表面发送变化时,交换链可能不再适配窗口表面。
7+
一种可能的原因是窗口大小被调整,我们需要捕获此事件并重建交换链。
78

89
## **重建交换链**
910

docs/md/0200_vertexinput.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# 顶点输入描述
1+
# **顶点输入描述**
22

3-
## 前言
3+
## **前言**
44

5-
在后面几章,我们将使用内存中的顶点缓冲数据代替Shader中的硬编码数据
5+
在后面几章,我们将使用内存中的顶点缓冲区\(vertex buffers\)数据代替Shader中的硬编码数据
66

7-
我们将从最简单的方式开始,创建CPU可见缓冲然后直接用`memcpy`将顶点数据复制进去。
8-
之后我们将了解如何使用暂存缓冲将顶点数据复制进高性能显存中
7+
我们将从最简单的方式开始,创建CPU可见缓冲区然后直接用 `memcpy` 将顶点数据复制进去。
8+
之后我们将了解如何使用暂存缓冲区\(staging buffers\)将顶点数据复制进高性能显存中
99

10-
## 顶点着色器
10+
## **顶点着色器**
1111

1212
首先我们需要改变顶点着色器的代码,不再包含硬编码的顶点数据。
1313
顶点数据将从外部获取,通过`in`关键字:
@@ -29,7 +29,7 @@ void main() {
2929
`inPosition``inColor` 是顶点参数,是每个顶点在顶点缓冲中指定的属性。
3030

3131
我们之前提过,一个`location`只能放一个资源,所以我们的位置和颜色信息需要放在不同的`location`中。
32-
我们通过输入接收了资源,所以`location = 0`暂时空了,可以用于输出
32+
注意 `inPosition` 是外部->顶点着色器,`fragColor`是顶点着色器->片段着色器,所以二者不冲突
3333

3434
特殊的是,某些类型需要多个槽位,比如使用`dvec3`时,后一个变量的索引至少要高2:
3535

@@ -40,7 +40,7 @@ layout(location = 2) in vec3 inColor;
4040

4141
您可以在 [OpenGL wiki](https://www.khronos.org/opengl/wiki/Layout_Qualifier_(GLSL)) 中找到有关 layout 限定符的更多信息。
4242

43-
## 顶点数据
43+
## **顶点数据**
4444

4545
现在回到C++代码,我们要将顶点数据从着色器代码移动到C++程序代码的数组中。
4646

@@ -72,12 +72,12 @@ inline static const std::vector<Vertex> vertices = {
7272
};
7373
```
7474

75-
我们使用的位置和颜色值与之前完全相同,但现在它们组合成一个顶点数组这被称为*交错*顶点属性
75+
我们使用的位置和颜色值与之前完全相同,但现在它们组合成一个顶点数组这被称为“交错顶点属性”
7676

7777
下一步要告诉 Vulkan 这些数据上传到GPU内存后如何传递给顶点着色器。
7878
我们需要两个结构体传达这些信息。
7979

80-
## 绑定描述
80+
## **绑定描述**
8181

8282
第一个结构体是 `vk::VertexInputBindingDescription` ,我们添加一个静态成员函数用于填充信息:
8383

@@ -94,7 +94,7 @@ struct Vertex {
9494
};
9595
```
9696

97-
顶点绑定描述了从内存中通过顶点集合加载顶点的速率
97+
顶点绑定描述结构体描述了从内存中通过顶点集合加载顶点的“速率”
9898
它规定了单个数据条目的字节数,以及要在每个顶点还是每个实例时读取一条数据。
9999

100100
```cpp
@@ -109,14 +109,14 @@ bindingDescription.inputRate = vk::VertexInputRate::eVertex;
109109

110110
`inputRate`参数具有以下两种枚举值:
111111

112-
| 枚举 | 意义 |
112+
| `vk::VertexInputRate` | 意义 |
113113
|------|------|
114114
| `eVertex` | 在处理每个顶点时读取一条 |
115115
| `eInstance` | 在处理每个实例时读取一条 |
116116

117117
我们不会使用实例化渲染,因此使用每个顶点读取一条。实际我们每条数据就对应一个顶点。
118118

119-
## 属性描述
119+
## **属性描述**
120120

121121
第二个结构体是 `vk::VertexInputAttributeDescription` ,它描述了如何处理顶点的输入数据。
122122
我们依然添加一个静态成员函数:
@@ -169,7 +169,7 @@ attributeDescriptions[1].offset = offsetof(Vertex, color);
169169

170170
> 注意这里的`format`对应的是`vec3`。
171171

172-
## 管线顶点输入
172+
## **管线顶点输入**
173173

174174
我们现在需要设置图形管线的配置,让它接收这些数据。现在修改`createGraphicsPipeline`函数,找到`vertexInputInfo`变量并添加信息:
175175

@@ -183,7 +183,7 @@ vertexInputInfo.setVertexBindingDescriptions(bindingDescription);
183183
vertexInputInfo.setVertexAttributeDescriptions(attributeDescriptions);
184184
```
185185

186-
## 最后
186+
## **最后**
187187

188188
现在管线已准备好接受指定格式的顶点数据并将其传递给顶点着色器。
189189

docs/md/0201_vertexbuffer.md

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
# 创建顶点缓冲
1+
# **创建顶点缓冲**
22

3-
## 前言
3+
## **前言**
44

55
缓冲(Buffers)在 Vulkan 中是一个用于存储任意数据的区域,它可以被显卡读取。
66
在本节中,我们将用它存储顶点数据。
77
与其他的 Vulkan 对象不同,缓冲并不会自动分配内存。
88
我们在之前的章节中见识到了Vulkan API的可控性,内存管理也是其中之一。
99

10-
## 创建缓冲
10+
> 本教程中有时叫它“缓冲区”,但大多数时候直接称为“缓冲”,二者是一样的。
11+
12+
## **创建缓冲**
1113

1214
`initVulkan`中创建一个新的函数`createVertexBuffer`,放在`createCommandBuffers`之前:
1315

@@ -46,7 +48,7 @@ vk::BufferCreateInfo bufferInfo;
4648
bufferInfo.size = sizeof(vertices[0]) * vertices.size();
4749
```
4850

49-
第二个参数是`usage`,它表示这些数据的用途。它本身是个位枚举,可以同时表示多种用途
51+
第二个参数是`usage`,它表示这些数据的用途,可以是多个位掩码的组合
5052
我们需要的是顶点缓冲,所以可以这样写:
5153

5254
```cpp
@@ -88,7 +90,7 @@ void createVertexBuffer() {
8890
}
8991
```
9092

91-
## 内存需求
93+
## **内存需求**
9294

9395
虽然缓冲已经创建了,但它实际还未分配任何内存。分配内存的第一步是查询他的内存需求量:
9496

@@ -104,8 +106,8 @@ vk::MemoryRequirements memRequirements = m_vertexBuffer.getMemoryRequirements();
104106
| `alignment` | 内存对齐方式,取决于`bufferInfo.usage``bufferInfo.flags` |
105107
| `memoryTypeBits` | 适用于缓冲的内存类型的位字段 |
106108

107-
显卡可以分配不同类型的内存,这些不同的内存类型可能有不同的操作或性能表现。
108-
我们需要结合需求寻找正确的内存类型,现在让我们创建新函数`findMemoryType`
109+
显卡可以分配不同类型的内存\(显存\),这些不同的内存类型可能有不同的操作或性能表现。
110+
我们需要根据需求寻找合适的内存类型,现在让我们创建新函数`findMemoryType`
109111

110112
```cpp
111113
uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties) {
@@ -120,11 +122,10 @@ uint32_t findMemoryType(uint32_t typeFilter, vk::MemoryPropertyFlags properties)
120122
auto memProperties = m_physicalDevice.getMemoryProperties();
121123
```
122124

123-
> `2`位后缀的类型大多数是在原基础上支持了`pNext`指针,我们使用普通函数即可。
124-
125125
`vk::PhysicalDeviceMemoryProperties`结构体中有两个数组 `memoryTypes``memoryHeaps`
126-
第二个数组内存堆是不同的内存资源,比如VRAM耗尽时专用于VRAM和RAM交换的空间。而不同的内存类型存在于这些堆中。
127-
现在我们只关心类型而不关心它来自哪个堆,但显然这也会影响性能。
126+
第二个数组“内存堆”是不同的内存资源,比如VRAM耗尽时专用于VRAM和RAM交换的空间。而不同的内存类型存在于这些堆中。
127+
128+
作为初学者,我们现在只关心类型而不关心它来自哪个堆,但需要记得后者其实也会影响性能。
128129

129130
让我们找一个合适的内存类型:
130131

@@ -155,7 +156,7 @@ for(uint32_t i = 0; i < memProperties.memoryTypeCount; ++i){
155156
}
156157
```
157158

158-
## 内存分配
159+
## **内存分配**
159160

160161
现在我们有办法找到正确的内存类型了,将这些信息都记入 `vk::MemoryAllocateInfo` 结构体中。
161162

@@ -167,7 +168,7 @@ allocInfo.memoryTypeIndex = findMemoryType( memRequirements.memoryTypeBits,
167168
);
168169
```
169170

170-
`eHostVisible` 表示可以被CPU访问`eHostCoherent` 表示内存自动同步。
171+
`eHostVisible` 表示可以被CPU\(主机\)访问`eHostCoherent` 表示内存自动同步。
171172

172173
分配内存非常简单,我们首先在 `m_vertexBuffer` **上方**创建一个新变量,然后使用 `allocateMemory` 分配资源:
173174

@@ -188,9 +189,9 @@ m_vertexBufferMemory = m_device.allocateMemory( allocInfo );
188189
m_vertexBuffer.bindMemory(m_vertexBufferMemory, 0);
189190
```
190191

191-
右边的`0`是内存区域内的偏移量,通过此变量可以让一块内存分成多个区域。此内存转为顶点缓冲分配,偏移量应为0。
192+
右边的`0`是内存区域内的偏移量,通过此变量可以让一块内存分成多个区域。此内存专为顶点缓冲分配,偏移量应为0。
192193

193-
## 填充顶点缓冲
194+
## **填充顶点缓冲**
194195

195196
现在是时候把顶点数据拷贝到缓冲中了。我们使用`mapMemory`获取内存地址指针:
196197

@@ -225,7 +226,7 @@ m_vertexBufferMemory.unmapMemory();
225226
刷新内存范围和使用一致性内存堆意味着驱动程序可以注意到我们写入了缓冲,但这不意味着在GPU上可见。
226227
GPU上的数据转移是个隐含的过程,规范只[告诉我们](https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/chap7.html#synchronization-submission-host-writes),它保证在下次调用`queue.submit`时完成。
227228
228-
## 绑定顶点缓冲
229+
## **绑定顶点缓冲**
229230
230231
剩下的就是在渲染操作期间绑定顶点缓冲,我们扩展`recordCommandBuffer`函数来执行此操作。
231232
@@ -245,7 +246,7 @@ commandBuffer.draw(static_cast<uint32_t>(vertices.size()), 1, 0, 0);
245246
`bindVertexBuffers`的第一个参数指定顶点缓冲绑定点的偏移量。
246247
我们还修改了`draw`,传递缓冲中得到顶点数,而不是硬编码的`3`
247248

248-
## 测试
249+
## **测试**
249250

250251
现在运行程序,你应该可以看到熟悉的三角形:
251252

0 commit comments

Comments
 (0)