Собственно название топика говорит само за себя.
Код: Выделить всё
;=======================================================================
; Функция avx_composite_4pixels: ((F * A) + (B * (256 - A))) >> 8
; rsi = адрес источника
; rdi = адрес приёмника
;=======================================================================
avx_composite_4pixels:
;-----------------------------------------------------------------------
; загружаем и распаковываем foreground в ymm0 и background в ymm1
;-----------------------------------------------------------------------
vpmovzxbw ymm0, [rsi]
vpmovzxbw ymm1, [rdi]
;-----------------------------------------------------------------------
; отщелкиваем альфу в ymm2 из foreground
;-----------------------------------------------------------------------
vpshufhw ymm2, ymm0, 11111111b
vpshuflw ymm2, ymm2, 11111111b
vpsrlw ymm3, ymm2, 7
vpaddw ymm2, ymm2, ymm3
;-----------------------------------------------------------------------
vpmullw ymm0, ymm0, ymm2 ; (F * A)
;-----------------------------------------------------------------------
; отщелкиваем (256 - alpha) в ymm4
;-----------------------------------------------------------------------
vpcmpeqd ymm4, ymm4, ymm4
vpsrlw ymm4, ymm4, 15
vpsllw ymm4, ymm4, 8
vpsubq ymm4, ymm4, ymm2
;-----------------------------------------------------------------------
vpmullw ymm1, ymm1, ymm4 ; (B * (256 - A)
vpaddq ymm0, ymm0, ymm1 ; ((F * A) + (B * (256 - A)))
vpsrlw ymm0, ymm0, 8 ; ((F * A) + (B * (256 - A))) >> 8
;-----------------------------------------------------------------------
mov rax, 0x00FF000000000000 ; забиваем альфа канал 0xFF
vmovq xmm2, rax
vbroadcastsd ymm2, xmm2
vpor ymm0, ymm0, ymm2
vpxor ymm1, ymm1, ymm1
vpackuswb ymm0, ymm0, ymm1
ret
;-----------------------------------------------------------------------
Все считается правильно, однако результат получается такой (содержимое регистра ymm0):
FF0D5289 FFFFCCAA
00000000 00000000
FF0C4A7C FFE1B69B
00000000 00000000
А мне надо такой (что бы младшая часть регистра ymm0 = xmm0, содержала 4 пикселя, на старшую часть наплевать):
FF0D5289 FFFFCCAA
FF0C4A7C FFE1B69B
00000000 00000000
00000000 00000000
Для того, что бы можно было сделать так:
Код: Выделить всё
vmovdqu [rdi], xmm0 ; сливаем пиксели в приемник
Я в AVX/SSE/MMX не спец, если кто шибко понимает в этом, буду рад доброму совету, может код как то можно улучшить = ускорить.
Решаемая задача: софтварный рендеринг с прозрачностью, нужно очень много и часто делать альфа блэндинг.
Да да, я знаю, CPU не предназначен для работы с графикой, для этих целей уже давно придуман GPU, однако что то мне подсказывает, что GPU юзает ту же технологию, так что это своего рода пробный шар, ну что бы понять как это работает.
Про Mesa OpenGL я тоже знаю, однако она, OpenGL, мне не подходит, т.к. практически намертво привязана в Xorg + гигабайты зависимостей...