c - 快速 24 位数组 -> 32 位数组转换?

标签 c bitmap bit-manipulation sse simd

快速总结:

我有一个 24 位值数组。关于如何快速将单个 24 位数组元素扩展为 32 位元素的任何建议?

详细信息:

我正在使用 DirectX 10 中的像素着色器实时处理传入的视频帧。一个绊脚石是我的帧来自具有 24 位像素的捕获硬件(作为 YUV 或 RGB 图像),但 DX10 需要32 位像素纹理。因此,我必须先将 24 位值扩展为 32 位,然后才能将它们加载到 GPU 中。

我真的不在乎我将剩余的 8 位设置为什么,或者传入的 24 位在 32 位值中的位置 - 我可以在像素着色器中修复所有这些。但我需要快速完成从 24 位到 32 位的转换真的

我不是很熟悉 SIMD SSE 操作,但从我粗略的一瞥来看,我似乎无法使用它们进行扩展,因为我的读取和写入大小不同。有什么建议么?还是我一直在按顺序处理这个数据集?

这感觉非常愚蠢 - 我正在使用像素着色器进行并行处理,但在此之前我必须执行顺序的每像素操作。我一定遗漏了一些明显的东西......

最佳答案

下面的代码应该非常快。它在每次迭代中复制 4 个像素,仅使用 32 位读/写指令。源指针和目标指针应对齐到 32 位。

uint32_t *src = ...;
uint32_t *dst = ...;

for (int i=0; i<num_pixels; i+=4) {
    uint32_t sa = src[0];
    uint32_t sb = src[1];
    uint32_t sc = src[2];

    dst[i+0] = sa;
    dst[i+1] = (sa>>24) | (sb<<8);
    dst[i+2] = (sb>>16) | (sc<<16);
    dst[i+3] = sc>>8;

    src += 3;
}

编辑:

这是使用 SSSE3 指令 PSHUFB 和 PALIGNR 执行此操作的方法。代码是使用编译器内在函数编写的,但如果需要,应该不难将其转换为汇编代码。它在每次迭代中复制 16 个像素。源指针和目标指针必须对齐到 16 字节,否则会出错。如果它们未对齐,您可以通过将 _mm_load_si128 替换为 _mm_loadu_si128 并将 _mm_store_si128 替换为 _mm_storeu_si128 使其工作,但这会更慢。

#include <emmintrin.h>
#include <tmmintrin.h>

__m128i *src = ...;
__m128i *dst = ...;
__m128i mask = _mm_setr_epi8(0,1,2,-1, 3,4,5,-1, 6,7,8,-1, 9,10,11,-1);

for (int i=0; i<num_pixels; i+=16) {
    __m128i sa = _mm_load_si128(src);
    __m128i sb = _mm_load_si128(src+1);
    __m128i sc = _mm_load_si128(src+2);

    __m128i val = _mm_shuffle_epi8(sa, mask);
    _mm_store_si128(dst, val);
    val = _mm_shuffle_epi8(_mm_alignr_epi8(sb, sa, 12), mask);
    _mm_store_si128(dst+1, val);
    val = _mm_shuffle_epi8(_mm_alignr_epi8(sc, sb, 8), mask);
    _mm_store_si128(dst+2, val);
    val = _mm_shuffle_epi8(_mm_alignr_epi8(sc, sc, 4), mask);
    _mm_store_si128(dst+3, val);

    src += 3;
    dst += 4;
}

SSSE3(不要与 SSE3 混淆)需要相对较新的处理器:Core 2 或更新版本,我相信 AMD 尚不支持它。仅使用 SSE2 指令执行此操作将需要更多操作,而且可能不值得。

关于c - 快速 24 位数组 -> 32 位数组转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2973708/

相关文章:

javascript - 有什么方法可以使用 HTML5/CSS/Javascript 对位图进行颜色转换吗?

c - 这里按位或用什么?

c - 直接以二进制执行计算机指令

c - 如何使用 `offsetof` 以符合标准的方式访问字段?

python - 在 python 扩展 (.so) 中同时链接 libgfortran 和 libstdc++

c - 意外的 C/C++ 移位运算符结果

java - 拍照和使用图像 - 内存不足错误

iphone - iOS:将 6x6 400x300px 图像添加到一张合成图像

javascript - UTF-8 编码算法如何在 8 位 block 上工作(在 JavaScript 中)?

c++ - 在不使用Abs函数或if语句的情况下获取绝对值