5

在 x86/SIMD 程序集中,我使用需要转换的图形图像的四个 32 位像素填充了 XMM 寄存器。但是,像素是 10 位压缩 RGB 格式,因此它们以这种形式以 32 位存在:

[  red   ][  green ][  blue  ][]
RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB00

最后两位是填充位,未使用。

我需要将这些像素乘以另一个值,但该值需要被屏蔽,因此它只会影响红色像素。这个值是常数,所以可以硬编码。假设值为 0.1234。我如何将它放入另一个具有适当掩码的 XMM 寄存器中,以便它只影响每个 32 位段的红色部分?

以图形方式说明,我想做这样的事情:

XMM0 (first 32 bit segment):
[ 0.1234 ][  1.0   ][  1.0   ][]

*

XMM1 (first 32 bit segment):
RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB00

结果是 XMM0 和 XMM1 的乘积。当然,这个 32 位段将在整个 XMM 寄存器中复制,我只是在这里指定了前 32 位,所以你明白了。

4

2 回答 2

3

如果您真的只想影响红色部分,您可能会想出一个技巧,将红色和部分绿色乘以某个常数(将寄存器视为 16 位短路的集合),然后重新组合新的红色部分与旧的绿色和蓝色部分。

如果您要对所有颜色进行操作,一个更好的策略是使用移位和随机播放的组合将该格式解压缩为受支持的 xmm 寄存器格式(如 16 位或 32 位短或浮点)(并可能转换为浮动)操作。然后做你所有的数学,然后把它打包回去。

如果您曾经重复使用任何值(例如,如果您正在计算一个过滤器内核)并且您正在使用浮点数,那么如果您解压缩并转换为浮点数然后重新使用该值更快和结束。即使您必须创建一个循环,将整行解压缩为 32 位浮点数,然后再对其进行操作并重新打包整行。

于 2013-02-18T19:35:55.380 回答
2

假设您想使用浮点来乘以您的值,我会将每个值的 R/G/B 值解压缩到 XMM 寄存器的各个浮点部分(只需除以 1023.0)。

您可能还会发现准备四个 R、四个 G 和四个 B 值实际上更容易,然后为另一个 XMM 寄存器中的每个颜色值构建一个具有相同乘数的值,然后乘以该值,而不是保持R、G 和 B 在一个寄存器中。显然,这将需要展开循环,但无论如何这往往会大大提高性能。

于 2013-02-18T20:49:09.447 回答