第 3 章 · 内存、资源与描述符绑定 章节摘要:本章跟着一条主线走——给渲染循环喂饱数据。显存要自己申请并按访问特性选型;缓冲与图像先领「资产证」再挂靠内存;子资源与布局决定数据以什么形态被谁读写;最后由描述符系统把资产递交给着色器。五节连起来,是把「数据放哪、怎么绑」这条管线彻底打通,也是全册工程性最强的一章。 一条主线 主线的起点是第 2 章末尾的一个尴尬:交换链图像有了,但你自己的顶点、纹理、 uniform 数据一件都还没进场。主线沿「库房到柜台」推进——显存是库房(3.1),缓冲与图像是资产证(3.2),数据搬运与形态转换走子资源与布局(3.3),描述符是把这些资产递进着色器的柜台(3.4),推常量与索引化则是免排队的小额通道(3.5)。
章节摘要:本章跟着一条主线走——给渲染循环喂饱数据。显存要自己申请并按访问特性选型;缓冲与图像先领「资产证」再挂靠内存;子资源与布局决定数据以什么形态被谁读写;最后由描述符系统把资产递交给着色器。五节连起来,是把「数据放哪、怎么绑」这条管线彻底打通,也是全册工程性最强的一章。
主线的起点是第 2 章末尾的一个尴尬:交换链图像有了,但你自己的顶点、纹理、 uniform 数据一件都还没进场。主线沿「库房到柜台」推进——显存是库房(3.1),缓冲与图像是资产证(3.2),数据搬运与形态转换走子资源与布局(3.3),描述符是把这些资产递进着色器的柜台(3.4),推常量与索引化则是免排队的小额通道(3.5)。
这张关系图概括了本章对象之间的法律关系:资源与内存两证分离、先证后靠;视图是资源的「使用面」;描述符集是视图的「点名册」。后面每一节都在填这张图的一个角落。
第一站 3.1 内存类型、堆与分配策略。查询内存「地理志」,理解设备本地、主机可见、缓存一致性三类属性的组合逻辑,并用子分配器对抗碎片与分配数上限。
第二站 3.2 缓冲区与图像资源。两类资产的核心参数——用法位、共享模式、tiling;图像比缓冲多出格式、范围、样本数三维;视图如何框定使用面。
第三站 3.3 子资源、布局与拷贝操作。mip 层与数组层的坐标系;图像布局为何存在、迁移屏障怎么写;拷贝、缩放、格式转换三种搬运工具的适用边界。
第四站 3.4 描述符布局、池与集合。着色器视角的「点名册」:布局声明格式、池批量供料、集合按套发放,更新与绑定的配对规则。
第五站 3.5 推常量与资源索引化。小于一张点名册的小额通道(推常量),以及把点名册压缩成一段数组的索引化路线(bindless 思路)及其代价。
本章的认知转折在 3.1 与 3.3 之间:当「内存放哪」与「数据以什么布局可见」都变成显式声明,数据流动就从驱动代管的事务,变成你在代码里亲手绘制的物流图。结论是:Vulkan 的性能上限很大程度在本章决定——资源管理的质量直接决定后面所有章节的优化空间。反过来,本章的手续也最容易被抄错:用法位漏一位、布局转错一步,症状都可能延迟到几十帧之后才爆发。
还有一个容易被低估的收获:本章的手续虽然繁琐,但每一步都「可查账」。内存分配有明确的归属与大小,布局有明确的当前值,描述符有明确的指向——出问题时你能把账本摊开逐行核对,这是黑箱 API 给不了的排错体验。第 8 章的排错工作法,一大半正是建立在这本可查的账上。
读懂 vkGetPhysicalDeviceMemoryProperties 的输出,为给定访问模式选出正确的内存类型并写出筛选函数。
解释「先创建资源、再分配内存、再绑定」的三步为什么不能合并,以及合并的尝试会在哪一步碰壁。
为一张需要 mipmap 与离屏采样的图像规划格式、用法位与布局迁移序列。
用描述符池支撑「每帧覆盖更新」的写法,说出 MAX sets 与各类型描述符数量两个配额的来源。
在推常量、动态 uniform 偏移、描述符索引化三种传参方式之间,按数据规模与更新频率做出选择。
数据进了场,接下来是加工:第 4 章把着色器与固定功能阶段组装成图形管线,本章的描述符布局将作为管线布局的一部分被直接消费;第 5 章则把同一套资源体系用进计算管线。本章的每张「点名册」都会在那两章被查验。