glPixelStorei(GL_UNPACK_ALIGNMENT, 1) 缺点?

Posted

技术标签:

【中文标题】glPixelStorei(GL_UNPACK_ALIGNMENT, 1) 缺点?【英文标题】:glPixelStorei(GL_UNPACK_ALIGNMENT, 1) Disadvantages? 【发布时间】:2012-06-18 00:19:06 【问题描述】:

总是使用1的alginment有什么缺点?

glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glPixelStorei(GL_PACK_ALIGNMENT, 1)

它会影响现代 GPU 的性能吗?

【问题讨论】:

您的意思是,除了您的某些数据可能没有 1 字节对齐的行之外? 对于非 POTS 纹理,它可能会影响上传/下载速度。对于 POTS 纹理,它应该没有效果。 @DietrichEpp:什么是 POTS 纹理? @NicolBolas:数据怎么可能不是1字节对齐的? @DietrichEpp:我的应用程序受到上传/下载性能的限制。我想我将不得不进行基准测试,我只是想更好地了解性能特征。我不太明白为什么它会慢得多,类似于 SSE 优化的 memcpy,我认为它应该能够以正确的对齐方式复制大部分内容,然后对最后一个字节有一个特殊情况。 【参考方案1】:

数据怎么不能1字节对齐?

这强烈表明缺乏对row alignment in pixel transfer operations means 的理解。

您传递给 OpenGL 的图像数据应该被分组到行中。每行包含width 个像素,每个像素的大小由格式和类型参数定义。因此,GL_RGB 格式和 GL_UNSIGNED_BYTE 类型将产生一个 24 位大小的像素。否则,像素会被打包,因此一行 16 个像素将占用 48 个字节。

每一行都应按GL_PACK/UNPACK_ALIGNMENT 定义的特定值对齐。这意味着您添加到指针以到达下一行的值是:align(pixel_size * width, GL_*_ALIGNMENT)。如果像素大小为 3 字节,宽度为 2,对齐为 1,则行字节大小为 6。如果对齐为 4,则行字节大小为

看到问题了吗?

图像数据可能来自某些图像加载器加载的图像文件格式,具有行对齐。有时这是 1 字节对齐的,有时它不是。 DDS 图像具有指定为格式的一部分的对齐方式。在许多情况下,图像具有 4 字节的行对齐;因此,小于 32 位的像素大小将在具有特定宽度的行末尾有填充。如果您给 OpenGL 的对齐方式与该对齐方式不匹配,那么您会得到一个格式错误的纹理。

您设置对齐方式以匹配图像格式的对齐方式。如果您知道或可以确保您的行对齐始终为 1(除非您编写了自己的图像格式或 DDS 编写器,否则这不太可能),您需要将行对齐设置为与您的图像格式使用的完全相同。

【讨论】:

@ronag:你不太可能击败解包器的性能,而使用 SIMD 编写的函数是出了名的复杂。听起来工作量很大,必须通过基准来证明您的应用程序受到上传速度的限制并且上传速度受到解包器的不利影响。 @ronag:这里有很多不同的变量,您正在考虑最复杂的选项,基本上是在您的应用程序中重新实现 OpenGL 解包器,希望它可能更快。您猜测 RGB -> BGRA 转换“可能有大约 1% 的开销”这一事实意味着您可能还没有为此做好准备——这个猜测由于几个原因没有通过气味测试(聊天如果你想要它们)。假设您可以发布基准数据,也许您想切换到聊天,或者提出另一个关于提高应用程序性能的问题。 @ronag: 1) 你不会打败 OpenGL 的解包器。 2) 即使你要打败它,PBO 解包也是异步,这需要你的应用程序显式使用线程。 3) 优化这一点的正确方法是对各种不同的格式进行基准测试,直到找到硬件本机支持的格式(即:最快的格式),然后预处理您的数据,例如他们符合那些。格式/类型值比行对齐更重要。 Nicol 的回答是正确的,但我仍然对数据如何不是 1 字节对齐感到困惑一段时间。对于那些坚持这一点的人,假设您从图像加载库中获取数据,您没有控制数据,因此您没有控制布局。假设可以在每行的末尾使用对齐字节导入数据。这种对齐方式是您指定的。希望这对某人有帮助! @sepideh:因为这就是 alignment 的意思。每条线必须从对齐的偶数倍数开始。 32 是下一个高于 27 的 8 的偶数倍数。【参考方案2】:

