簡體   English   中英

如何使用SSE將_m128i轉換為unsigned int?

[英]How do I convert _m128i to an unsigned int with 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個浮點數,但我找不到正確的反向方法。

我搜索了SSE文檔,找不到_mm_cvtepu8_epi32的反向

一個存在嗎?

您需要_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));

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

但是,您當前的方法非常不理想,並且您依賴的是.m128i_u8 ,它是MSVC擴展。 根據我對MSVC的經驗,它將使用對齊的緩沖區來訪問各個元素。 由於部分詞語訪問,這會受到非常嚴重的懲罰。

而不是.m128i_u8 ,使用_mm_extract_epi32() 這是在SSE4.1中。 但是你已經使用_mm_cvtepu8_epi32()依賴SSE4.1了。

由於您使用的是1字節粒度,因此這種情況特別糟糕。 如果您使用的是2字節(16位整數)粒度,則可以使用shuffle內在函數進行有效的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM