在图形渲染中,discard指令会阻止片元写入帧缓冲,但若GPU提前写入深度/颜色数据,会导致错误结果(如透明边缘残留错误像素)。因此,GPU必须等待discard判断完成后再决定是否写入,这导致EarlyZ优化失效——原本可通过提前丢弃被遮挡片元节省计算,现需完整执行所有片元的着色器,造成性能损耗。新架构尝试动态平衡正确性与EarlyZ优化,但实际仍需性能分析工具验证。
1. 为什么discard前不能写深度/颜色缓冲?
直观例子:
- 假如你在一个像素的 fragment shader 里写了 discard;,说明你“不想把这个像素画到屏幕上”。
- 如果 GPU 没有等着你判断、提前就把它的颜色/深度数据写到 framebuffer(帧缓冲区),
那写进去的信息就都是无效甚至错误的!
比如一片原本应该透明的树叶边缘还写上了颜色、深度,后续其它像素就可能被莫名其妙挡住、混色出错。
- 只有等 shader 判断完「丢还是不丢」以后,
没有 discard,才把颜色和深度写入。
有 discard,什么都不写。
2. “关闭 EarlyZ” 是什么含义?
EarlyZ 的核心思路是「碰到被先前片元挡住的像素,根本不用让 pixel shader 跑完就直接丢了」。这能极大省算力。
但有 discard,GPU就不能提前假设某个片元的颜色/深度是一定要写进 buffer 的。
- 因为 shader 跑到中途可能动态决定「这个片元丢弃」。
- 万一提前就写了,后面又被 discard,前面写入的内容就没人擦掉了!
所以,某些早期架构 GPU 为了保证绝对正确性,会采取:
- 放弃“提前写深度或颜色”,
- 先都让片元执行完 shader、跑完 discard 判断后,
- 再决定:到底写不写进去。
这样的话:
- 就完全丧失了 EarlyZ “早丢人、不跑shader” 的优化优势!
- 每个像素无论是否遮住、无论最终被 discard,都要执行 full shader——这就是性能损耗的原因。
3. 为什么“后写/推迟写”是正确实现,而 EarlyZ 就不起作用了?
过程对比:
- 没有 discard
GPU可以直接判断深度,提前丢片元,不进pixel shader,节省性能。
- 有 discard
必须先执行完整 shader,只有在 shader 里遇到 discard,GPU才知道结果。丢不丢的决定太晚,EarlyZ就没机会介入提前丢片元了。
小结
你句子的本质理解可以这样拆解:
- Discard 之前,GPU不能写数据到缓冲区,否则白写了/写错了、还出错。
- 于是,为了数据流正确,不得不“关掉”早期优化(EarlyZ),都先执行完整 shader,再根据 discard 的实际情况做正确的深度/颜色写入或丢弃。
- 这就损失了 EarlyZ 能带来的大部分性能提升。
4. 进阶:新架构如何改进?
后来的高端GPU为了既保证正确性,又保 EarlyZ 性能,会分析 shader 代码、实施延迟/条件写入、甚至动态启用 EarlyZ,但不能保证所有场景都生效。因此实际场景下,仍需要用 GPU Profiler 验证结果。
总结口诀
Discard提前判断慢,
缓冲写入需靠后。
EarlyZ被迫关大门,
片元全跑损性能。
版权声明:本文为CSDN博主「你一身傲骨怎能输」的原创文章,
遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_33060405/article/details/150936893





