• Keine Ergebnisse gefunden

Architektur und Programmierung von Grafik- und Koprozessoren

N/A
N/A
Protected

Academic year: 2022

Aktie "Architektur und Programmierung von Grafik- und Koprozessoren"

Copied!
34
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Architektur und Programmierung von Grafik- und Koprozessoren

Die Grafik Pipeline

Stefan Zellmann

Lehrstuhl f¨ur Informatik, Universit¨at zu K¨oln

SS2019

(2)

Lernziele

1. Host Interface- die Studierenden verstehen das

Zusammenspiel zwischen “Kernel Mode” und “User Mode”

Ger¨atetreibern, die mehreren Betriebssystemprozessen den gleichzeitigen Zugriff auf die Grafikkarte erlauben.

2. Kommandoverarbeitung - die Studierenden verstehen den Kontrollfluss von Zeichenkommandos, die die Applikation an die Grafikkarte verschickt.

3. Architekturen- die Studierenden kennen

Architekturprinzipien, die bei modernen Grafikkarten eine Rolle spielen.

4. Moderne Grafik APIs - die Vorlesungseinheit bereitet die Studierenden auf moderne Grafik APIs wie DirectX 12 oder Vulkan vor. Die Studierenden verstehen, welche Rolle

Nebenl¨aufigkeit und Synchronisation bei der Programmierung moderner Grafikkarten spielen.

(3)

Kurze Einf¨ uhrung in Grafik APIs

(4)

Immediate Mode vs. Retained Mode APIs

Immediate Mode APIs

Application Library Display

Updates Scene

Draw Commands

Abbildung:vgl. Windows Dev Center - Windows Graphics: Retained Mode Versus Immediate Mode.

(5)

Immediate Mode vs. Retained Mode APIs

Retained Mode APIs

Application Library Display

Updates Scene

Draw Commands Update Commands

Abbildung:vgl. Windows Dev Center - Windows Graphics: Retained Mode Versus Immediate Mode.

(6)

Immediate Mode APIs

3D APIs traditionellImmediate Mode - wenn Programm Zeichenbefehl spezifiziert,sieht es so aus, als w¨urde der Befehl unmittelbar ausgef¨uhrt.

Realit¨at: Treiberpuffert Kommandos und schickt Batches von Zeichenbefehlen an GPU. Batches beinhalten potentiell Zeichenbefehle von verschiedenen Threads oder sogar

verschiedenen Applikationen. Komplizierte Heuristiken, um zu entscheiden, wie gepuffert wird.

Das kann teils zu ¨uberraschendem Performanzverhalten f¨uhren!

Moderne APIs (Vulkan, D3D12): nicht Immediate, Applikation steuert, wann welche Speicherbefehlezu submittieren sind, sowie Abh¨angigkeiten zwischen Kommandos + Synchronisation ⇒viel weniger komplexe Treiber.

(7)

Immediate Mode APIs

I Auf den folgenden Folien: OpenGL-¨ahnlicher Pseudo Code dient zur Illustration, Programmausschnitte unvollst¨andig.

I Kein OpenGL Tutorial, nur Konzepte.

I Konzepte gelten auch f¨ur alte Direct3D Versionen.

(8)

Immediate Mode APIs

g l B e g i n ( G L _ T R I A N G L E S );

// Red t r i a n g l e g l C o l o r 3 u b (255 ,0 ,0);

g l V e r t e x 3 f (0 ,0 ,0);

g l V e r t e x 3 f (1 ,0 ,0);

g l V e r t e x 3 f (1 ,1 ,0);

// G r e e n t r i a n g l e g l C o l o r 3 u b (0 ,255 ,0);

g l V e r t e x 3 f (0 ,0 ,0);

g l V e r t e x 3 f (1 ,0 ,0);

g l V e r t e x 3 f (1 ,1 ,0);

g l E n d ();

(9)

Immediate Mode APIs

I Immediate Mode APIs bilden den Zeichenalgorithmus ab, nicht die zugrundeliegende Hardware.

I Hardware:hochparallel, f¨ur hohen Durchsatzoptimiert.

I Besonderes Merkmal von GPUs: hohe Bandbreite, daf¨ur vergleichsweise hohe Latenz: z. B. bei Host-Interconnect (PCIe), aber auch bei GDDR Speicher.

I Immediate Mode Operationen wie die von oben h¨atten eine unglaublich hohe Latenz ⇒ Pufferung n¨otig.

I Frage: wer puffert Daten?

