Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Alphablending mit MMX / SSE Befehle (https://www.delphipraxis.net/13204-alphablending-mit-mmx-sse-befehle.html)

schty 13. Dez 2003 12:01


Alphablending mit MMX / SSE Befehle
 
Hier gibt's meine 'weiterentwickelte' alpha-blending procedure (sehe unten). Das Original "CombineMem" findet man im Freeware Komponenten-Source "Graphics32" von Alex Denissov.

// Result = Alpha * (Foreground - Background) + Background

Die Ergebnisse fuer R, G und B Werte werden parallel berechnet mit inline MMX / SSE Assembler-Befehle.

Weiss jemandem weitere Optimierungen oder sogar noch schnellere Algorithmen fuer Alphablending?

MfG,
Arjan


Delphi-Quellcode:
procedure AlphaBlend(PenColor:TColor32; DIB:PColor32; Alpha:DWORD);
asm
    MOVD           MM1, EAX      
// MM1 = 00 00 00 00 ** Fr Fg Fb
    MOVD           MM2,[EDX]    
// MM2 = 00 00 00 00 ** Br Bg Bb
    PUNPCKLBW      MM1, MM0       
// MM1 = 00 ** 00 Fr 00 Fg 00 Fb
    MOVD           MM3, ECX      
// MM3 = 00 00 00 00 00 00 00 AA
    PUNPCKLBW      MM2, MM0       
// MM2 = 00 ** 00 Br 00 Bg 00 Bb
    PSHUFW         MM3, MM3, 0   
// MM3 = 00 AA 00 AA 00 AA 00 AA
    PSUBW          MM1, MM2
    PSLLW          MM2, 8
    PMULLW         MM1, MM3
    PADDW          MM1, MM2
    PSRLW          MM1, 8
    PACKUSWB       MM1, MM0
    MOVD          [EDX],MM1
end;
[edit=Admin]Code in Tags [delphi ]..[ /delphi] gesetzt. Künftig bitte selber machen. Mfg, Daniel[/edit]

OregonGhost 13. Dez 2003 13:57

Re: Alphablending mit MMX / SSE Befehle
 
Mein letzter Alphablending-Algorithmus sieht so aus:
Code:
__asm {
   pxor MM7, MM7;    // Zero MM7
   movd MM0, dtarget;      // Get Target
   movd MM1, dsource;      // Get Source
   movd MM2, dalpha;      // Alpha packed
   movd MM3, d255;   // 255 für jedes Byte
   punpcklbw MM0, MM7;// Target unpacked
   punpcklbw MM1, MM7;// Source unpacked
   punpcklbw MM2, MM7;// Alpha unpacked
   punpcklbw MM3, MM7;// 255 unpacked
   
   pmullw MM1, MM2; // Multiply source with alpha
   pmullw MM3, MM0; // Multiply target with 255
   pmullw MM0, MM2; // Multiply target with alpha
   psubusw MM3, MM0;// subtract a*tr from ...
   paddusw MM1, MM3; // Add target*255 to source*alpha
   psrlw MM1,8; // Right shift target by 8 (divide by 256)

   packuswb MM1, MM7; // pack target to MM7
   movd dtarget, MM1;
   EMMS;
}
Ich musste allerdings feststellen, dass ein Ausmultiplizieren der Funktion keinen Geschwindigkeitsunterschied bringt (bzw. nur im Mikrosekundenbereich für das gesamte Bild).

Da meine Routine mehr Anweisungen verwendet, müsste sie langsamer sein als deine - Wie schnell ist denn deine?
Meine braucht für ein 256x256-Bild (mit Perpixelalpha und zusätzlichem konstantem Alpha) etwa 4650µs auf meinem Athlon XP 2100+.


Um auf deine Frage zu kommen, noch schneller geht's wahrscheinlich nur, wenn du die Arbeit den 3D-Chip machen lässte ;c)


Was ich noch anmerken möchte: Auf die Formel
Zitat:

Result = Alpha * (Foreground - Background) + Background
bin ich auch gekommen, und sie ist korrekt für Werte zwischen 0 und 1. Wenn du aber Werte von 0 bis 255 hast, sieht das ganze so aus:
Code:
Result = Alpha * Source + (255 - Alpha) * Target
Result = Alpha * Source + 255 * Target - Alpha * Target
Result = Alpha * (Source - Target) + 255 * Target
Und das finde ich in deinem Code nicht wieder. Wenn ich mich recht entsinne, habe ich es mal mit "deiner" Formel ausprobiert und es hat zu unbefriedigenden Ergebnissen geführt.

schty 13. Dez 2003 16:55

Re: Alphablending mit MMX / SSE Befehle
 
Liste der Anhänge anzeigen (Anzahl: 1)
Was die absolute Geschwindigkeit angeht, zum Vergleich mit deiner Code, kann ich noch keine genaue Aussagen machen, dafuer fehlt mir noch ein Testprogramm.... ich bin etwas unsicher ueber die Instruction Pairing und SSE Optimierungen usw., ich bin keine Experte. z.B. laut Intel sollte man mit PSHUFW (SSE) gegenueber nur MMX-Befehle 2 Befehle einsparen koennen, ich habe aber nur einer eingespart:

Delphi-Quellcode:
 
// mit PSHUFW (SSE):
 MOVD     MM3, ECX      
// MM3 = 00 00 00 00 00 00 00 AA  32 BITS -> 64 BITS Alpha
 PSHUFW   MM3, MM3, 0   
// MM3 = 00 AA 00 AA 00 AA 00 AA

// in MMX sieht das so aus:
 MOVD     MM3, ECX  
 PUNPCKLWD MM3, MM3   
 PUNPCKLQD MM3, MM3   

// Was ich eigentlich will ist alles in 1 Befehl, aber das habe ich mit Delphi nicht geschaft:
  PSHUFW  MM3, [ECX], 0
// Das geht so nicht, weil mann muss 64 bits (aligned?) uebertragen....
Nun, relativ gesehen bin ich doch um die 50% schneller (auch abhaengig vom Linienlaenge) als der "Graphics32-MMX-Referenz", das hat teilweise aber auch mit der Loop-optimierung zu tun.

Ah, du hast recht. Der Faktor 256 ist nicht im Formel aufgelistet, sondern wird im Code mit den PSSLW (x256) und PSRLW (/256) Befehle geloest. Ich muss sagen dass die Ergebnisse kwalitativ doch ziemlich gut sein koennen, abhaengig vom Anruf.

Im Attachment n' schlechter GIF (in wirklichkeit arbeitet das Programm Bildfehlerfrei) von einem 4xAA Beispiel, also fuer jeden "Punkt" wird "Alphablend" 4x angerufen, vergleichbar mit "DrawLineFS in Graphics32").

Arjan

OLLI_T 13. Dez 2003 17:29

Re: Alphablending mit MMX / SSE Befehle
 
Hallo Arjan!

Leider kennt mein Delphi 5 keine MMX Assembler Anweisungen. Mit welcher Delphi Version arbeitest Du? Dein Funktion gefällt mir nämlich sehr gut! Ich denke mehr lässt sich daran nicht optimieren. Allenfalls ab einer beliebiegen Schwelle 1 addieren, um den kleinen Fehler, der durch SHR 8 gemacht wird, zu kompensieren.

@OregonGhost:

Deine "Formelsammlung" ist leider nicht richtig. Du hast generell vergessen, durch 255 zu dividieren (optimiert SHR 8 )

Delphi-Quellcode:
Result := Alpha * (FG - BG) SHR 8 + BG; // für Alpha = 0..255

Gruss

OLLI

schty 14. Dez 2003 02:29

Re: Alphablending mit MMX / SSE Befehle
 
Hallo OLLI!

Schoenen Dank fuer deine Interesse und Bemerkungen. Tatsaechlich sollte man fuer sehr exakte Ergebnisse noch einer dazu zaehlen....

Ab Delphi 6 kann man MMX, SSE (integer&float) und ich glaube auch SSE2 direkt im inline-Assembler nutzen! Aber pas auf: die Kombination van MMX und SSE Integer Befehle wird nur ab Pentium III / Athlon CPU unterstuetzt. SSE Float und SSE2 sind nicht AMD-Compatible (dafuer gibt's 3D Now), aber vielleicht doch wieder mit den neuen Athlon XP's (3d Now Pro)?.

Arjan

OregonGhost 14. Dez 2003 19:29

Re: Alphablending mit MMX / SSE Befehle
 
@OLLI_T: halbrichtig.
Das Ergebnis meiner Formel ist in der Tat ein Wert zwischen 0 und 65535, der noch durch 256 geteilt werden muss. Wenn du in meinen Code schaust, wirst du feststellen, dass ich das durchaus getan habe, aber das ist nicht der Punkt. Die Multiplikation muss an dieser Stelle mit 255 und nicht mit 256 erfolgen, zumindest wenn man die Formel so verwendet wie ich sie verwendet habe, um korrekte Ergebnisse zu erzielen (auch wenn der Unterschied marginal ist).

Ich benutze übrigens dafür Visual C++ 6 SP5 mit Processor Pack, weil meine Delphi-Version(en) leider nicht die erweiterten Instruktionen unterstützen.

schöni 1. Jun 2005 21:30

Re: Alphablending mit MMX / SSE Befehle
 
Hallo!

Bei dieser Problematik frag ich gleich mal hier, wo man zu MMX- und SSE Befehlssatz ein gutes Handbuch findet. Ich kann nämlich mit den MMX und SSE Zeug gar nix anfangen. Ich muß mich da erst mal schlau machen.

Danke für Eure Hilfe

Schöni

BenBE 1. Jun 2005 22:42

Re: Alphablending mit MMX / SSE Befehle
 
Kurz-Referenz gibt's in der Ge-packt-Reihe vom mitp-Verlag. Einfach dort mal gucken.

schöni 1. Jun 2005 23:43

Re: Alphablending mit MMX / SSE Befehle
 
Hallo BenBE!

Danke für den Tipp. Werde danach suchen.

Schöni

snapman 2. Jun 2005 00:05

Re: Alphablending mit MMX / SSE Befehle
 
was ist eigentlich alpha blending?


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:05 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz