ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
video/ascii/avx2/common.c
Go to the documentation of this file.
1
5
6#include <stdint.h>
7#include <ascii-chat/common.h>
9
10#if SIMD_SUPPORT_AVX2
11#include <immintrin.h>
12
13// Thread-local storage for AVX2 working buffers
14// These stay in L1 cache and are reused across function calls
15// Non-static for shared library compatibility (still thread-local)
16THREAD_LOCAL _Alignas(32) uint8_t avx2_r_buffer[32];
17THREAD_LOCAL _Alignas(32) uint8_t avx2_g_buffer[32];
18THREAD_LOCAL _Alignas(32) uint8_t avx2_b_buffer[32];
19THREAD_LOCAL _Alignas(32) uint8_t avx2_luminance_buffer[32];
20
21// Optimized AVX2 function to load 32 RGB pixels and separate channels
22// Uses simple loop that auto-vectorizes to VMOVDQU + VPSHUFB
23void avx2_load_rgb32_optimized(const rgb_pixel_t *__restrict pixels, uint8_t *__restrict r_out,
24 uint8_t *__restrict g_out, uint8_t *__restrict b_out) {
25 // Simple loop that compiler auto-vectorizes into efficient SIMD
26 for (int i = 0; i < 32; i++) {
27 r_out[i] = pixels[i].r;
28 g_out[i] = pixels[i].g;
29 b_out[i] = pixels[i].b;
30 }
31}
32
33// AVX2 function to compute luminance for 32 pixels
34void avx2_compute_luminance_32(const uint8_t *r_vals, const uint8_t *g_vals, const uint8_t *b_vals,
35 uint8_t *luminance_out) {
36 // Load all 32 RGB values into AVX2 registers
37 __m256i r_all = _mm256_loadu_si256((const __m256i_u *)r_vals);
38 __m256i g_all = _mm256_loadu_si256((const __m256i_u *)g_vals);
39 __m256i b_all = _mm256_loadu_si256((const __m256i_u *)b_vals);
40
41 // Process low 16 pixels with accurate coefficients (16-bit math to prevent overflow)
42 __m256i r_lo = _mm256_unpacklo_epi8(r_all, _mm256_setzero_si256());
43 __m256i g_lo = _mm256_unpacklo_epi8(g_all, _mm256_setzero_si256());
44 __m256i b_lo = _mm256_unpacklo_epi8(b_all, _mm256_setzero_si256());
45
46 __m256i luma_16_lo = _mm256_mullo_epi16(r_lo, _mm256_set1_epi16(77));
47 luma_16_lo = _mm256_add_epi16(luma_16_lo, _mm256_mullo_epi16(g_lo, _mm256_set1_epi16(150)));
48 luma_16_lo = _mm256_add_epi16(luma_16_lo, _mm256_mullo_epi16(b_lo, _mm256_set1_epi16(29)));
49 luma_16_lo = _mm256_add_epi16(luma_16_lo, _mm256_set1_epi16(128));
50 luma_16_lo = _mm256_srli_epi16(luma_16_lo, 8);
51
52 // Process high 16 pixels with accurate coefficients
53 __m256i r_hi = _mm256_unpackhi_epi8(r_all, _mm256_setzero_si256());
54 __m256i g_hi = _mm256_unpackhi_epi8(g_all, _mm256_setzero_si256());
55 __m256i b_hi = _mm256_unpackhi_epi8(b_all, _mm256_setzero_si256());
56
57 __m256i luma_16_hi = _mm256_mullo_epi16(r_hi, _mm256_set1_epi16(77));
58 luma_16_hi = _mm256_add_epi16(luma_16_hi, _mm256_mullo_epi16(g_hi, _mm256_set1_epi16(150)));
59 luma_16_hi = _mm256_add_epi16(luma_16_hi, _mm256_mullo_epi16(b_hi, _mm256_set1_epi16(29)));
60 luma_16_hi = _mm256_add_epi16(luma_16_hi, _mm256_set1_epi16(128));
61 luma_16_hi = _mm256_srli_epi16(luma_16_hi, 8);
62
63 // Pack back to 8-bit
64 __m256i luma_packed = _mm256_packus_epi16(luma_16_lo, luma_16_hi);
65
66 // After unpack and pack operations, bytes are already in correct order [0-31]
67 // luma_16_lo contains pixels 0-7 (lower 128) and 16-23 (upper 128)
68 // luma_16_hi contains pixels 8-15 (lower 128) and 24-31 (upper 128)
69 // packus produces: [0-7, 8-15] in lower 128, [16-23, 24-31] in upper 128
70 // No permute needed - this is already the correct sequential order
71 _mm256_storeu_si256((__m256i_u *)luminance_out, luma_packed);
72}
73
74#endif // SIMD_SUPPORT_AVX2
⚙️ Common definitions, error codes, macros, and types shared throughout the application
unsigned char uint8_t
Definition common.h:60
SIMD-optimized ASCII conversion interface.