Skip to content

Commit 0601cd2

Browse files
committed
Modify
1 parent 8a51a49 commit 0601cd2

30 files changed

+189
-21
lines changed
Loading

docs/md/02/20_descriptor1.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void main() {
5555
注意`uniform``in``out`三中变量是声明顺序是任意的。
5656
`binding``location`指令类似,我们将在描述符布局中引用此绑定。
5757

58-
> `UniformBufferObject` 不是自定义的类型名,不能修改
58+
> `UniformBufferObject` 自定义的类型名,可以任意编写
5959
6060
## **描述符集布局**
6161

@@ -73,10 +73,10 @@ struct UniformBufferObject {
7373
};
7474
```
7575
76-
> 这里的 `UniformBufferObject` 是自定义类名,可以随意设置。
77-
7876
我们使用GLM的类型,它的内存布局完全匹配着色器中的定义,所以我们可以直接使用`memcpy`。
7977
78+
> C++ 中的类型名可以和 GLSL 中不一致,重要的是内存布局一致。
79+
8080
### 2. 辅助函数
8181
8282
我们需要在图形管线创建时指定描述符的细节,就像我们为顶点参数指定了`location`一样。

docs/md/03/50_pushconstant.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ void main() {
105105
}
106106
```
107107

108-
因为推送常量只有一个数据区,直接使用 `push_constant``PushConstants` 标记即可。
108+
因为推送常量只有一个数据区,直接使用 `push_constant` 标记即可。
109+
110+
> `PushConstants` 是自定义的类型名。
111+
109112
之前提到可以使用 `Range``offset` 划分数据段,假设某个数据段的起始偏移是 64 字节,那么可以这样读取:
110113

111114
```glsl

docs/md/03/60_dynamicuniform.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ void updateDynamicUniformBuffer(uint32_t currentImage) {
213213
214214
第二个矩阵将用于兔子,我们让其不断旋转,通过时间计算旋转角度保证转速均匀。
215215
216-
> 我们只修改了第二个矩阵,所以 `memcpy` 可以部分复制,你可以自行修改代码。
216+
> 可以使用 `memcpy` 配合指针偏移量更新局部数据。
217217
218218
现在可以在 `drawFrame` 函数中使用它:
219219
@@ -226,6 +226,8 @@ void drawFrame() {
226226
}
227227
```
228228

229+
> 实际应用中,你应该只在数据变化后 `memcpy` 更新局部数据,而非每帧都更新全部内容。
230+
229231
### 5. 记录命令
230232

231233
现在修改 `recordCommandBuffer` 函数,在两次绘制前分别调用 `bindDescriptorSets` 函数:

docs/md/03/80_pipelinecache.md

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -118,21 +118,6 @@ void createPipelineCache() {
118118
119119
---
120120

121-
你现在掌握的 Vulkan 基本知识应该足以开始探索更多功能,例如
122-
123-
- 查询与查询池\(Query and QueryPool\)
124-
- 多线程命令缓冲生成\(Multi-threaded command buffer generation\)
125-
- 多个子通道\(Multiple subpasses\)
126-
- 几何着色器\(Geometry shader\)
127-
- 计算着色器\(Compute shaders\)
128-
129-
当前的程序可以通过多种方式扩展,例如添加 Blinn-Phong 光照、后期处理效果和阴影贴图。
130-
你应该能够从其他 API 的教程中学习这些效果是如何工作。尽管 Vulkan API 很细致,但许多概念仍然是相同的。
131-
132-
> 理论上,作者会慢慢更新这些内容,你可以看看Github仓库的最近更新时间。
133-
134-
---
135-
136121
**[C++代码](../../codes/03/80_pipelinecache/main.cpp)**
137122

138123
**[C++代码差异](../../codes/03/80_pipelinecache/main.diff)**

docs/md/03/90_compute.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# **计算着色器与SSBO**
2+
3+
## **前言**
4+
5+
在基础部分的最后,我们将介绍 **计算着色器\(compute shader\)****着色器存储缓冲对象\(SSBO\)**
6+
7+
与其他图形引擎不同, Vulkan 强制支持计算着色器,这意味着你可以使用它在 GPU 上进行通用计算。
8+
GPU 的计算能力可以用于图像处理、可见性测试、后期处理、高级光照计算、动画、物理(例如粒子系统)等工作。
9+
它甚至可以用于不需要任何图形输出的非可视化计算工作,例如数值计算或 AI 相关的内容,这被称为“无头计算\(headless compute\)”。
10+
11+
## **管线框图**
12+
13+
计算着色器并非图形管线的一部分,让我们看看官方规范的 Vulkan 管线框图:
14+
15+
![vulkan_pipeline_block_diagram](../../images/0390/vulkan_pipeline_block_diagram.png)
16+
17+
左侧是我们熟悉的传统图形管线,中间是输入缓冲、描述符与附件,而计算着色器位于右上角。
18+
19+
> 中右侧有个“Task-Mesh”的着色器模块,它用于代替传统的“顶点-细分-几何”着色器模式,我们会在进阶章节中介绍。
20+
21+
这里的重点是,虽然计算着色器不属于图形管线,但它可以使用描述符集访问内存资源。
22+
23+
## **粒子系统**
24+
25+
本章将实现一个简单的基于 GPU 的粒子系统,用于演示计算着色器与 SSBO 的使用。
26+
27+
这种系统在许多游戏中都有使用,通常由数千个需要按逻辑帧速率更新的粒子组成。
28+
渲染这样的系统需要两个主要组件:顶点\(用顶点缓冲传递\)和更新它们的方式\(比如某种方程\)
29+
30+
“经典”的基于 CPU 的粒子系统会将粒子数据存于系统主存,然后使用 CPU 更新它们。
31+
每次更新后,都需要将数据从主存传输到 GPU 的显存,无论你使用“主机可见内存”还是“设备本地内存”都是如此,这非常昂贵。
32+
33+
基于 GPU 的粒子系统不需要这种往返,计算着色器将直接更新 GPU 显存中的顶点数据,而此数据区可采用设备本地内存类型,从而获得最高性能。
34+
35+
在具有专用计算队列的 GPU 上,可以并行执行计算任务和图像管线的渲染任务,这被称为“异步计算”,我们将在进阶章节介绍。
36+
37+
## **数据准备**
38+
39+
Vulkan 提供了两种专用存储类型允许着色器**任意读取和写入缓存**,它们分别是:
40+
41+
- 着色器存储缓冲对象\(SSBO\)
42+
- 存储图像
43+
44+
我们不会在本章中进行图像处理,但你应该知晓计算着色器也可以用于图像处理。
45+
46+
### 1. 着色器存储缓冲
47+
48+
“着色器存储缓冲对象\(SSBO\)”允许着色器直接读取和写入缓冲。它们类似于 Uniform 缓冲对象,最大的区别在于您可以将其他缓冲类型别名化为 SSBO,并且它们可以任意大。
49+
50+
本章我们会直接让计算着色器修改我们的顶点缓冲区数据,为此需要给缓冲区创建信息添加一个标志位 `vk::BufferUsageFlagBits::eStorageBuffer` ,此标志位表示此缓冲将用作存储缓冲。
51+
52+
因此我们需要修改 `createVertexBuffer` 函数中顶点缓冲区的创建代码:
53+
54+
```cpp
55+
void createVertexBuffer() {
56+
......
57+
createBuffer(bufferSize,
58+
vk::BufferUsageFlagBits::eStorageBuffer |
59+
vk::BufferUsageFlagBits::eTransferDst |
60+
vk::BufferUsageFlagBits::eVertexBuffer,
61+
vk::MemoryPropertyFlagBits::eDeviceLocal,
62+
m_vertexBuffer,
63+
m_vertexBufferMemory
64+
);
65+
......
66+
}
67+
```
68+
69+
// TODO 2025-06-22
70+
71+
---
72+
73+
我们的 `main.cpp` 已经变得非常庞大,不适合再添加内容了。
74+
75+
对于后面的进阶章节,我们会在前言部分给出代码框架。
76+
请读者先阅读基础代码,然后根据章节内容为框架添加代码。
77+
78+
---
79+
80+

docs/md/04/00_cxxmodule.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# **C++模块化**
2+
3+
// TODO

docs/md/04/10_querypool.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# **查询池**
2+
3+
// TODO

docs/md/04/20_multithreading.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# **并行命令录制**
2+
3+
// TODO

docs/md/04/21_resourceloading.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# **资源加载系统**
2+
3+
// TODO

0 commit comments

Comments
 (0)