如何使用霓虹灯创建1/255 f32矢量?

时间:2012-10-31 05:25:45

标签: arm neon

当我计算alpha混合时,我需要将8bit alpha转换为float,即alpha / 255。因为NEON没有分裂,我想要alpha * 1/255。那么如何在q1中生成1/255向量?

vmov.f32 q1,#0.003921569始终报告错误。

vmov.u32 q1,#255 vrecpe.u32 q1,q1总是在f32中生成0。

4 个答案:

答案 0 :(得分:2)

你很亲密。你需要在取倒数之前将255的向量转换为浮点数。

vmov.u32        q0, #255
vcvt.f32.u32    q0, q0
vrecpe.f32      q1, q0

请注意vrecpe有少量错误,但它应该足够接近alpha混合。

答案 1 :(得分:1)

不是100%的答案,但是因为到目前为止你没有得到任何其他人,我以为我会帮助你开始;

根据我的记忆,您可以使用vmov.f32加载的浮点子集非常有限,因此如果要加载任意浮点数,则需要将其存储为常量并从常量池加载它使用vldr。像这样的东西应该这样做;

ldr r1,=floats 

vldr.32 s0,[r1]     @1/256

floats:
.float 0.003921569

“不是100%”部分是因为我没有查看向量说明,因此我不确定您是否可以在此代码中使用s0立即替换q1,或者如果您需要在加载后将s0移至q1

答案 2 :(得分:1)

你真的不需要为浮点数而烦恼。给出:

y = rint(x * a / 255.0);

对于没有浮点使用的任何8位输入,您可以得到相同的结果:

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

通常,最后两个操作实现从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

答案 3 :(得分:0)

可能你想要的 float32x4_t x = vdupq_n_32(1.0f / 255);

编译器负责计算常量,vdup指令将值广播到向量的所有四个通道

vdup指令支持NEON标量和ARM寄存器作为源操作数