我正试图绕过NEON内在函数,并认为我可以从一个例子开始并提出一些问题。
在这个实验中,我想将32位RGB转换为16位BGR。将以下代码转换为使用NEON内在函数会有什么好的开始?我在这里遇到的问题是16bit与我能看到的任何内在都不匹配。那里有16x4 16x8等等。但是我只是运气不好,围绕着我需要如何解决这个问题。有什么提示吗?
这是我要转换的代码。
typedef struct {
uint16_t b:5, g:6, r:5;
} _color16;
static int depth_transform_32_to_16_c (VisVideo *dest, VisVideo *src)
{
int x, y;
int w;
int h;
_color16 *dbuf = visual_video_get_pixels (dest);
uint8_t *sbuf = visual_video_get_pixels (src);
uint16x8
int ddiff;
int sdiff;
depth_transform_get_smallest (dest, src, &w, &h);
ddiff = (dest->pitch / dest->bpp) - w;
sdiff = src->pitch - (w * src->bpp);
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
dbuf->b = *(sbuf++) >> 3;
dbuf->g = *(sbuf++) >> 2;
dbuf->r = *(sbuf++) >> 3;
dbuf++;
sbuf++;
}
dbuf += ddiff;
sbuf += sdiff;
}
return VISUAL_OK;
}
编辑:哦,由于某种原因,我考虑的是16x3位,但我们看的是5,6,5 = 16位。我意识到我需要轮班。 HMM。
答案 0 :(得分:4)
NEON使用128位宽的寄存器,因此从概念上讲,您要做的是读取4位32位RGB像素,对它们使用按位运算,最终写出16位像素。一个观察结果是,为了获得最佳性能,您可能需要组合两个128位输入(8个32位像素)并生成一个128输出。这将使您的内存访问更有效。
考虑这个问题的另一种方法是你正在采用你的内循环内容并且并行执行四个像素。使用原始代码有点困难的原因是因为你使用位字段而隐藏了一些“魔法”。如果您将C代码重写为32位到16位并使用shift /和/或代码将更自然地转换为SIMD,您可以直观地了解如何在该上下文中处理多个数据。
如果你只看每个32位组件 - &gt; 16位转换:
00000000RRRRRRRRGGGGGGGGBBBBBBBB
0000000000000000BBBBBGGGGGGRRRRR
这可以帮助您可视化四个像素并行执行的操作。转移,提取和组合。您可以将此视为4个32位通道,但对于某些位操作,寄存器宽度无关紧要(例如,4个32位寄存器或8个16位寄存器是相同的)。
粗糙的伪代码: