从前,当>快于<…时,等等?


280

我正在阅读一个很棒的OpenGL教程。真的很好,相信我。我当前所在的主题是Z缓冲区。除了解释全部内容之外,作者还提到我们可以执行自定义深度测试,例如GL_LESS,GL_ALWAYS等。他还解释了深度值的实际含义(最高和最低)也可以是定制。到目前为止我还了解。然后作者说了一些难以置信的话:

zNear范围可以大于zFar范围;如果是这样,那么就构成距观看者最近或最远的位置而言,窗口空间值将反转。

此前,有人说窗口空间Z值0最接近,而1最远。但是,如果我们的剪辑空间Z值被取反,则深度1将最接近视图,深度0将最远。但是,如果翻转深度测试的方向(GL_LESS到GL_GREATER等),我们将得到完全相同的结果。因此,这实际上只是一个约定。确实,翻转Z的符号和深度测试曾经是许多游戏中至关重要的性能优化。

如果我正确理解,从性能角度来看,翻转Z的符号和深度测试仅是将<比较更改为比较而已>。因此,如果我理解正确,而作者并没有在撒谎或编造东西,那么更改<>过去对于许多游戏来说都是至关重要的优化

作者是在编造东西吗,我是在误解某些东西,还是真的曾经比<他慢(如作者所说,生命至关重要>

感谢您澄清这个非常奇怪的问题!

免责声明:我完全知道算法复杂性是优化的主要来源。此外,我怀疑现在绝对不会有任何改变,我不是要优化它。我只是极度,痛苦,甚至是好奇。


6
本教程的链接似乎(最近)已失效。:(
TZHX

@TZHX:由于接受的答案是本教程的作者编写的,因此我们希望能再次找到它。看到我对他的回答的最后评论:)
Armen Tsirunyan

3
此处提供参考的OpenGL教程。
冯斯

(a <b)与(b> a)相同,因此绝对不需要在硬件中实现这两个比较操作。性能上的差异是比较操作的结果。要解释所有副作用,这是一条漫长而曲折的道路,但是这里有一些提示。游戏用于填充深度缓冲区,以避免对深度测试失败的片段进行更昂贵的片段处理。Quake过去将深度范围分为两半,以避免清除帧缓冲区,因为游戏总是填充屏幕上的每个像素,依此类推。
t0rakka

2
@Fons看起来像链接已经死了,再次:(
nalzok

Answers:


350

如果我正确理解,从性能角度来看,翻转Z的符号和深度测试仅是将<比较改为>比较而已。因此,如果我理解正确,并且作者没有撒谎或捏造东西,那么将<更改为>曾经是许多游戏的重要优化。

我没有特别好地解释这一点,因为它并不重要。我只是觉得这是一个有趣的琐事。我不打算专门研究该算法。

但是,上下文是关键。我从未说过<比较要比>比较快。请记住:我们在谈论图形硬件深度测试,而不是您的CPU。不operator<

我指的是一个特定的旧优化,您可以GL_LESS在[0,0.5]范围内使用一帧 。在下一帧中,渲染GL_GREATER范围为[1.0,0.5]。您来回走动,逐字地“翻转Z的符号并进行深度测试”。

这会损失一点深度精度,但是您不必清除深度缓冲区,这曾是相当慢的操作。由于深度清理现在不仅免费,而且实际上比这种技术快,因此人们不再这样做。


1
目前清除深度缓冲区速度更快的原因有两个,这两个原因都是基于GPU使用分层深度缓冲区的事实。因此,只需清除即可将砖块状态设置为清除(快速),即可更改深度比较符号,但是,这意味着需要刷新整个HiZ缓冲区,因为它仅存储取决于比较符号的最小值或最大值。
贾斯珀·贝克斯

3
@NicolBolas:PerTZHX的评论,在我的问题中指向您的教程的链接已失效。您能否让我们所有人都知道教程的位置,并可以选择编辑问题?
Armen Tsirunyan

2
教程可在Web存档中找到。如果@NicolBolas允许,如果我们可以将它们移到更易于访问的位置,将对社区有所帮助。也许是GitHub之类的东西。web.archive.org/web/20150215073105/http://arcsynthesis.org/...
ApoorvaJ

3

几乎可以肯定的答案是,无论使用哪种芯片+驱动器,Hierarchical Z都只能在一个方向上工作-这在当今是一个相当普遍的问题。低级组装/分支与它无关-Z缓冲是在固定功能的硬件中完成的,并且是流水线的-没有推测,因此也没有分支预测。


0

这样的优化会损害许多嵌入式图形解决方案的性能,因为它会使帧缓冲区解析效率降低。清除缓冲区是向驱动程序发出的明确信号,表示在合并时不需要存储和还原缓冲区。

背景信息很少:平铺/合并光栅化器以适合于片内存储器的非常小的图块数量处理屏幕。这减少了对外部存储器的写入和读取,从而减少了存储器总线上的通信量。当一个帧完成时(调用交换,或者因为它们已满而刷新FIFO,更改帧缓冲区绑定等),必须解析帧缓冲区;这意味着将依次处理每个垃圾箱。

驱动程序必须假定必须保留先前的内容。保存意味着必须将垃圾箱写到外部存储器,然后在再次处理垃圾箱时从外部存储器恢复。清除操作告诉驱动程序箱中的内容已明确定义:清除颜色。这是优化的琐碎情况。也有一些扩展可以“丢弃”缓冲区的内容。


-8

它与高度调整的程序集中的标志位有关。

x86同时具有jl和jg指令,但是大多数RISC处理器仅具有jl和jz(无jg)。


2
如果这就是答案,那么它将引发新的问题。在早期的RISC处理器上,“采取分支”的速度是否比“忽略分支”的速度慢?据我所知,现在肯定不是以任何可衡量的方式。您是否应该编写一个for循环,该循环具有向后无条件的分支,而很少有条件的向前分支以退出循环呢?听起来很尴尬。
Pascal Cuoq

54
-1:这个问题与CPU无关。GL_LESS和GL_GREATER是在GPU上运行的深度比较操作。
Nicol Bolas

8
有趣的是,对于标题正确但与实际问题无关的答案,您可以获得多少代表。
约书亚

7
+1不,此答案至少对部分问题是正确的。问题是:“作者是在编造东西吗?我是在误解什么吗?或者确实确实是一次<慢于(如作者说的那样)比>慢的情况?”。给出了三个选项。这个答案是对选项3的可能性的回应。本文中没有提到CPU / GPU的技术,也没有必要使用GPU(CPU上的第一个3D游戏)。好的...我不认为RISC上有很多3d游戏:-)
xanatos 2011年

3
(并且GPU标签是在20:34添加的。第一个修订版只有CPU标签。此响应是在18:44编写的)
xanatos 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.