Skip to content

Commit f89ddb9

Browse files
committed
Fix AVX512 H-resampler coeff preparation for fixed-type coeff advances, regardless of filter_size_real.
1 parent fcb9c8a commit f89ddb9

3 files changed

Lines changed: 26 additions & 17 deletions

File tree

avs_core/filters/intel/resample_avx512.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ void resizer_h_avx512_generic_float_pix16_sub4_ks_4_8_16(BYTE * dst8, const BYTE
133133

134134
// transpose and hi/lo unpack of resampling program for permute-based H-resizers
135135
// allocate and fill pixel_coefficient_AVX512_H coeffs buffer of the ResamplingProgram
136-
void resize_prepare_coeffs_AVX512_H(ResamplingProgram* p, IScriptEnvironment* env, int iSamplesInTheGroup, int iGroupsCount);
136+
// fixed_kernel_size: number of taps the target kernel's fixed unrolled loop always reads
137+
// per x-group (now 4, 8 or 16), so the coefficient table stride matches the kernel's fixed
138+
// index advance amount, regardless of filter_size_real.
139+
// For variable-loop kernels (ks48/ks64) 0 must be passed, which read exactly filter_size_real taps.
140+
void resize_prepare_coeffs_AVX512_H(ResamplingProgram* p, IScriptEnvironment* env, int iSamplesInTheGroup, int iGroupsCount, int fixed_kernel_size);
137141
// allocate and fill pixel_coefficient_AVX512_float_H for float permutex-based H-resizers (ks16 variants)
138142
void resize_prepare_coeffs_AVX512_float_H(ResamplingProgram* p, IScriptEnvironment* env);
139143

avs_core/filters/intel/resample_avx512b.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3458,7 +3458,8 @@ template void resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks16_pretranspos
34583458
template void resize_h_planar_uint16_avx512_permutex_vstripe_mp_4s16_ks48_pretransposed_coeffs_base<false>(BYTE* dst8, const BYTE* src8, int dst_pitch, int src_pitch, ResamplingProgram* program, int width, int height, int bits_per_pixel);
34593459
template void resize_h_planar_uint16_avx512_permutex_vstripe_mp_4s16_ks48_pretransposed_coeffs_base<true>(BYTE* dst8, const BYTE* src8, int dst_pitch, int src_pitch, ResamplingProgram* program, int width, int height, int bits_per_pixel);
34603460

3461-
void resize_prepare_coeffs_AVX512_H(ResamplingProgram* p, IScriptEnvironment* env, int iSamplesInTheGroup, int iGroupsCount) {
3461+
// fixed_kernel_size == 0 marks: "not fixed".
3462+
void resize_prepare_coeffs_AVX512_H(ResamplingProgram* p, IScriptEnvironment* env, int iSamplesInTheGroup, int iGroupsCount, int fixed_kernel_size) {
34623463
// note: filter_size_real was the max(kernel_sizes[])
34633464
int filter_size_aligned = AlignNumber(p->filter_size_real, p->filter_size_alignment);
34643465
// FIXME: really this needs to be dynamic based on SIMD used in resizer
@@ -3517,12 +3518,16 @@ void resize_prepare_coeffs_AVX512_H(ResamplingProgram* p, IScriptEnvironment* en
35173518
return *(current_coeff + filter_size_padded * std::min(j, avail - 1) + ki);
35183519
};
35193520
// process by 2 rows because madd/dp can only make FMA from 2 unpacked uint16 pairs
3520-
// ks16 (iSamplesAtATime==32): filter always reads 16 vectors per x-group (advance by 16),
3521-
// so we must store all filter_size_aligned/2 pairs even when filter_size_real < 16.
3521+
// Specific unrolled kernels (ks4/ks8/ks16) read a fixed number of taps per group of x.
3522+
// They advance current_coeff_SIMD by an appropriate fixed amount, regardless of
3523+
// filter_size_real. The coefficient table must be padded to that same fixed width
3524+
// (fixed_kernel_size) or else discrapancy happens after the first x group.
35223525
// Extra iterations access zero-padded taps and produce zero coefficient pairs — harmless.
3523-
// ks64 (iSamplesAtATime==64): filter advances by filter_size_real*2 (variable), so it uses
3524-
// filter_size_to_process to store exactly that many pairs — must NOT use filter_size_aligned.
3525-
const int i_limit = (iSamplesAtATime == 32) ? filter_size_aligned : filter_size_to_process;
3526+
// For variable loop kernels like ks48/ks64 (signalled as fixed_kernel_size==0) advance
3527+
// current_coeff_SIMD by filter_size_real*2 (pairs), so they must store exactly filter_size_to_process
3528+
// pairs, contrary to the previous case, padding to a fixed width would cause coeff desynchronization
3529+
// after the first x group.
3530+
const int i_limit = (fixed_kernel_size > 0) ? fixed_kernel_size : filter_size_to_process;
35263531
for (int i = 0; i < i_limit; i += 2)
35273532
{
35283533
if (iSamplesAtATime == 64) // 2 groups of 32 coeffs for columns 0..31 and 32..63

avs_core/filters/resample.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
17321732
17331733
Winners: (Fast) resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks4_vnni (Base) resize_h_planar_uint8_avx512_permutex_vstripe_ks4_base
17341734
*/
1735-
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1735+
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 4/*fixed_kernel_size*/);
17361736
if (has_AVX512_fast)
17371737
return resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks4_pretransposed_coeffs_vnni;
17381738
else
@@ -1763,14 +1763,14 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
17631763
17641764
Winners: (Fast) resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks8_vnni (Base) resize_h_planar_uint8_avx512_permutex_vstripe_ks8_base
17651765
*/
1766-
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1766+
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 8/*fixed_kernel_size*/);
17671767
if (has_AVX512_fast)
17681768
return resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks8_pretransposed_coeffs_vnni;
17691769
else
17701770
return resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks8_pretransposed_coeffs_base;
17711771
}
17721772
if (!program->resize_h_planar_gather_permutex_vstripe_check(32/*iSamplesInTheGroup*/, 128/*permutex_index_diff_limit*/, 8/*kernel_size*/)) { // slower ks8 but more downsample ratio for /2
1773-
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 2/*iGroupsCount*/);
1773+
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 2/*iGroupsCount*/, 8/*fixed_kernel_size*/);
17741774
if (has_AVX512_fast)
17751775
return resize_h_planar_uint8_avx512_permutex_vstripe_2s32_ks8_pretransposed_coeffs_vnni;
17761776
else
@@ -1794,7 +1794,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
17941794
17951795
Winners: (Fast) resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks16_vnni (Base) resize_h_planar_uint8_avx512_permutex_vstripe_ks16_base
17961796
*/
1797-
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1797+
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 16/*fixed_kernel_size*/);
17981798
if (has_AVX512_fast)
17991799
return resize_h_planar_uint8_avx512_permutex_vstripe_mpz_ks16_pretransposed_coeffs_vnni;
18001800
else
@@ -1803,7 +1803,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
18031803
}
18041804
if (!program->resize_h_planar_gather_permutex_vstripe_check(32/*iSamplesInTheGroup*/, 128/*permutex_index_diff_limit*/, program->filter_size_real/*kernel_size*/))
18051805
{
1806-
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 2/*iGroupsCount*/);
1806+
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 2/*iGroupsCount*/, 0/*fixed_kernel_size: variable-loop kernel*/);
18071807
if (has_AVX512_fast)
18081808
return resize_h_planar_uint8_avx512_permutex_vstripe_mpz_2s32_ks64_pretransposed_coeffs_vnni;
18091809
else
@@ -1854,7 +1854,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
18541854
Fazit: The MP versions' difference is only two VNNI instructions between BASE/FAST, in benchmarks zero visible speed benefit is seen.
18551855
Winners: (Both mp) (Fast) resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks4_vnni (Base) resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks4_base
18561856
*/
1857-
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1857+
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 4/*fixed_kernel_size*/);
18581858
if (bits_per_pixel < 16) {
18591859
if (has_AVX512_fast)
18601860
return resize_h_planar_uint16_avx512_permutex_vstripe_mp_2s32_ks4_pretransposed_coeffs_vnni<true>;
@@ -1880,7 +1880,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
18801880
Fazit: The MP versions' difference is only two VNNI instructions between BASE/FAST, in benchmarks 1-2% visible speed benefit is seen.
18811881
Winners: (Both mp) (Fast) resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks8_vnni (Base) resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks8_base
18821882
*/
1883-
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1883+
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 8/*fixed_kernel_size*/);
18841884
if (bits_per_pixel < 16) {
18851885
if (has_AVX512_fast)
18861886
return resize_h_planar_uint16_avx512_permutex_vstripe_mp_2s32_ks8_pretransposed_coeffs_vnni<true>;
@@ -1903,7 +1903,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
19031903
// Case E LanczosResize(int(width*0.5 + 0.5), height, taps=2) kernel size 8
19041904
// Case R: LanczosResize(int(width*0.5 + 0.5), height, taps=2) kernel size 8
19051905
if (!program->resize_h_planar_gather_permutex_vstripe_check(16/*iSamplesInTheGroup*/, 64/*permutex_index_diff_limit*/, 8/*kernel_size*/)) {
1906-
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1906+
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 8/*fixed_kernel_size*/);
19071907
if (bits_per_pixel < 16) {
19081908
if (has_AVX512_fast)
19091909
return resize_h_planar_uint16_avx512_permutex_vstripe_mp_4s16_ks8_pretransposed_coeffs_vnni<true>;
@@ -1937,7 +1937,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
19371937
resizer_h_avx2_generic_uint16_t (fallback) 1156 1085 1292
19381938
Winners: (Both mp) (Fast) resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks8_vnni (Base) resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks8_base
19391939
*/
1940-
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1940+
resize_prepare_coeffs_AVX512_H(program, env, 32/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 16/*fixed_kernel_size*/);
19411941
if (bits_per_pixel < 16) {
19421942
if (has_AVX512_fast)
19431943
return resize_h_planar_uint16_avx512_permutex_vstripe_mp_ks16_pretransposed_coeffs_vnni<true>;
@@ -1962,7 +1962,7 @@ ResamplerH FilteredResizeH::GetResampler(int CPU, int pixelsize, int bits_per_pi
19621962
// The function itself has no hard 48 limit; it loops over filter_size_real directly.
19631963
if (!program->resize_h_planar_gather_permutex_vstripe_check(16/*iSamplesInTheGroup*/, 64/*permutex_index_diff_limit*/, program->filter_size_real/*kernel_size*/))
19641964
{
1965-
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/);
1965+
resize_prepare_coeffs_AVX512_H(program, env, 64/*iSamplesInTheGroup*/, 1/*iGroupsCount*/, 0/*fixed_kernel_size: variable-loop kernel*/);
19661966
if (bits_per_pixel < 16) {
19671967
if (has_AVX512_fast)
19681968
return resize_h_planar_uint16_avx512_permutex_vstripe_mp_4s16_ks48_pretransposed_coeffs_vnni<true>;

0 commit comments

Comments
 (0)