I Treiber: Produktivit¨at.

I Anwendungsentwickler: applikationsspezifisches Wissen oheres Potential f¨ur bessere Performanz.

(10)

Immediate Mode APIs

Graphic APIs, egal welche, unterst¨utzen heute zumindest Pufferung von Daten:

// O n l y o n c e :

g l B i n d B u f f e r ( G L _ A R R A Y _ B U F F E R , vbo );

g l B u f f e r D a t a ( G L _ A R R A Y _ B U F F E R , n u m _ v e r t s , verts , G L _ S T A T I C _ D R A W );

// Later , w h e n r e n d e r i n g :

g l B i n d B u f f e r ( G L _ A R R A Y _ B U F F E R , vbo );

g l D r a w B u f f e r ( vbo );

Anwender hat aber generell wenig Kontrolle, wann Daten kopiert werden, welche Speicherbereiche genutzt werden etc.

(11)

GPU Zustandsmaschine

Traditionelle GPU APIs implementieren den

Rasterisierungsalgorithmus mittels Zustandsmaschinen:

g l A c t i v e T e x t u r e ( G L _ T E X T U R E 0 );

g l B i n d T e x t u r e ( G L _ T E X T U R E _ 2 D , tex );

g l T e x I m a g e 2 D ( . . . ) ; g l E n a b l e ( G L _ L I G H T 0 );

g l L i g h t f v ( G L _ L I G H T 0 , G L _ P O S I T I O N , pos );

g l M a t r i x M o d e ( G L _ M O D E L V I E W );

g l L o a d M a t r i x ( mv );

gefolgt von Zeichenbefehlen:

g l B i n d B u f f e r ( G L _ A R R A Y _ B U F F E R , vbo );

g l D r a w B u f f e r ( fb );

g l X S w a p B u f f e r s (); // p l a t f o r m s p e c i f i c !

(12)

GPU Zustandsmaschine

glActiveTexture(GL TEXTURE0)- aktive Textureinheit ist jetzt

’0’.

glEnable(GL LIGHT0)- aktive Lichtquelle ist jetzt ’0’.

glMatrixMode(GL MODELVIEW)- als n¨achstes wird MV Matrix ver¨andert.

glBindBuffer(GL ARRAY BUFFER, vbo)- der gerade gebundene Buffer ist Vertex-Buffer mitHandle’vbo’.

(13)

GPU Zustandsmaschine

Programmablauf exemplarisch f¨ur (altes) OpenGL:

1. Erzeuge Fenster, erzeuge OpenGL Kontext(e). Binde Kontexte an Threads.

2. Initialisiere Framebuffer, Zeichnen in Backbuffer etc.

3. Starte “Render-Loop”:

I Pushe intrinsische Kameraparameter und globale Kameratransformation auf Matrix Stack.

I Traversiere Szenengraph (Baumstruktur, die Geometrie hierarchisch mit Transformationen / Materialeigenschaften etc.

verkn¨upft).

I Pushe individuelle Transformationen auf Matrix Stack.

I Initialisiere Materialien / Texturen etc. per Geometrie.

I Submitte Geometrie (Vertex Buffer).

I Setze Beleuchtungsparameter, Zeichen-State (Depth Buffering, Alpha Blending, Backface Culling, ...)

I Pr¨asentiere Bild, indem Front- und Backbuffer vertauscht werden.

(14)

GPU Zustandsmaschine

Zustand wurde / wird inKontexten gespeichert. Kontext speichert gesamten Zustand zu Zeitpunktt.

Shading State 1 Diffuse:

Specular:

Rough: 1.0 Light-Pos: (0,0,-1) Light-Col.:

Geom. Buffers

EnableBlending Shading State 2 Diffuse:

Specular:

Rough: 0.0 Light-Pos: (1,0,1) Light-Col.:

DisableDepth SetClipPlane

Geom. Buffers

Present

(15)

GPU Zustandsmaschine

Kontexte von GPU und API verwaltet, Benutzer kann Zustand durch API Calls ver¨andern.

// GPU K o n t e x t ( i m p l i z i t ) {

b l e n d i n g : no d e p t h t e s t : yes d i f f u s e : (255 ,0 ,0) s p e c u l a r : ( 2 5 5 , 2 5 5 , 2 5 5 )

r o u g h : 1.0

l i g h t 1 : d i s a b l e d ; l i g h t p o s 1 : (0 ,0 ,1) l i g n t c o l 1 : ( 2 5 5 , 2 5 5 , 2 5 5 ) c l i p p l a n e 1 : no

}

