2011-12-22 54 views
4

我已經制作了一個用於張貼圖像的功能。如何將_m128i轉換爲帶有SSE的無符號整數?

// =(
#define ARGB_COLOR(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) 

inline UINT PosterizeColor(const UINT &color, const float &nColors) 
{ 
    __m128 clr = _mm_cvtepi32_ps( _mm_cvtepu8_epi32((__m128i&)color) ); 

    clr = _mm_mul_ps(clr, _mm_set_ps1(nColors/255.0f) ); 
    clr = _mm_round_ps(clr, _MM_FROUND_TO_NEAREST_INT); 
    clr = _mm_mul_ps(clr, _mm_set_ps1(255.0f/nColors) ); 

    __m128i iClr = _mm_cvttps_epi32(clr); 

    return ARGB_COLOR(iClr.m128i_u8[12], 
         iClr.m128i_u8[8], 
         iClr.m128i_u8[4], 
         iClr.m128i_u8[0]); 
} 
在第一線

,我解開顏色分爲4個浮點,但我不能找到合適的方式做相反。

我搜索通過上證所文檔,找不到的_mm_cvtepu8_epi32

反向確實存在一個?

回答

5

不幸的是,即使在AVX中也沒有這樣做的說明(我沒有意識到)。所以你必須手動完成,就像現在一樣。

但是,您目前的方法是非常不理想的,而您依靠的是.m128i_u8這是一個MSVC擴展。根據我對MSVC的經驗,它將使用對齊的緩衝區來訪問各個元素。由於部分單詞訪問,這有非常嚴重的處罰。

而不是.m128i_u8,請使用_mm_extract_epi32()。這是在SSE4.1中。但是你已經依靠與_mm_cvtepu8_epi32()的SSE4.1。

由於您使用的是1字節的粒度,所以這種情況尤其糟糕。如果您使用的是2字節(16位整數)粒度,則使用shuffle intrinsics有效的解決方案。

+0

_mm_extract_epi32()幫助了一點,但你所說的「非常次優」是什麼意思? – bitwise

+0

一般來說,當您存儲一些數據,然後立即嘗試以不同的字號訪問它時,將會有一個巨大的懲罰。從我所看到的,MSVC提取'xmm'寄存器組件的方法就是:存儲到內存中,並單獨訪問這些單詞。但我想這個特例並不是最壞的情況。 – Mysticial

+0

好的,無論如何,對於2048x2048它運行在22ms,我認爲現在已經足夠了。謝謝=) – bitwise

8

_mm_shuffle_epi8_mm_cvtsi128_si32組合是你所需要的:

static const __m128i shuffleMask = _mm_setr_epi8(0, 4, 8, 12, -1, -1, -1, -1, 
               -1, -1, -1, -1, -1, -1, -1, -1); 
UINT color = _mm_cvtsi128_si32(_mm_shuffle_epi8(iClr, shuffleMask)); 
+0

小錯誤:'_mm_set_epi8'應該是'_mm_setr_epi8'。否則,這實際上工作!我很驚訝,+1。我沒有意識到SSSE3有一個字節粒度的洗牌。 – Mysticial

+0

感謝這一點,但我也發現我可以做到這一點,這給了我幾乎相同的結果,如上所示: \t \t iClr = _mm_packs_epi32(iClr,_mm_setzero_si128()); \t \t iClr = _mm_packus_epi16(iClr,_mm_setzero_si128()); UINT color =(UINT)_mm_extract_epi32(iClr,0); - 我還使用整數數學重寫了例程,然後將其轉換爲asm,從而爲2048x2048圖像生成8〜9 ms的最佳結果。 – bitwise

+0

@bitwise我認爲這應該是被接受的答案。 – Antonio

相關問題