xilebo noone | Alors,
imagine tu veux appliquer un coefficient sur un pixel, voici comment on pourrait procéder :
syntaxe assembleur MSVC :
Code :
- movdqa xmm6, _coeff // tu charges au préalable ton coefficient sur 128 bits dans un registre. Par exemple 8 valeurs sur 16 bits contenant ton coeff 0x00C000C000C000C000C000C000C000C0
- boucle :
- movdqa xmm0, [edi] // tu charges dans ton registre SSE 4 pixels en même temps. On suppose que tu as chargé l'adresse de ton buffer dans edi.
- pxor xmm4, xmm4 // mise à 0 du registre 4
- movdqa xmm1,xmm0 // sauvegarde xmm0
- punpcklbw xmm0, xmm4 // tu unpackes xmm0 combiné avec xmm4 Ceci pour les pixels 0 et 1 .Cela permet de mettre chaque composante sur 16 bits pour faire la multiplication. Voir : http://webster.cs.ucr.edu/AoA/Wind [...] Seta2.html
- pmullw xmm0, xmm6 // tu multiplies chaque composante par le coeff ( pixel 0, 1 )
- punpckhbw xmm1, xmm4 // unpack pixel 2 et 3 dans xmm1
- pmullw xmm1, xmm6 // tu multiplies chaque composante par le coeff ( pixel 2, 3 )
- psrlw xmm0, 8 // division par 256 ( pixel 0,1 )
- psrlw xmm1, 8 // division par 256 ( pixel 2,3 )
- packuswb xmm0, xmm1 // tu repackes
- movdqa [edi], xmm0 // tu sauvegardes
- add edi, 16 // tu incrémentes de 16 octets
- dec ecx // compteur de boucle
- jnz boucle // tu boucles
|
syntaxe assembleur GCC
Code :
- "movdqa %3, %%xmm6 \n\t"
- "movdqa (%%edi), %%xmm0 \n\t"
- "pxor %%xmm4, %%xmm4 \n\t"
- "movdqa %%xmm0, %%xmm1 \n\t"
- "punpcklbw %%xmm4, %%xmm0 \n\t"
- "pmullw %%xmm6, %%xmm0 \n\t"
- "punpckhbw %%xmm4, %%xmm1 \n\t"
- "pmullw %%xmm6, %%xmm1 \n\t"
- "psrlw $8, %%xmm0 \n\t"
- "psrlw $8, %%xmm1 \n\t"
- "packuswb %%xmm1, %%xmm0 \n\t"
- "movdqa %%xmm0, (%%edi) \n\t"
- "addl $16, %%edi \n\t"
- //
- // Loop again or break.
- //
- "decl %%ecx \n\t"
- "jnz d \n\t"
|
On peut même travailler sur 8 pixels car il y a assez de registres, et il y a 2 pipelines qui peuvent travailler en parallèle ( à voir si ca marche vraiment ).
Tu peux t'inspirer de ça pour écrire ton code ( il te faudra utiliser également paddsw pour faire une addition ).
Attention, tout doit être aligné sur 16 octets, ton buffer, mais également la variable 128 bits qui contiendra ton coefficient mat ( sur 16 bits donc 8 fois ) et aussi tes 3 variables tr tg tb recevant le résultat ( sinon on peut avoir des crashs ).
PS : j'ai écrit ça en recopiant du code , je ne sais pas si il est exact , mais le principe est là.
|