Skip to content

Fix AVX2 YV24 source alpha packing#491

Open
msg7086 wants to merge 1 commit into
AviSynth:masterfrom
msg7086-forks:fix/avx2-yv24-source-alpha
Open

Fix AVX2 YV24 source alpha packing#491
msg7086 wants to merge 1 commit into
AviSynth:masterfrom
msg7086-forks:fix/avx2-yv24-source-alpha

Conversation

@msg7086

@msg7086 msg7086 commented Jul 12, 2026

Copy link
Copy Markdown

Disclosure: This report was prepared by OpenAI Codex, a GPT-based coding agent.
The GitHub user posting this issue is forwarding the report and is not claiming authorship of the analysis.

Summary

Fix corrupted source-alpha output in the AVX2 YV24 -> BGR32 conversion path (convert_yv24_to_rgb_avx2<4, true>).

How the issue was found

The issue was found by an external unit test using fixed Y, U, V, and alpha anchors. The test compares the output against an independent fixed-point YUV-to-RGB reference.

SSE2 and SSSE3 preserved source alpha correctly. The AVX2 path produced zero or incorrectly ordered alpha bytes. For example, one output alpha value was expected to be 64 but was written as 0.

Root cause

The AVX2 RGB result vectors are lane-local after the packing operations. Their effective byte order for alpha interleaving is:

low 128-bit lane:  R0 R1 R2 R3 R8 R9 R10 R11
high 128-bit lane: R4 R5 R6 R7 R12 R13 R14 R15

The old code expanded each 8-bit alpha value to a 16-bit value before calling _mm256_unpacklo_epi8:

src_a:
  D0=[A0 A1 A2 A3] D1=[A4 A5 A6 A7]
  D2=[A8 A9 A10 A11] D3=[A12 A13 A14 A15]

a_lo = unpacklo_epi8(src_a, 0):
  [A0 00 A1 00 A2 00 A3 00 A4 00 A5 00 A6 00 A7 00]

a_hi = unpackhi_epi8(src_a, 0):
  [A8 00 A9 00 A10 00 A11 00 A12 00 A13 00 A14 00 A15 00]

_mm256_unpacklo_epi8 expects packed 8-bit alpha bytes. It therefore consumed the inserted 00 bytes as alpha values, and the subsequent lane permutation also did not match the packed RGB lane order.

The fix keeps alpha packed as bytes and arranges its dwords to match the RGB vectors:

alpha_lo = shuffle(D0, D1, D2, D3) -> [D0 D2 D1 D3]
  consumed bytes: [A0 A1 A2 A3 A8 A9 A10 A11]

alpha_hi = shuffle(D0, D1, D2, D3) -> [D1 D3 D3 D3]
  consumed bytes: [A4 A5 A6 A7 A12 A13 A14 A15]

Only the low eight bytes of each 128-bit alpha lane are consumed by _mm256_unpacklo_epi8, so the duplicated upper dwords in alpha_hi are not observed.

Testing

The regression was discovered and confirmed in the external AviSynthPlus unit-test framework before transferring this minimal fix. No performance test was performed. Only correctness of the fix was tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant