第 4 章 · 图形管线与着色器 章节摘要:本章跟着一条主线走——把第 3 章备好的资源加工成一帧图像。着色器以 SPIR-V 字节码入场;固定功能状态被打包成不可变的管线执照;渲染通道与帧缓冲规定附件的加工次序;动态状态把少数高频变化项从执照里摘出来。四节连起来,回答「GPU 按什么流程把三角形变成像素」。 一条主线 主线的起点是第 3 章结尾的待加工原料:顶点缓冲在库里、纹理在点名册上、离屏图像已建好。终点是这批原料被一条图形管线按序加工、写入交换链图像。加工流程有明确的工位顺序:顶点装配、顶点着色、光栅化、片段着色、深度模板、混合输出——其中可编程工位由你的着色器代码定义,固定功能工位由管线状态定义。
章节摘要:本章跟着一条主线走——把第 3 章备好的资源加工成一帧图像。着色器以 SPIR-V 字节码入场;固定功能状态被打包成不可变的管线执照;渲染通道与帧缓冲规定附件的加工次序;动态状态把少数高频变化项从执照里摘出来。四节连起来,回答「GPU 按什么流程把三角形变成像素」。
主线的起点是第 3 章结尾的待加工原料:顶点缓冲在库里、纹理在点名册上、离屏图像已建好。终点是这批原料被一条图形管线按序加工、写入交换链图像。加工流程有明确的工位顺序:顶点装配、顶点着色、光栅化、片段着色、深度模板、混合输出——其中可编程工位由你的着色器代码定义,固定功能工位由管线状态定义。
管线与产线执照的类比贯穿本章:执照(VkPipeline)申请昂贵、查验严格、办妥后每次开工只出示编号;执照上写不下的高频项(视口、剪裁框)被单独列为「动态状态」,开工时口头报备。而渲染通道(VkRenderPass)像是「本次生产任务单」,规定哪几张相纸(帧缓冲附件)按什么顺序流转。
第一站 4.1 着色器模块与 SPIR-V。着色器为什么以字节码而非源码进场;glslc 编译会话;着色器接口的匹配规则;反射工具如何帮你自动对接描述符布局。
第二站 4.2 图形管线状态对象。一份完整的 VkGraphicsPipelineCreateInfo 骨架逐段拆解;不可变设计换来什么;管线缓存与衍生管线如何把创建成本摊薄;变体矩阵的管理策略。
第三站 4.3 渲染通道、帧缓冲与动态状态。附件、子通道、依赖的三层声明;传统 RenderPass 与 Vulkan 1.3 动态渲染两条路线的取舍;视口与剪裁框的按帧报备。
本章的认知转折在 4.2:当你把「改变混合模式」从一次函数调用变成一次管线创建,就会理解 Vulkan 性能模型的全部逻辑——把昂贵的事挪到启动期,把运行期压到最薄。结论是:管线数量管理是渲染引擎的隐性架构问题,变体矩阵失控的引擎会在加载与内存上同时付账;而动态状态与动态渲染这两样 Vulkan 1.2 与 1.3 时代收编的能力,正是行业对「哪些状态不该固化」给出的标准答案。
用 glslc 把 GLSL 编译成 SPIR-V 并创建着色器模块,说出离线编译与运行时编译各自的风险点。
写出完整的图形管线创建代码,指出每个子状态结构体的职责与必填项。
用管线缓存与衍生管线优化批量创建,解释命中率查询反馈的读取方法。
为一个多通道后处理链设计渲染通道:附件声明、子通道引用、依赖的写法。
判断一个项目该用传统渲染通道还是动态渲染,并给出迁移时的注意事项。
把视口与剪裁框设为动态状态,按帧按物体报备而不重建管线。
最后留一条自检标准:把你的管线装配代码拿给同事读,如果对方能在不看文档的情况下说出「改哪个字段会得到什么画面」,说明装配结构是清晰的;如果连你自己都要靠注释回忆字段含义,那就值得先重构再继续。管线代码是全册复用率最高的代码,清晰度就是它的第一性能指标。
图形管线画三角形,计算管线跑通用并行——两者共享本章的资源与描述符体系。第 5 章用计算管线补齐另一半加工能力,并把本章的渲染命令与计算命令装进命令缓冲,走完「记录到提交」的最后一公里。
交接清单只有一条:本章所有管线在创建时都引用了描述符布局(4.2 的管线布局字段),第 5 章的计算管线同样如此——布局对象是跨管线复用的,提前把布局设计好,两条管线就能共享同一套资源体系。这也是本章顺序先于第 5 章的原因。