GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 110
Functions: 0.0% 0 / 0 / 4
Branches: 0.0% 0 / 0 / 36

convert/intel/convert_rgb_avx512.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
3
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35 #include <avs/config.h>
36 #include <avs/types.h>
37 #include <cstdint>
38
39 #include "../../filters/intel/check_avx512.h" // compiler avx512 directives check
40 #include "convert_rgb_avx512.h"
41
42 #include <immintrin.h> // Includes AVX-512 intrinsics
43
44 template<typename pixel_t, bool targetHasAlpha>
45 void convert_rgba_to_rgbp_avx512vbmi(const BYTE *srcp, BYTE * (&dstp)[4],
46 int src_pitch, int (&dst_pitch)[4], int width, int height)
47 {
48 // 8-bit: 16 BGRA8 pixels = 64 bytes fits in one ZMM
49 // 16-bit: 8 BGRA16 pixels = 64 bytes fits in one ZMM
50 const int pixels_at_a_time = (sizeof(pixel_t) == 1) ? 16 : 8;
51
52 // Build the vpermb index vector, constant, computed once
53 __m512i perm;
54 if constexpr (sizeof(pixel_t) == 1) {
55 // B channel: bytes 0,4,8,...,60 (stride 4, offset 0)
56 // G channel: bytes 1,5,9,...,61 (stride 4, offset 1)
57 // R channel: bytes 2,6,10,...,62 (stride 4, offset 2)
58 // A channel: bytes 3,7,11,...,63 (stride 4, offset 3)
59 alignas(64) uint8_t idx[64];
60 for (int i = 0; i < 16; i++) idx[i] = i * 4 + 0; // B
61 for (int i = 0; i < 16; i++) idx[16+i] = i * 4 + 1; // G
62 for (int i = 0; i < 16; i++) idx[32+i] = i * 4 + 2; // R
63 for (int i = 0; i < 16; i++) idx[48+i] = i * 4 + 3; // A
64 perm = _mm512_load_si512(reinterpret_cast<const __m512i *>(idx));
65 }
66 else {
67 alignas(64) uint8_t idx[64];
68 for (int i = 0; i < 8; i++) {
69 idx[i * 2 + 0] = (uint8_t)(i * 8 + 0); // B low byte
70 idx[i * 2 + 1] = (uint8_t)(i * 8 + 1); // B high byte
71 idx[16 + i * 2 + 0] = (uint8_t)(i * 8 + 2); // G low byte
72 idx[16 + i * 2 + 1] = (uint8_t)(i * 8 + 3); // G high byte
73 idx[32 + i * 2 + 0] = (uint8_t)(i * 8 + 4); // R low byte
74 idx[32 + i * 2 + 1] = (uint8_t)(i * 8 + 5); // R high byte
75 idx[48 + i * 2 + 0] = (uint8_t)(i * 8 + 6); // A low byte
76 idx[48 + i * 2 + 1] = (uint8_t)(i * 8 + 7); // A high byte
77 }
78 perm = _mm512_load_si512(reinterpret_cast<const __m512i*>(idx));
79 }
80
81 // No remainder: BGRA source is 4 bytes/pixel, 64-byte aligned scanlines guarantee width is a multiple of 16 (8-bit) or 8 (16-bit)
82 for (int y = height; y > 0; --y) {
83 for (int x = 0; x < width; x += pixels_at_a_time) {
84 __m512i src = _mm512_load_si512(
85 reinterpret_cast<const __m512i *>(srcp + x * 4 * sizeof(pixel_t)));
86
87 // 64-byte cross-lane permutation
88 // Result layout:
89 // bytes 0-15: B0..B15 (8-bit) or B0..B7 as pairs (16-bit)
90 // bytes 16-31: G channel
91 // bytes 32-47: R channel
92 // bytes 48-63: A channel
93 __m512i result = _mm512_permutexvar_epi8(perm, src);
94
95 // Extract each 128-bit quarter and store
96 // _mm512_extracti32x4_epi32: extract 128-bit lane 0,1,2,3
97 __m128i B = _mm512_extracti32x4_epi32(result, 0);
98 __m128i G = _mm512_extracti32x4_epi32(result, 1);
99 __m128i R = _mm512_extracti32x4_epi32(result, 2);
100 __m128i A = _mm512_extracti32x4_epi32(result, 3);
101
102 _mm_store_si128(reinterpret_cast<__m128i *>(dstp[1] + x * sizeof(pixel_t)), B);
103 _mm_store_si128(reinterpret_cast<__m128i *>(dstp[0] + x * sizeof(pixel_t)), G);
104 _mm_store_si128(reinterpret_cast<__m128i *>(dstp[2] + x * sizeof(pixel_t)), R);
105 if constexpr (targetHasAlpha)
106 _mm_store_si128(reinterpret_cast<__m128i *>(dstp[3] + x * sizeof(pixel_t)), A);
107 }
108
109
110 srcp -= src_pitch;
111 dstp[0] += dst_pitch[0];
112 dstp[1] += dst_pitch[1];
113 dstp[2] += dst_pitch[2];
114 if constexpr (targetHasAlpha)
115 dstp[3] += dst_pitch[3];
116 }
117 }
118
119 // Instantiations
120 template void convert_rgba_to_rgbp_avx512vbmi<uint8_t, false>(const BYTE* srcp, BYTE* (&dstp)[4], int src_pitch, int(&dst_pitch)[4], int width, int height);
121 template void convert_rgba_to_rgbp_avx512vbmi<uint8_t, true>(const BYTE* srcp, BYTE* (&dstp)[4], int src_pitch, int(&dst_pitch)[4], int width, int height);
122 template void convert_rgba_to_rgbp_avx512vbmi<uint16_t, false>(const BYTE* srcp, BYTE* (&dstp)[4], int src_pitch, int(&dst_pitch)[4], int width, int height);
123 template void convert_rgba_to_rgbp_avx512vbmi<uint16_t, true>(const BYTE* srcp, BYTE* (&dstp)[4], int src_pitch, int(&dst_pitch)[4], int width, int height);
124