第 2 章 · 初始化:从实例、设备到交换链 章节摘要:本章跟着一条主线走——把一个空白工程推进到「屏幕上出现会变色的一帧」。这条路上要依次办下五道手续:创建实例并挂上验证层、评估并选定物理设备、开设逻辑设备账户并领取队列、把程序窗口接到 Vulkan(平台表面)、申请一串可以轮换呈现的图像(交换链)。每一节都以完整可抄的 C 代码交付,并在最后处理呈现节奏与失策略这个所有窗口应用的公共难题。 一条主线 主线的起点是一个除了 main 函数之外空无一物的工程,终点是屏幕上持续翻转的图像。
章节摘要:本章跟着一条主线走——把一个空白工程推进到「屏幕上出现会变色的一帧」。这条路上要依次办下五道手续:创建实例并挂上验证层、评估并选定物理设备、开设逻辑设备账户并领取队列、把程序窗口接到 Vulkan(平台表面)、申请一串可以轮换呈现的图像(交换链)。每一节都以完整可抄的 C 代码交付,并在最后处理呈现节奏与失策略这个所有窗口应用的公共难题。
主线的起点是一个除了 main 函数之外空无一物的工程,终点是屏幕上持续翻转的图像。中间的全部工作,就是按顺序办下五张证件:Instance(大厅登记)、PhysicalDevice 的选择决定(网点选择)、Device(账户)、SurfaceKHR(把窗口接到大厅)、SwapchainKHR(一组可翻转的展台)。
这张流程图就是本章的行进路线,每一站对应一节。注意箭头之间的依赖:后一站的申请参数里几乎总有前一站的产出——物理设备的族编号进设备账户,设备账户的队列给呈现用,表面的能力约束交换链参数。初始化代码因此呈现出鲜明的「查询、再申请」节奏,这个节奏会延续到全书的每一类资源。
第一站 2.1 实例创建与验证层。写全 VkInstanceCreateInfo 的每个字段,把 VK_EXT_debug_utils 调试回调装进调用链,并弄清验证层为什么应该在第一天就打开。
第二站 2.2 物理设备评估与选择。枚举设备只是第一步,真正的工作是给每块设备打分:队列族够不够、交换链支持如何、显存多大、特性齐不齐。本节交付一个可复用的评分函数。
第三站 2.3 逻辑设备与队列族。把选中的档案变成账户:声明队列族与数量、启用设备级扩展与特性,最后领取那几个真正执行命令的 VkQueue。
第四站 2.4 平台表面与交换链构建。窗口句柄如何变成 VkSurfaceKHR;查询表面的能力、格式与呈现模式;用查询结果反推交换链的每一项参数,而不是拍脑袋填默认值。
第五站 2.5 呈现与图像采集。交换链图像在「获取」与「呈现」之间的轮转规则,双缓冲与三缓冲的取舍,以及 IMAGE_OUT_OF_DATE 这类退件的标准处理流程。
本章的认知转折出现在 2.4 节:当你发现交换链的尺寸、格式、呈现模式全都必须从查询结果里选,而不是从教程里抄,初始化就不再是「照打代码」,而是一套「先问后办」的程序。结论同样直白:初始化阶段写下的查询代码,是整个程序其余部分的信用基础——后面所有章节的参数合法性,都建立在你在本章查过的那些清单上。
另一个值得提前说破的经验:本章代码看似冗长,但每一行都属于「写完就不动了」的一次性投资。真实项目里这些代码会被封进初始化模块,之后几百帧的渲染循环都在消费它。耐心办完这五道手续,后面的路会越走越宽。
调试本章代码的效率法则也提前交底:初始化失败时,先看验证层消息的编号,再核对报错调用点的每一个输入是否来自查询结果——九成的初始化故障会在这两步内归位。剩下的一成多为环境问题(驱动过旧、SDK 缺失),vulkaninfo 一跑便知。
写出完整的实例创建代码,包含扩展校验与调试回调注册,并解释每个启用项为什么存在。
用评分函数从多块设备里选出目标设备,说出评分维度中哪几项是硬性门槛、哪几项是加权项。
创建逻辑设备时列出三份必须的材料:队列声明、设备级扩展、特性开关,并说明各自的查询来源。
给定一个原生窗口句柄,创建表面并查询其能力,解释 capabilities、formats、presentModes 三张清单分别约束什么。
处理获取图像返回的 OUT_OF_DATE 与 SUBOPTIMAL 两种状态,说出各自触发的重建条件与差别。
交换链图像只是「展台」,还不是你的「资产」——它们不能直接被渲染写入,还需要视图、渲染通道与正确的图像布局。第 3 章从内存这个最底层的库房讲起,把这些资产类手续一次办齐。