|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.