当我计算 alpha blending 时,我需要将 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。
你很亲密。在取倒数之前,您需要将 255 的向量转换为浮点数。
vmov.u32 q0, #255
vcvt.f32.u32 q0, q0
vrecpe.f32 q1, q0
请注意,它vrecpe
有少量错误,但它应该足够接近 Alpha 混合。
对于微不足道的 alpha 混合,您真的不需要为浮点数烦恼。鉴于:
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
不是 100% 的答案,但由于到目前为止你没有得到任何其他答案,我想我会帮助你开始;
据我记得,您可以使用的浮点子集vmov.f32
非常有限,因此如果您想加载任意浮点数,您需要将其存储为常量并使用vldr
. 像这样的事情应该这样做;
ldr r1,=floats
vldr.32 s0,[r1] @1/256
floats:
.float 0.003921569
“不是 100%”部分是我没有查看向量指令,所以我不确定您是否可以s0
立即在此代码中替换,或者您是否需要在加载后q1
移至。s0
q1
可能你想要 float32x4_t x = vdupq_n_32(1.0f / 255);
编译器负责计算常数,vdup 指令将值广播到向量的所有四个通道
vdup 指令支持 NEON 标量和 ARM 寄存器作为源操作数