// P r o g r a m m :

g l E n a b l e ( G L _ L I G H T 1 );

g l L i g h t f v ( G L _ L I G H T 1 , G L _ P O S I T I O N , { 0 ,0 , -1 });

(16)

GPU Zustandsmaschine

I GPU Kontexte sind sehr schwergewichtig, speichern gesamten Rendering State.

I Fr¨uhe API Versionen: nicht CPU Multi-Threading “aware”.

Ein Kontext pro Thread, kein Sharing, kein Austausch und keine Synchronisation.

I Umschalten zwischen Threads: binde ganz anderen Kontext, unklar, welcher State sich unterscheidet.

(17)

Ressourcen Handles

I Ressourcen werden ¨uberHandlesverwaltet. Einfache Datentypen (GLint,GLenum), teils Objekte mit opaker Struktur (z. B. GLXContext).

I Kein direkter Zugriff auf GPU Speicher, keine Pointer etc.

I Ressourcen sind an Kontexte gebunden, Teilen von Ressourcen durch mehrere Threads oder Prozesse schwergewichtig.

(18)

Zeichenbefehle

Der eigentliche Algorithmus steckte in den Zeichenbefehlen und war in den Anfangszeiten von GPUs außer ¨uber denState nicht beeinflussbar.

g l B i n d B u f f e r ( G L _ A R R A Y _ B U F F E R , vbo );

g l D r a w B u f f e r ( fb );

g l X S w a p B u f f e r s ();

(19)

Zeichenbefehle

g l F i n i s h (); // or

g l F l u s h (); // or

g l X S w a p B u f f e r s (); // or ..

Verschiedene Kommandos (Zeichnen, State Change, etc.) laufen beim API auf. Es ist dem API / Treiber ¨uberlassen, wann die Befehle ausgef¨uhrt werden (direkt oder sp¨ater). Kommandos wie SwapBuffer(),Flush(),Finish()f¨uhren dazu, dass die Pipeline stalled und die aufgelaufenen Befehle (in endlicher Zeit, nicht notwendigerweise sofort) abgearbeitet werden m¨ussen.

(20)

Shader Programme

Sp¨atere GPUs: Shader Programme, die den Ablauf des

Rasterisierungsalgorithmusauf der GPU selbstbeeinflussten (vgl.

AlgorithmusRasterisierung):

a c t i v a t e _ v e r t e x _ b u f f e r ( h a n d l e ) d r a w _ t r i a n g l e s () {

for ( e a c h v e r t e x )

v e r t e x _ s h a d e r (); /* - - - - */

t r i a n g l e _ s e t u p ();

for ( e a c h t r i a n g l e ) s c a n _ c o n v e r t ();

for ( e a c h f r a g m e n t ) for ( e a c h l i g h t )

f r a g m e n t _ s h a d e r (); /* - - - - */

d e p t h _ t e s t ();

a l p h a _ b l e n d i n g ();

}

p r e s e n t ();

(21)

Shader Programme

I C-artige Programme, die auf GPU ablaufen. Werden an dedizierten Einsprungpunkten in die Grafik Pipeline eingeh¨angt.

I Mit Vertex Shadernkann die Vertex Transformationsphase (Model-View und Perspektivische Transformation, Clipping, Transformation in normalisierte Ger¨atekoordinaten)

modifiziertwerden.

I Geometrie Shader schließen sich an Vertex Phase an.

Programm erh¨alt ein Vertex als Input und emittiert weitere Vertices.

I Mit Fragment Shadern kann die Fragment Phase modifiziert werden, im Rahmen derer die Fragment Farbe bestimmt wird.

(22)

Shader Programme

Nomenklatur

Bezeichnungen weichen je nach API und Konvention etwas ab.

Manchmal werden die KonzepteShaderund Programmvermischt.

D3D nennt Fragment ShaderPixel Shader.

Wir verwenden dieOpenGLKonvention: Vertex Shader,Fragment Shaderund ggf. weitere bilden zusammen einShader Programm.

(23)

Shader Programme

Shading Languages

I Es existieren eine Reihe:

I GLSL (“GLSlang”) - Teil des OpenGL Standards.

I HLSL - Microsoft DirectX Shading Language.

I Nvidia Cg - identisch mit HLSL, jedoch kompatibel mit OpenGL.

I API-neutrale Sprachen, z. B. OpenShadingLanguage; Sprachen ur spezielle APIs wie z. B. Pixars RenderMan.

