Skip to content

Commit da0c7e7

Browse files
committed
Improve
1 parent 1c43532 commit da0c7e7

12 files changed

+53
-41
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@
3131

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

34-
**注意:文档内容暂不完善,正在制作、重构与改善中。**
35-
36-
> 本文档可能使用AI优化语言组织,请注意甄别错误!
34+
**注意:文档正在制作、重构与改善中。**
3735

3836
### 教程简介
3937

docs/md/0000_intro.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
### 什么是 Vulkan?
66

7-
Vulkan 是 [Khronos Group](https://www.khronos.org/) 推出的**现代图形与计算 API** 。与传统 API (如[OpenGL](https://en.wikipedia.org/wiki/OpenGL)[Direct3D](https://en.wikipedia.org/wiki/Direct3D))相比,它为显卡提供了更好的抽象,使你可以更好的描述应用程序的行为,从而带来更好的性能和减少意外的驱动程序行为。
7+
Vulkan 是 [Khronos Group](https://www.khronos.org/) 推出的**现代图形与计算 API**。与传统 API (如[OpenGL](https://en.wikipedia.org/wiki/OpenGL)[Direct3D](https://en.wikipedia.org/wiki/Direct3D))相比,它为显卡提供了更好的抽象,使你可以更好的描述应用程序的行为,从而带来更好的性能和减少意外的驱动程序行为。
88

99
### 与传统API的关键差异
1010

@@ -15,7 +15,7 @@ Vulkan 是 [Khronos Group](https://www.khronos.org/) 推出的**现代图形与
1515
| 着色器编译 | 运行时GLSL编译 | 预编译SPIR-V字节码 |
1616
| 内存管理 | 驱动自动分配 | 开发者控制内存类型 |
1717

18-
这些好处的代价是您必须使用更细致的 API,每个细节都需要由您的应用程序从头开始设置,这意味着您必须在应用程序中执行更多工作以确保正确的行为。
18+
这些好处的代价是你必须使用更细致的 API,每个细节都需要由您的应用程序从头开始设置,这意味着您必须在应用程序中执行更多工作以确保正确的行为。
1919

2020
### 什么人适合Vulkan
2121

@@ -67,7 +67,7 @@ Vulkan 采用"默认高性能"的设计哲学,其调试系统具有以下关
6767

6868
我们现在在玩一款沙盒游戏,我们的目标是让一些机器人自动画画并提交画作。
6969

70-
1. 首先我们需要创建一个新世界,初始化天空地面机器人之类的设置。这就是实例 `VkInstance`
70+
1. 首先我们需要创建一个新世界,初始化天空地面和机器人之类的设置。这就是实例 `VkInstance`
7171

7272
2. 我们希望有东西帮我们检查错误,这就是验证层 `Validation Layer`
7373

@@ -91,7 +91,7 @@ Vulkan 采用"默认高性能"的设计哲学,其调试系统具有以下关
9191

9292
12. 现在机器人终于可以画画了,我们要为他准备一个画架,用来放画纸。这个画架就是帧缓冲`VkFrameBuffer`,一帧代指一副图像。
9393

94-
13. 我们还要为机器人设计一个房子,房子里放着画笔、颜料等工具,还有一台用于清洗(重置)画纸的机器。这个房子就是渲染通道`VkRenderPass`这些画笔和机器之类的就是附件`Attachments`
94+
13. 我们还要为机器人设计一个房子,房子里放着画笔、颜料等工具,还有一台用于清洗(重置)画纸的机器。这个房子就是渲染通道`VkRenderPass`而画笔和机器等工具就是附件`Attachments`
9595

9696
14. 当画作变得更加复杂,我们可以在一个房子里放多个小房间,每个房间干不同的事情,这些小房间就是子通道`VkSubpass`
9797

@@ -120,6 +120,6 @@ Vulkan 采用"默认高性能"的设计哲学,其调试系统具有以下关
120120

121121
---
122122

123-
准备好投入高性能图形 API 的未来了吗? 让我们开始吧!
123+
准备好投入高性能图形API的未来了吗?让我们开始吧!
124124

125125
---

docs/md/0001_env.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# 开发环境
22

33
## 概述
4-
本文将指导您完成Vulkan应用程序开发环境的设置,包括安装必要的工具和库。
4+
本文将指导你完成Vulkan应用程序开发环境的设置,包括安装必要的工具和库。
55

66
注意,CMake和Vcpkg自身的安装,以及MSVC/Clang等编译器的安装,不是本教程的内容。
77

docs/md/0100_base.md

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ private:
121121
```
122122
123123
`glfwCreateWindow` 前三个参数指定窗口的宽度、高度和标题。
124-
第四个参数允许您选择性地指定要在其上打开窗口的监视器,最后一个参数仅与 OpenGL 相关。
124+
第四个参数可以指定显示器以及是否全屏,最后一个参数仅与 OpenGL 相关。
125125
126-
> `m_`用于区分是不是成员变量*
126+
> `m_`用于区分是不是成员变量
127127
128128
### 4. 添加主循环
129129
@@ -138,7 +138,7 @@ void mainLoop() {
138138
它循环并检查事件,例如按下 `X` 按钮,直到窗口被用户关闭。
139139

140140
### 5. 清理资源
141-
一旦窗口关闭,我们需要通过销毁窗口并终止 GLFW 本身来清理资源
141+
一旦窗口关闭,我们需要销毁窗口并终止 GLFW 本身从而清理资源
142142

143143
```cpp
144144
void cleanup() {
@@ -147,10 +147,6 @@ void cleanup() {
147147
}
148148
```
149149

150-
## 尝试运行
151-
152-
现在运行程序,您应该看到一个标题为 Vulkan 的窗口出现,直到应用程序在窗口关闭时终止。
153-
154150
## 代码结构解析
155151

156152
| 组件 | 功能说明 |
@@ -160,6 +156,11 @@ void cleanup() {
160156
| `mainLoop()` | 处理事件和渲染循环 |
161157
| `cleanup()` | 释放所有资源 |
162158

159+
160+
## 尝试运行
161+
162+
现在运行程序,您应该看到一个标题为 Vulkan 的窗口出现,直到应用程序在窗口关闭时终止。
163+
163164
---
164165

165166
这个基础框架为后续Vulkan开发奠定了良好基础,接下来可以开始初始化Vulkan实例和设备。

docs/md/0101_instance.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
## RAII上下文初始化
44

5-
### 1. 创建Context对象
6-
75
`vk::raii::Context` 的作用是 初始化 Vulkan 的动态加载层(Loader),并提供 Vulkan 函数指针的加载功能。它是 RAII 封装的基础。
86

97
**要求:**
@@ -50,7 +48,7 @@ void createInstance(){
5048
}
5149
```
5250

53-
> 上面提到大部分 `raii` 资源不支持无参构造,要使用 `nullptr` 初始化表示无效值
51+
> 之前提到大部分 `raii` 资源不支持无参构造,要使用 `nullptr` 初始化表示无效值
5452
5553
### 2. 添加应用程序信息
5654

@@ -81,7 +79,7 @@ applicationInfo.setApplicationVersion(1); // or use setter()
8179
8280
### 2. 配置基础创建信息
8381

84-
前面提到,Vulkan中资源的创建都依赖对应的 `CreateInfo` 结构体,我们必须先填写它。
82+
Vulkan中资源的创建都依赖对应的 `CreateInfo` 结构体,我们必须先填写它。
8583

8684
```cpp
8785
vk::InstanceCreateInfo createInfo(
@@ -124,7 +122,7 @@ m_instance = vk::raii::Instance( m_context, createInfo );
124122

125123
Vulkan 是一个平台无关的 API,这意味着您需要一个扩展来处理窗口系统接口。
126124

127-
### 1. 获取所需扩展与修改CreateInfo
125+
### 1. 获取所需扩展
128126

129127
GLFW 有一个方便的内置函数,可以返回它需要的扩展,我们可以将其传递给结构体
130128

@@ -143,7 +141,7 @@ createInfo.setPEnabledExtensionNames( requiredExtensions );
143141
```cpp
144142
// 扩展的数量
145143
createInfo.enabledExtensionCount = static_cast<uint32_t>(requiredExtensions.size());
146-
// 扩展名数组,每个扩展名都是个字符串字面量
144+
// 扩展名数组首地址指针
147145
createInfo.ppEnabledExtensionNames = requiredExtensions.data();
148146
```
149147

@@ -187,21 +185,19 @@ vulkan-hpp 提供了一些特殊的 `setter` 成员函数,它们通过 `vk::Ar
187185

188186
通常代码可能如下所示
189187
```cpp
190-
// ......
191188
std::vector<const char*> requiredExtensions( glfwExtensions, glfwExtensions + glfwExtensionCount );
192189
requiredExtensions.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
193190

194191
createInfo.setPEnabledExtensionNames( requiredExtensions );
195192
createInfo.flags |= vk::InstanceCreateFlagBits::eEnumeratePortabilityKHR;
196-
// ......
197193
```
198194
199195
现在重新尝试构建与运行项目,不应该出现错误。
200196
201197
202198
## 检查扩展支持
203199
204-
不支持扩展时,创建 `instance` 就会抛出异常,异常代码为 `vk::Result::eErrorExtensionNotPresent`。
200+
有扩展不支持时,创建实例会抛出异常,异常代码为 `vk::Result::eErrorExtensionNotPresent`。
205201
206202
我们可以主动检查哪些扩展是支持的,使用 `enumerateInstanceExtensionProperties` 函数,会返回一个 `std::vector` ,表示支持的扩展类型。
207203
@@ -247,7 +243,7 @@ for (const auto& extension : extensions) {
247243

248244
---
249245

250-
在继续实例创建之后更复杂的步骤之前,是时候通过查看验证层来评估我们的调试选项了
246+
在继续实例创建之后更复杂的步骤之前,是时候通过验证层来评估我们的程序了
251247

252248
---
253249

docs/md/0102_validation.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Vulkan API 的设计理念: **尽量减少驱动程序开销**
77
这导致 **默认情况下 API 中的错误检查非常有限**
88

99
Vulkan要求你对所做的一切都非常明确,因此很容易犯许多小错误,例如使用新的 GPU 功能,却忘记在逻辑设备创建时请求它。
10-
但是及时像将 "错误的枚举值" 或 "错误的空指针" 这样简单的错误,通常也不会被显式处理,只会导致崩溃或未定义的行为。
10+
即使像 "错误的枚举值" 或 "错误的空指针" 这样简单的错误,通常也不会被显式处理,只会导致崩溃或未定义的行为。
1111

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

@@ -88,8 +88,8 @@ static constexpr std::array<const char*,1> validationLayers {
8888

8989
> `NDEBUG` 宏是 C++ 标准的一部分,意思是“非调试”。
9090
>
91-
> 常量静态成员与静态数据成员的内容,此处不介绍,可参考[cppref-静态成员](https://zh.cppreference.com/w/cpp/language/static)
92-
> 你也可以全部使用`constexpr`,自带内联,保证是常量对象可ODR使用。
91+
> 常量静态成员的内容,此处不介绍,可参考[cppref-静态成员](https://zh.cppreference.com/w/cpp/language/static)
92+
> 你也可以全部使用`inline static const`,保证是常量对象可ODR使用。
9393
9494
### 2. 验证层可用性检查
9595

@@ -177,7 +177,7 @@ std::vector<const char*> getRequiredExtensions() {
177177
}
178178
```
179179

180-
> 此处使用了 `VK_EXT_DEBUG_UTILS_EXTENSION_NAME` 宏,它等于字符串 `"VK_EXT_debug_utils"`
180+
> 此处使用了 `VK_EXT_DEBUG_UTILS_EXTENSION_NAME` 宏,它等于字符串 `"VK_EXT_debug_utils"`
181181
182182
现在可以在 `createInstance` 中使用此函数简化代码:
183183

docs/md/0104_device.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ m_device = m_physicalDevice.createDevice( createInfo );
112112
vk::raii::Queue m_graphicsQueue{ nullptr };
113113
```
114114
115-
我们可以使用 `device->getQueue` 成员函数来检索每个队列族的队列句柄
115+
我们可以使用 `getQueue` 成员函数来获取每个队列族的队列句柄
116116
参数是队列族和队列索引。因为我们只从此队列族创建一个队列,所以简单地使用索引 `0`。
117117
```c++
118118
m_graphicsQueue = m_device.getQueue( indices.graphicsFamily.value(), 0 );

docs/md/0111_swapchain.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ vk::SurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<vk::SurfaceFormat
193193
|------|-----|
194194
| `eImmediate` | 图像会立即传输到屏幕,可能会导致图像撕裂。 |
195195
| `eFifo` | 先进先出的队列。若队列已满,则程序必须等待。 |
196-
| | 这与现代游戏中的垂直同步最相似。显示刷新的时刻称为“垂直消隐”。 |
196+
| | 这与现代游戏中的垂直同步最相似。显示刷新的时刻称为“垂直消隐”。 |
197197
| `eFifoRelaxed` | 第二种的变体,图像在最终到达时立即传输,可能会导致明显的撕裂。 |
198198
| | 仅当应用程序迟到且队列在上次垂直消隐时为空,此模式才与前一种模式不同。 |
199199
| `eMailbox` | 第二种的变体,队列已满时将已排队的图像简单地替换为较新的图像。 |

docs/md/0120_pipeline.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
固定功能阶段允许您使用参数调整其操作,但它们的工作方式是预定义的。
4040

4141
可编程阶段(`programmable`)意味着您可以将自己的代码上传到显卡,以精确地应用您想要的操作。
42-
这使您可以使用片段着色器,例如实现从纹理和光照到光线追踪器的任何功能。这些程序在许多 GPU 核心上同时运行,以并行处理许多对象,例如顶点和片段。
42+
这使您可以使用着色器代码实现从纹理和光照到光线追踪的任何功能。这些程序在许多 GPU 核心上同时运行,以并行处理许多对象,例如顶点和片段。
4343

4444
如果您以前使用过像 OpenGL 和 Direct3D 这样的旧 API,那么您会习惯于使用像 `glBlendFunc`` OMSetBlendState`这样的调用随意更改任何管线设置。
4545
Vulkan 中的图形管线几乎是完全不可变的,因此如果您想更改着色器、绑定不同的帧缓冲或更改混合功能,则必须从头开始重新创建管线。
@@ -54,7 +54,8 @@ Vulkan 中的图形管线几乎是完全不可变的,因此如果您想更改
5454
例如,如果您只是绘制简单的几何体,则可以禁用细分和几何阶段。
5555
如果您只对深度值感兴趣,则可以禁用片段着色器阶段,这对于 阴影贴图 生成很有用。
5656

57-
在下一章中,我们将首先创建将三角形放到屏幕上所需的两个可编程阶段:顶点着色器和片段着色器。
57+
在下一章中,我们将创建将三角形放到屏幕上所需的两个可编程阶段:顶点着色器和片段着色器。
58+
5859
混合模式、视口、光栅化等固定功能配置将在之后的章节中设置。
5960
在 Vulkan 中设置图形管线的最后一部分还涉及输入和输出帧缓冲的规范。
6061

docs/md/0121_shader.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ GLSL是一种具有C风格语法的着色语言。
3131
比如顶点着色器会对每个顶点调用一遍主函数,片段着色器则是对每个片段(像素)调用一遍主函数。
3232

3333
与常规编程语言不同,GLSL并不依赖参数输入和返回值输出,而是通过全局变量来实现输入与输出操作。
34-
语言本身隐含了一些变量用于接受和输出顶点颜色等数据,还可以定义一些全局变量传输自己需要的数据,你很快就会看到。
34+
语言本身隐含了一些变量用于输入和输出顶点颜色等数据,还可以定义一些全局变量传输自己需要的数据,你很快就会看到。
3535

3636

3737
## 创建着色器代码文件
@@ -136,7 +136,7 @@ GLSL 中的颜色是 4 分量向量,R、G、B 和 alpha 通道在 [0, 1] 范
136136
红色被写入此 `outColor` 变量,该变量链接到索引 `0` 处的第一个(也是唯一的)帧缓冲。
137137

138138
> 注意,in和out的变量名是不重要的,重要的是变量类型和location的值。
139-
> 只有保证类型和location都一致,就能一个地方out,另一个地方in。
139+
> 只要保证类型和location都一致,就能一个地方out,另一个地方in。
140140
> 一个location不能同时放置多个数据。
141141
142142
### 3. 逐顶点颜色
@@ -179,8 +179,7 @@ void main() {
179179
}
180180
```
181181

182-
输入变量不一定需要使用相同的名称,它们将使用 `location` 指令指定的索引链接在一起。
183-
`main` 函数已修改为输出颜色以及 `alpha` 值。如上图所示,`fragColor` 的值将为三个顶点之间的片段自动插值,从而产生平滑的渐变。
182+
`main` 函数已修改为输出颜色以及 `alpha` 值。图形管线将使用三个顶点的数据,自动插值生成内部片段的`fragColor` ,从而产生平滑的渐变。
184183

185184
### 4. 编译着色器
186185

@@ -244,6 +243,8 @@ xxx/VulkanSDK/x.x.x.x/Bin/glslc.exe shader.frag -o frag.spv
244243
在命令行上编译着色器是最直接的选择之一,也是我们将在本教程中使用的选择,但也可以直接从您自己的代码中编译着色器。
245244
Vulkan SDK 包含 libshaderc,这是一个从您的程序中将 GLSL 代码编译为 SPIR-V 的库。
246245

246+
### 5. CMake编译着色器
247+
247248
直接命令行显然不够优秀,且写明路径导致无法跨平台,所以我们借助CMake执行命令。
248249

249250
现在让我们在 `shaders/` 文件夹中创建新的 `CMakeLists.txt`,内容如下所示:
@@ -352,6 +353,8 @@ void createGraphicsPipeline() {
352353
我们通过打印缓冲区的大小并检查它们是否与字节的实际文件大小匹配,确保着色器已正确加载。
353354

354355
> 注意我们使用了相对路径,这要求你运行可执行程序时,当前路径必须位于项目根目录。
356+
>
357+
> 或者你可以将着色器文件夹复制一份到你的执行目录。
355358
356359
## 创建着色器模块
357360

0 commit comments

Comments
 (0)