2012-10-31 76 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