调配 32 位 alpha 通道所需的 Intel 内在函数
Posted
技术标签:
【中文标题】调配 32 位 alpha 通道所需的 Intel 内在函数【英文标题】:Intel intrinsics needed for swizzling 32-bit alpha channel 【发布时间】:2014-08-28 01:20:00 【问题描述】:我有一个 32 位 RGBA 图像缓冲区。假设它是 1920x1080 - 典型的从左到右、从上到下的 RAW 缓冲区。
这是我真正想做的事情:从这个源缓冲区创建两个新缓冲区...
-
"FILL" 缓冲区... RGB 值与原始缓冲区的值匹配。 alpha 值将变得不透明 (0xff)
“KEY”缓冲区...每个 RGB 值都与原始缓冲区的 alpha 值匹配。 alpha 值将是不透明的 (0xff)
对于输入缓冲区的每个像素,我的(慢)解决方案如下:
u_int32_t pixel = *srcPtr++; // grab the source 32-bit pixel value
*fillPtr++ = pixel | 0xff; // FILL: keep only the RGB channels (alpha = 0xff)
pixel &= 0xff; // KEY: grab just the alpha value
*keyPtr++ = (pixel<<24) | (pixel<<16) | (pixel<<8) | 0xff; // KEY: xfer alpha to RGB, alpha = 0xff
可以假设源缓冲区是 16 字节对齐的。
一些初步测试表明,在 1920x1080 图像(英特尔至强 E5、六核、12MB 三级高速缓存、3.5Ghz)上,此时钟大约为 8 毫秒。
有人可以提供他们的 SSE3 内在专业知识来加快速度吗?
【问题讨论】:
Cory.. 我没有尝试任何来自 SSE-land 的东西,因为我只是粗略地意识到它的存在。 【参考方案1】:听起来这是您想要的基础——它一次处理四个像素。
void split_pixels(__m128i src, __m128i *fill, __m128i *key)
__m128i const alphamask = _mm_set_epi8(-1, 0, 0, 0, -1, 0, 0, 0,
-1, 0, 0, 0, -1, 0, 0, 0);
__m128i const fillmask = _mm_set_epi8(-1, 15, 15, 15, -1, 12, 12, 12,
-1, 7, 7, 7, -1, 3, 3, 3);
_mm_stream_si128(fill, _mm_or_si128(src, alphamask));
_mm_stream_si128(key, _mm_or_si128(_mm_shuffle_epi8(src, fillmask), alphamask));
它使用了 SSE shuffle 指令,该指令通过它们在寄存器中的索引来随机播放字节。它还使用流媒体存储,因为您无法在缓存中容纳三个 1080p 缓冲区。流媒体商店很挑剔,可能有帮助也可能没有帮助,这取决于你在做什么,所以我会对这些进行基准测试。
请注意,此问题受到内存带宽的严重限制,因此虽然它可能比普通 C 版本运行得更快,但它可能不会快 4 倍。您可以在存储之前捆绑的处理越多,它的执行速度就越快。
【讨论】:
为什么说流媒体商店“挑剔”? 该死...我知道我应该得到 8 核和 25MB 缓存 ;-) 说真的,非常感谢 - 我会试一试并报告。跨度> 【参考方案2】:除了 Cory 的回答之外,您还可以尝试多个线程。尽管这是使用多个线程 can increase the throughput for a single socket system by up to a factor of two 的内存绑定(在多套接字系统上甚至更多)。
你可以用 OpenMP 做这样的事情
#pragma omp parallel for
for(int i=0; i<height; i++)
for(int j=0; <width; j+=4)
split_pixels(&src[i*width+j], &fill[i*width+j], &key[i*width+j])
【讨论】:
如果我使用多个线程,我会在 Mac 上使用 dispatch_apply 和 GCD(Grand Central Dispatch)。我的经验是,除非 L3 缓存足够大以容纳源/目标缓冲区,否则跨多个内核条带化工作只会带来最小的收益。以上是关于调配 32 位 alpha 通道所需的 Intel 内在函数的主要内容,如果未能解决你的问题,请参考以下文章
Unity ShadersTransparency —— 使用alpha通道创建透明效果