它会影响现代 GPU 的性能吗?

不,因为像素存储设置仅与从 GPU 传输数据或向 GPU 传输数据相关,即数据的对齐方式。一旦进入 GPU 内存,它就会以 GPU 和驱动程序所需的任何方式对齐。

【讨论】:

我想他是在问一个或多个 GPU 是否需要 CPU 在上传之前对数据进行一些修改。也就是说,如果 GPU 无法处理字节对齐的行。 我在问它是否以及何时会影响 gpu 上传/下载,以及是否还有其他方面我需要考虑。 @ronag:好吧,如果GPU不能处理你原始数据的数据格式,那么数据格式需要驱动先转换。但是,由于总体上您会偶尔上传纹理数据,因此它只会消耗很少的 CPU 时间。然而,数据传输并不是我认为的 GPU 性能问题。瓶颈显然是那里的 CPU 和数据总线。【参考方案3】:

不会对性能产生影响。设置更高的对齐方式(在 openGL 中)不会改善任何事情,也不会加速任何事情。

所有的对齐都是告诉openGL在哪里期待下一行像素。如果您的图像像素紧密排列,即如果在一行字节的结束位置和新行的开始位置之间没有间隙,则应始终使用 1 对齐。

默认对齐方式是 4(即 openGL 期望下一行像素在内存中可以被 4 整除的跳转之后),这可能会在您加载不是 4 的 R、RG 或 RGB 纹理的情况下导致问题-bytes 浮动,或者宽度不能被 4 整除。如果您的图像像素被紧密排列,您必须将对齐更改为 1 才能使解包工作。

你可以(我个人没有遇到过)有一个 3x3 RGB ubyte 的图像,它的行是第 4 对齐的,最后有 3 个额外的字节用作填充。哪些行可能如下所示:

R - G - B - R - G - B - R - G - B - X - X - X(共16个字节)

其原因是对齐的数据提高了处理器的性能(不确定它在当今处理器上的真实性/合理性有多少)。 如果您可以控制原始图像的合成方式,那么可能以一种或另一种方式对齐它会改善对它的处理。但这是在 openGL 之前完成的。 OpenGL 无法对此进行任何更改,它只关心在哪里找到像素。

所以,回到上面的 3x3 图像行 - 将对齐设置为 4 会很好(并且有必要)跳过最后一个填充。如果您将其设置为 1,它会弄乱您的结果,因此您需要将其保留/恢复为 4。(请注意,您也可以使用 ROW_LENGTH 跳过它,因为这是处理子集时使用的参数图像,在这种情况下,有时您必须跳转超过 3 或 7 个字节(这是 8 的对齐参数可以给您的最大值)。在我们的示例中,如果您提供 4 的行长度和 1 的对齐也将工作)。

包装也是如此。您可以告诉 openGL 将像素行对齐到 1、2、4 和 8。如果要保存 3x3 RGB ubyte,则应将对齐方式设置为 1。从技术上讲,如果您希望结果行紧密排列,您应该总是给 1。如果你想(无论出于什么原因)创建一些填充,你可以给另一个值。给(在我们的例子中)一个 4 的 PACK_ALIGNMENT 将导致创建看起来像上面的行的行(最后有 3 个额外的填充)。请注意,在这种情况下,您的包含对象(openCV mat、位图等)应该能够接收额外的填充。

【讨论】:

以上是关于glPixelStorei(GL_UNPACK_ALIGNMENT, 1) 缺点?的主要内容,如果未能解决你的问题,请参考以下文章

osg学习(六十五)图片到纹理

没有纹理图像单元的 Opengl 纹理

用于 OpenGL 纹理映射的 Java 图像作为 ByteBuffer

如何将浮点矩阵作为 2D 纹理传递给片段着色器?