I GL ARB fragment program (OpenGL 1.3) - erste OpenGL Spezifikation f¨ur programmierbare Fragment Stage,

Assembler-artig, kein Branching etc.

(24)

Shader Programme

I Shader Programme werden hochparallel ausgef¨uhrt.

I Implizites paralleles Programmiermodell.

I Keinerlei Zugriff auf andere Shader Instanzen.

I Vulkan / Modernes OpenGL: minimaler Vertex Shader verpflichtend (außer Compute). Ohne minimalen Fragment Shader kein Bild (manchmal Ergebnis kein Bild).

(25)

Vertex Shader

Einfacher Vertex Shader (lose basierend aufOpenGL Shading Language(GLSL)) . Applikation verwaltet Viewing

Transformationsmatrix und perspektivische Transformationsmatrix und ¨ubergibt sie an alle Vertex Shader Instanzen.

a t t r i b u t e v e c 3 p o s i t i o n ; in m a t 4 v i e w _ m a t ;

in m a t 4 p r o j _ m a t ; v o i d m a i n () {

g l _ P o s i t i o n = v i e w _ m a t * p r o j _ m a t * v e c 4 ( p o s i t i o n , 1 . 0 ) ; }

(26)

Vertex Shader

Benutzerspezifische globale Attribute:

a t t r i b u t e v e c 3 p o s i t i o n ; in m a t 4 v i e w _ m a t ; // g l o b a l in m a t 4 p r o j _ m a t ; // g l o b a l in f l o a t t i m e ; // g l o b a l v o i d m a i n () {

p o s i t i o n . x += cos ( t i m e );

p o s i t i o n . y += sin ( t i m e );

g l _ P o s i t i o n = v i e w _ m a t * p r o j _ m a t * v e c 4 ( p o s i t i o n , 1 . 0 ) ; }

(27)

Vertex Shader

Benutzerdefinierteper Vertex Attribute:

a t t r i b u t e v e c 3 p o s i t i o n ; // per v e r t e x in m a t 4 v i e w _ m a t ;

in m a t 4 p r o j _ m a t ;

a t t r i b u t e v e c 3 n o r m a l ; // per v e r t e x v o i d m a i n () {

...

g l _ N o r m a l = t r a n s f o r m ( normal , v i e w _ m a t , p r o j _ m a t );

...

}

(28)

Vertex Shader

Vertex Output geht sp¨ater durch Raster Engines⇒ benutzerdefinierte Attribute werden w¨ahrend Scan Konvertierung interpoliert!

varying: interpolierte Attribute stehen sp¨ater in Fragment Phase zur Verf¨ugung.

a t t r i b u t e v e c 3 p o s i t i o n ; in m a t 4 v i e w _ m a t ;

in m a t 4 p r o j _ m a t ; v a r y i n g v e c 3 n o r m a l ; v a r y i n g v e c 2 uv ; v o i d m a i n () {

...

}

(29)

Fragment Shader

Einfacher Fragment Shader mit diffusem Beleuchtungsmodell.

varyingAttribute aus Vertex Shader. Fragment-spezifischer Input (z. B.light dir).

// S i m p l e d i f f u s e s h a d e r in s a m p l e r 2 D tex ;

in v e c 3 l i g h t _ d i r ; v a r y i n g v e c 3 n o r m a l ; v a r y i n g v e c 2 uv ; out v e c 4 f r a g _ c o l o r ; v o i d m a i n () {

// 2 - D t e x t u r e a c c e s s

v e c 3 d i f f = t e x 2 D ( tex , uv );

// S i m p l e ( single - s i d e d ) L a m b e r t s h a d i n g d i f f *= max (0.0 , dot ( l i g h t _ d i r , n o r m a l ));

// W r i t e r e s u l t

f r a g _ c o l o r = ve c 4 ( diff , 1 . 0 ) ; }

(30)

Shader Programme

I Neue APIs: mehr programmierbare Pipeline Stages.

I Geometrie Shader: folgen auf Vertex Stage. Programmatisch Erzeugung weiterer Polygone.

I Tesselation Shader: niedrig aufgel¨oste Geometrie kann durch Tesselierungverfeinert werden, z. B. mit Bezier Patches (Subdivision SurfaceAlgorithmen).

I Weitere programmierbare Stages z. B. im Zusammenhang mit Multisampling.

I Wir gehen vereinfachend nur von Vertex und Fragment Shadern aus.

(31)

Shader Programme

