实际场景中Fragment discard对Early Fragment Test的影响问询(骁龙Adreno平台)
结论
只要片元着色器仅使用discard、未手动修改gl_FragDepth,包括骁龙Adreno在内的绝大多数主流移动/桌面GPU,都可以保留Early Z剔除优化,深度测试失败的片段不需要执行片元着色器。
核心逻辑说明
你对Early Fragment Test的拆分理解完全正确,该机制实际包含两个独立的执行环节:
- Early Z 测试:在片元着色器执行前,用顶点着色器输出插值得到的深度值,和当前深度缓冲区的对应值做比对,测试失败的片段直接被丢弃,不需要进入片元着色器阶段
- Early Z 写入:测试通过的片段,在片元着色器执行前就把深度值更新到深度缓冲区
使用discard只会禁用Early Z 写入环节:因为硬件无法预判片元着色器是否会执行discard丢弃当前片段,如果提前写入深度,后续片段被丢弃时还要回滚深度缓冲区,开销远大于提前写入带来的收益。但Early Z测试环节完全不受影响,毕竟测试失败的片段无论后续是否会被discard,最终都会被丢弃,完全没有执行片元着色器的必要。
骁龙Adreno系列实际表现
从Adreno 500系列到最新的Adreno 700系列,只要同时满足以下两个条件,Early Z剔除就会正常生效:
- 片元着色器仅包含
discard逻辑,没有对gl_FragDepth赋值 - 未开启alpha-to-coverage、alpha测试等会修改片段覆盖状态的管线配置
只有当你手动修改gl_FragDepth时,硬件才会完全关闭整个Early Fragment Test流程,所有片段都必须执行完片元着色器后再做深度测试和写入。
简易验证方案
你可以自行写测试用例验证该逻辑:
- 准备两个片元着色器,一个直接输出固定颜色,另一个加入永远不会命中的
discard分支(例如if(gl_FragCoord.x < 0.0) discard;) - 绘制大量完全被前景遮挡的三角形,统计两个场景的GPU耗时
如果两个场景耗时几乎一致,即可证明Early Z剔除生效,被遮挡的片段都没有执行片元着色器。
内容的提问来源于stack exchange,提问作者matthias_buehlmann
相关产品推荐
相关产品推荐

