第 5 章 · 计算管线与命令执行 章节摘要:本章跟着一条主线走——不画任何三角形,让 GPU 完成一整段通用计算,并把「记录、提交、回收」的命令执行体系立起来。前半章是计算管线与分派模型:工作组网格、共享内存、与图形管线的交错执行;后半章是命令缓冲的完整生命周期:从池里领取、多线程录制、带同步凭证提交、按节奏回收。 一条主线 主线从一个具体任务出发:把一段二十万粒子的物理模拟从 CPU 挪到 GPU。这个任务不产出像素,却要用到第 3 章全部的资源知识与一套新的执行知识。沿主线你会办两件大事:把计算管线(只含一个着色阶段的产线执照)办下来,学会用 vkCmdDispatch 把任务切成工作组网格派发;然后把计算命令、渲染命令一起装进命令缓冲,走完从录制到提交再到回收的全流程。
章节摘要:本章跟着一条主线走——不画任何三角形,让 GPU 完成一整段通用计算,并把「记录、提交、回收」的命令执行体系立起来。前半章是计算管线与分派模型:工作组网格、共享内存、与图形管线的交错执行;后半章是命令缓冲的完整生命周期:从池里领取、多线程录制、带同步凭证提交、按节奏回收。
主线从一个具体任务出发:把一段二十万粒子的物理模拟从 CPU 挪到 GPU。这个任务不产出像素,却要用到第 3 章全部的资源知识与一套新的执行知识。沿主线你会办两件大事:把计算管线(只含一个着色阶段的产线执照)办下来,学会用 vkCmdDispatch 把任务切成工作组网格派发;然后把计算命令、渲染命令一起装进命令缓冲,走完从录制到提交再到回收的全流程。
这张生命周期图是本章后半的地图:命令缓冲从池中领取、开始录制、录制完成成为可提交状态、递交队列后进入待执行、执行完毕可重置或归还。理解状态迁移,就理解了「为什么提交过的命令不能改、回收之前必须确认执行完成」这两条铁律。
第一站 5.1 计算管线与分派。计算管线的极简装配(一个着色阶段加一个布局);分派的三维网格与工作组内共享内存;用一次真实的直方图统计把资源、管线、分派串起来,并讨论计算与图形的交错执行。
第二站 5.2 命令缓冲记录与队列提交。命令池的分配策略与线程归属;主命令缓冲与次级缓冲的分工;提交时挂上等待与发出信号量、完成栅栏的完整仪式;按在途帧数设计命令池与缓冲的轮换回收。
本章的认知转折在 5.2 的提交仪式:当等待信号量、发出信号量、完成栅栏三样东西要在一次 vkQueueSubmit 里同时安排,前面各章埋的同步伏笔全部收线——队列提交不是「把命令发出去」这么简单,而是一次带因果声明的委托。结论是:命令执行体系的设计(几个池、几条缓冲、按什么节奏回收)决定了引擎的并行上限,比任何单条命令的写法都重要。计算管线的加入还带来一个架构选项:让计算与图形在时间线上交错,把 GPU 的空闲时段填满——这是老 API 给不了的编排自由。
补充一个务实的观察:本章的代码模式(领取、录制、提交、回收)与任何异步任务系统的设计同构。哪怕你日后转向其他图形接口或计算框架,这套路单据管理的思路都能原样迁移——这也是为什么值得把本章的框架代码整理成可复用模块,而不是散落在渲染代码里。
创建计算管线并说明它与图形管线在装配上的差异,解释为什么它更简单却更灵活。
根据任务规模计算分派维度,写出工作组尺寸选择与共享内存容量的权衡依据。
实现一次完整的计算任务:输入缓冲、分派、结果读回,含布局与访问屏障。
说明命令缓冲的五种状态及各自允许的操作,解释「提交后不可改」的底层原因。
用次级命令缓冲把录制工作分摊到多个线程,并说出与线程数、池分配的配套关系。
为提交调用配齐等待信号量、发出信号量与完成栅栏,画出三者与队列的时间线关系。
本章你已经尝过信号量与栅栏的滋味,但只是「会用」。第 6 章把这些原语摊开:栅栏与信号量的语义边界、事件与管线屏障的细粒度控制、多队列与多线程的并发模型——以及它们拼错时那些最难缠的故障形态。
给第 6 章预留的问题清单也一并留下:5.2 的帧栅栏为什么能保证命令缓冲可重录?提交时挂的两个信号量在队列之间传递时,CPU 看得到它们的状态吗?跨队列提交的顺序由什么决定?带着这三问进入下一章,每一节都会有「原来如此」的落点。