当我计算阿尔法混合,我需要转换8位阿尔法浮动,这将是阿尔法/ 255。因为NEON没有分裂,所以我想alpha * 1/255。那么如何在q1中生成1/255向量呢?如何使用霓虹灯创建1/255 f32矢量?
vmov.f32 q1,#0.003921569总是报告错误。
vmov.u32 q1,#255 vrecpe.u32 q1,q1总是在f32中产生0。
当我计算阿尔法混合,我需要转换8位阿尔法浮动,这将是阿尔法/ 255。因为NEON没有分裂,所以我想alpha * 1/255。那么如何在q1中生成1/255向量呢?如何使用霓虹灯创建1/255 f32矢量?
vmov.f32 q1,#0.003921569总是报告错误。
vmov.u32 q1,#255 vrecpe.u32 q1,q1总是在f32中产生0。
你就近了。在采取倒数之前,您需要将255的向量转换为浮点数。
vmov.u32 q0, #255
vcvt.f32.u32 q0, q0
vrecpe.f32 q1, q0
注意,vrecpe
有错误的量小,但它应该是alpha混合足够接近。
不是100%的答案,但由于你迄今没有得到任何其他人,我以为我会帮你开始;
从我记得,你可以使用vmov.f32
加载浮动的子集是非常有限的,所以如果你想加载一个任意的浮动,你需要将它存储为一个常量,并使用vldr
从常量池加载它。像这样的东西应该这样做;
ldr r1,=floats
vldr.32 s0,[r1] @1/256
floats:
.float 0.003921569
的“不是100%”的部分是,我还没有进去看了向量指令,所以我不能确定是否可以在此代码替换s0
与q1
马上或者如果你需要移动s0
到加载后加载q1
。
感谢您的回答!是的,霓虹灯也可以加载恒定。 asm代码嵌入在C中,所以我也可以在c中计算float常量。但霓虹灯不能像r0那样移动寄存器到Q0/S0,对吗?也许我必须将常量传递给变量并将可变地址传递给嵌入的asm代码。 –
@RichardZhao:当然你可以从r0移动到s0。 'vmov s0,r0'。你也可以将一个预先计算好的常量直接加载到's0'或'q0',这可能是你真正想要的。 –
可能你想要 float32x4_t x = vdupq_n_32(1.0f/255);
编译器负责计算不变,VDUP指令值广播到向量的所有四个车道
的VDUP指令支持NEON标量和ARM寄存器作为源操作数
你真的needn”不必担心浮点操作可能会导致一个简单的alpha混合。鉴于:
t = x * a;
t += (t + 0x80) >> 8;
y = (t + 0x80) >> 8;
这是一样的东西:
; given eight 8-bit x in d0, and eight 8-bit a in d1
vmull.u8 q2, d0, d1
vrsra.u16 q2, q2, #8
vrshrn.u16 d2, q2, #8
; result is eight 8-bit (s*a/255) in d2
一般最后两个
y = rint(x * a/255.0);
可以使用得到相同的结果对于任何8位输入,而不浮点操作实现了从16位输入到8位输出的全面划分255;但他们依赖于8乘8乘的有限范围。如果16位中间比乘法而造成的更多的则可能有必要夹紧,并且因为没有vqrsra
顺序变长:
; given eight 8-bit x in d0, and eight 8-bit a in d1
vmull.u8 q2, d0, d1
???
vrshr.u16 q3, q2, #8
vqadd.u16 q2, q2, q3
vqrshrn.u16 d2, q2, #8
; result is eight 8-bit (s*a/255) in d2
一般来说,如果你有8个数据,不想转换为浮点型来进行alpha混合;您可以使用16位定点算法获得足够的精度,从而可以在每个矢量中保留更多像素。 –