2012-10-31 41 views
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。

+3

一般来说,如果你有8个数据,不想转换为浮点型来进行alpha混合;您可以使用16位定点算法获得足够的精度,从而可以在每个矢量中保留更多像素。 –

回答

2

你就近了。在采取倒数之前,您需要将255的向量转换为浮点数。

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

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

1

不是100%的答案,但由于你迄今没有得到任何其他人,我以为我会帮你开始;

从我记得,你可以使用vmov.f32加载浮动的子集是非常有限的,所以如果你想加载一个任意的浮动,你需要将它存储为一个常量,并使用vldr从常量池加载它。像这样的东西应该这样做;

ldr r1,=floats 

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

floats: 
.float 0.003921569 

的“不是100%”的部分是,我还没有进去看了向量指令,所以我不能确定是否可以在此代码替换s0q1马上或者如果你需要移动s0到加载后加载q1

+0

感谢您的回答!是的,霓虹灯也可以加载恒定。 asm代码嵌入在C中,所以我也可以在c中计算float常量。但霓虹灯不能像r0那样移动寄存器到Q0/S0,对吗?也许我必须将常量传递给变量并将可变地址传递给嵌入的asm代码。 –

+0

@RichardZhao:当然你可以从r0移动到s0。 'vmov s0,r0'。你也可以将一个预先计算好的常量直接加载到's0'或'q0',这可能是你真正想要的。 –

0

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

编译器负责计算不变,VDUP指令值广播到向量的所有四个车道

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

1

你真的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