簡體   English   中英

ARM霓虹內在函數的深度變換

[英]depth transformation with ARM neon intrinsics

我試圖繞過NEON內在函數,並認為我可以從一個例子開始並提出一些問題。

在這個實驗中,我想將32位RGB轉換為16位BGR。 將以下代碼轉換為使用NEON內在函數會有什么好的開始? 我在這里遇到的問題是16bit與我能看到的任何內在都不匹配。 那里有16x4 16x8等等。但是我只是運氣不好,圍繞着我需要如何解決這個問題。 有小費嗎?

這是我試圖轉換的代碼。

typedef struct {
    uint16_t b:5, g:6, r:5;
} _color16;

static int depth_transform_32_to_16_c (VisVideo *dest, VisVideo *src)
{
    int x, y;
    int w;
    int h;

    _color16 *dbuf = visual_video_get_pixels (dest);
    uint8_t *sbuf = visual_video_get_pixels (src);

    uint16x8

    int ddiff;
    int sdiff;

    depth_transform_get_smallest (dest, src, &w, &h);

    ddiff = (dest->pitch / dest->bpp) - w;
    sdiff = src->pitch - (w * src->bpp);

    for (y = 0; y < h; y++) {
        for (x = 0; x < w; x++) {
            dbuf->b = *(sbuf++) >> 3;
            dbuf->g = *(sbuf++) >> 2;
            dbuf->r = *(sbuf++) >> 3;

            dbuf++;
            sbuf++;
        }

        dbuf += ddiff;
        sbuf += sdiff;
    }

    return VISUAL_OK;
}

編輯:哦,由於某種原因我考慮16x3位,但我們正在考慮5,6,5 = 16位。 我意識到我需要輪班。 嗯。

NEON使用128位寬的寄存器,因此從概念上講,您想要做的是讀取4位32位RGB像素,對它們使用按位運算,最終寫出16位像素。 一個觀察結果是,為了獲得最佳性能,您可能需要組合兩個128位輸入(8個32位像素)並生成一個128輸出。 這將使您的內存訪問更有效。

考慮這個問題的另一種方法是你正在采用你的內循環內容並且並行執行四個像素。 使用原始代碼有點困難的原因是因為你使用位字段而隱藏了一些“魔法”。 如果您將C代碼重寫為32位到16位並使用shift /和/或代碼將更自然地轉換為SIMD,您可以直觀地了解如何使用該上下文中的多個數據。

如果你只看每個32位組件 - > 16位轉換:

00000000RRRRRRRRGGGGGGGGBBBBBBBB
0000000000000000BBBBBGGGGGGRRRRR

這可以幫助您可視化四個像素並行執行的操作。 轉移,提取和組合。 您可以將其視為4個32位通道,但對於某些位操作,寄存器寬度無關緊要(例如,4個32位寄存器或8個16位寄存器是相同的)。

粗偽代碼:

  • 讀(向量加載 )128位寄存器= 4個32位像素。
  • 綠色(所有四個組件)移至右位位置。
  • 將綠色(使用AND掩碼)屏蔽到另一個寄存器中。 (概念上仍然是4x32位“模式”)
  • 紅色(所有四個組件)移至右位位置。
  • 掩蓋紅色到另一個寄存器。
  • 藍色移至右位位置。
  • 將藍色掩蓋到另一個寄存器中。
  • 紅色和藍色移到右位位置。
  • 使用按位OR組合。
  • 現在,您將擁有4個16位值,32位對齊。 (到目前為止,所有概念仍為4x32位)
  • 重復另一組4像素。
  • 將這兩組與NEON解壓縮( VUZP )組合以產生一個128位/ 8像素寄存器。
  • 寫(向量存儲 )那些像素。

暫無
暫無

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

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