Annotation of nono/lib/bitmap_avx2.cpp, revision 1.1.1.1

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2024 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: //
                      8: // ビットマップ (AVX2)
                      9: //
                     10: 
                     11: #include "bitmap.h"
                     12: #include <x86intrin.h>
                     13: 
                     14: // I8 から RGBX への変換。
                     15: void
                     16: BitmapRGBX::CopyLineI8_avx2(uint32 *d32, const uint8 *s8, uint width,
                     17:        const Color *palette)
                     18: {
                     19:        uint packed = width & ~7;
                     20: 
                     21:        const uint8 *s8total  = s8 + width;
                     22:        const uint8 *s8packed = s8 + packed;
                     23: 
                     24:        for (; s8 < s8packed; ) {
                     25:                // 8ピクセルずつ処理する
                     26: 
                     27:                // s8 は BitmapI8 なのでビッグエンディアン並びに相当。
                     28:                // idx0 = $00000000'00000000'I7I6I5I4'I3I2I1I0
                     29:                __m128i idx0 = _mm_loadl_epi64((const __m128i *)s8);
                     30:                s8 += 8;
                     31: 
                     32:                // idx  = $000000I7'000000I6'000000I5'000000I4'
                     33:                //         000000I3'000000I2'000000I1'000000I0
                     34:                __m256i idx = _mm256_cvtepu8_epi32(idx0);
                     35: 
                     36:                // 8個の 32bit インデックスから XBGR を取得
                     37:                // c  = $00B7G7R7'00B6G6R6'00B5G5R5'00B4G4R4'
                     38:                //       00B3G3R3'00B2G2R2'00B1G1R1'00B0G0R0
                     39:                __m256i c = _mm256_i32gather_epi32((const int *)palette, idx, 4);
                     40: 
                     41:                _mm256_storeu_si256((__m256i *)d32, c);
                     42:                d32 += 8;
                     43:        }
                     44: 
                     45:        // 残りは通常通り処理
                     46:        if (s8 < s8total) {
                     47:                CopyLineI8_gen(d32, s8, (width - packed), palette);
                     48:        }
                     49: }
                     50: 
                     51: // RGBX から RGB への変換。
                     52: void
                     53: BitmapRGBX::ConvertToRGB_avx2(BitmapRGB& dst) const
                     54: {
                     55:        const BitmapRGBX& src = *this;
                     56: 
                     57:        // 256bit リニアに使えれば下詰めで済んだんだが、上位 128bit と
                     58:        // 下位 128bit をまたいでシャッフルは出来なくて、かつこの後のストアは
                     59:        // 連続領域への書き込みになるので、中央でつなげておく。うーん。
                     60:        const __m256i shuff = _mm256_set_epi8(
                     61:                -1,-1,-1,-1, 14,13,12,10,  9, 8, 6, 5,  4, 2, 1, 0,
                     62:                14,13,12,10,  9, 8, 6, 5,  4, 2, 1, 0, -1,-1,-1,-1
                     63:        );
                     64:        const __m256i mask = _mm256_set_epi32(0, -1, -1, -1,  -1, -1, -1, 0);
                     65: 
                     66:        // この変換は一次元配列とみなしても行える。
                     67:        // モニタ等のパネルでも呼ばれるので何ピクセルで割り切れるかの前提は不可。
                     68:        uint total  = GetWidth() * GetHeight();
                     69:        uint packed = total & ~7;
                     70: 
                     71:        const uint32 *s32 = (const uint32 *)src.GetRowPtr(0);
                     72:        const uint32 *s32total  = s32 + total;
                     73:        const uint32 *s32packed = s32 + packed;
                     74: 
                     75:        uint32 *d32 = (uint32 *)dst.GetRowPtr(0);
                     76:        for (; s32 < s32packed; ) {
                     77:                // 8ピクセルずつ処理する
                     78: 
                     79:                // c  = $x7B7G7R7'x6B6G6R6'x5B5G5R5'x4B4G4R4'
                     80:                //       x3B3G3R3'x2B2G2R2'x1B1G1R1'x0B0G0R0
                     81:                __m256i c = _mm256_load_si256((const __m256i *)s32);
                     82:                s32 += 8;
                     83: 
                     84:                // res= $00000000'B7G7R7B6'G6R6B5G5'R5B4G4R4'
                     85:                //       B3G3R3B2'G2R2B1G1'R1B0G0R0'00000000
                     86:                __m256i res = _mm256_shuffle_epi8(c, shuff);
                     87: 
                     88:                // 先頭(下位)と末尾(上位)の 32bit ずつを除いたところを書き出す。
                     89:                _mm256_maskstore_epi32((int *)(d32 - 1), mask, res);
                     90:                d32 += 6;
                     91:        }
                     92: 
                     93:        uint8 *d8 = (uint8 *)d32;
                     94:        for (; s32 < s32total; ) {
                     95:                // 残りを1ピクセルずつ処理する
                     96:                Color c(*s32++);
                     97:                *d8++ = c.r;
                     98:                *d8++ = c.g;
                     99:                *d8++ = c.b;
                    100:        }
                    101: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.