Shader werdenzur Programmlaufzeitkompiliert und gelinkt.

G L u i n t vs = g l C r e a t e S h a d e r ( G L _ V E R T E X _ S H A D E R );

G L u i n t fs = g l C r e a t e S h a d e r ( G L _ F R A G M E N T _ S H A D E R );

g l S h a d e r S o u r c e ( vs , s t r l e n ( v e r t _ s h a d e r _ s t r ) , v e r t _ s h a d e r _ s t r , 0);

g l C o m p i l e S h a d e r ( vs );

g l S h a d e r S o u r c e ( fs , s t r l e n ( f r a g _ s h a d e r _ s t r ) , f r a g _ s h a d e r _ s t r , 0);

g l C o m p i l e S h a d e r ( fs );

G L u i n t p r o g = g l C r e a t e P r o g r a m ();

g l A t t a c h S h a d e r ( prog , vs );

g l A t t a c h S h a d e r ( prog , fs );

g l L i n k P r o g r a m ( p r o g );

g l U s e P r o g r a m ( p r o g );

(32)

Shader Programme

I Laufzeitkompilation und Linking.

I Laufzeit Overhead (wegen Caching meistens nur erster Programmlauf).

I OpenGL Runtime muss Compiler integrieren.

I Traditionell sehr fehleranf¨allig - IHVs (Independent Hardware Vendors) legen Sprachstandard unterschiedlich aus.

I Treiber muss Compiler-generierten Intermedi¨arcode in Maschinencode ¨ubersetzen.

I Shader Programme stehen im Klartext im Binary, k¨onnen einfach mit Hex-Editor ausgelesen werden.

I Vulkan API: Shader werden zur Compile Zeit in optimierten Intermedi¨arcode (SPIR-V) ¨ubersetzt.

(33)

Hierarchische Pipeline

Alte Versionen von Direct3D und OpenGL hatten hierarchische Pipelines:

I Stack f¨ur Transformationsmatrizen.

I Stack f¨ur generellen State.

I Wende Transformationen / Materialien etc. auf Teile der Geometrie an, indem State / Transformationen auf Stack gepush()ed werden. Wenn entsprechende Teile der Geometrie gezeichnet,pop() vom Stack.

(34)

Hierarchische Pipeline

Neue APIs gehen davon aus, dass die Applikation den hierarchischen State samt Transformationen verwaltet (z. B.

Szenengraph Bibliothek), und dass Transformationen als uniforme Variablen anShader Instanzen¨ubergeben werden.

Kompletter Matrix Stack in OpenGL deprecated. Viele

Betriebssystemhersteller (insb. Microsoft, Apple) unterst¨utzen nur sehr alte OpenGL Versionen, daher noch viel legacy Code, der auf alten OpenGL Konzepten aufbaut.

Referenzen

ÄHNLICHE DOKUMENTE

“Sampling” bestimmt. Dies ist eine in den Prozessor eingebaute Funktionalit¨ at, die, falls aktiviert, die Instruktionspipeline zu definierten Zeitpunkten anh¨ alt und

C++ spezifiziert keine Garbage Collection (der Standard schließt sie nicht explizit aus, aber es gibt keine Implementierungen, die mir bekannt sind). Daher m¨ ussen alle Ressourcen,

I Desktop GPUs implementieren traditionell Immediate-Mode Rendering: Verarbeitung orientiert sich an Reihenfolge, in der Dreiecke submittiert wurden (nicht zu verwechseln

I Vor und nach Skalarprodukt m¨ ussen Threads synchronisiert werden, damit nicht schon andere Threads aus Warp anderen Block in Shared Memory laden... I Seit Nvidia Kepler

Die Template Klasse sync queue in der beigef¨ ugten Datei queue.cpp wird von mehreren Threads gleichzeitig als Schlange zum Austauschen von Nachrichten genutzt. Intern verwaltet

(2) Die Bin¨ arrepr¨ asentation der sich ergebenden nat¨ urlichen Zahl k setzt sich immer abwechselnd aus den Bin¨ arziffern der Zahlpaare (i, j) zusammen. Tragen Sie das Ergebnis

Trifft man die vereinfachende Annahme, dass geometrische, aus Dreiecken zusammengesetzte Objekte geschlossen sind und immer nur von außen betrachtet werden, kann man vor dem

Der Ray Tracer geht im Weiteren davon aus, dass totale interne Reflektion aufgetreten ist, wenn refract() einen 0-Vektor zurückgegeben hat und ruft in dem Fall die Funktion