Programování GPU („shaders“) © 2004-2005 Josef Pelikán, MFF UK Praha http://cgg.ms.mff.cuni.cz/~pepca/
[email protected]
Obsah architektura programovatelných GPU vertex shaders fragment shaders texture shaders (historie) programování GPU low-level: assembler vyšší programovací jazyky: Cg, HLSL, GLSL
Schéma programovatelné GPU Texture Memory
Geom.
Vertex Processor
Vertices App Memory
Pixel Unpack
Primitive Assembly
Clip Project Viewport Cull
Fragment Processor
Geom. Rasterize Pixels
Fragments
Pixel Transfer
Textures Pixels
Pixel Pack
Pixel Groups
Per-Fragment Operations
Read Control
Frame Buffer Operations
Frame Buffer
Vývoj NVIDIA GeForce 3 (2001) první programovatelná GPU, DirectX 8.0: VS,PS 1.0-1.1 v tomtéž roce: ATI Radeon 8500, Microsoft Xbox, NVIDIA GeForce 4 Titanium velmi omezený rozsah shaderů (fragment shader se spíš podobá krátkému konfiguračnímu scriptu, je dovoleno jen pár assembler instrukcí), texture shaders OpenGL: ARB_vertex_program extension (univerzální), fragment shading – podle výrobců
DirectX 8.1 PS 1.2-1.4 (jen ATI), VS zůstává 1.1, Radeon 9000
Vývoj II NVIDIA GeForce FX (2002) – CineFX architektura ATI Radeon 9500-9700 DirectX 9.0: VS, PS 2.0 rozsah programů se podstatně zvětšil: 256 instrukcí konstantní paměť (uniform variables): 256 vektorů několik dalších formátů dat, FPU typ „half“, apod. OpenGL: ekvivalentní funkce přes různá rozšíření
2004: DirectX 9.0c: VS, PS 3.0 NVIDIA GeForce 6800, 6xxx (NV4x čipy), PCI-E bus ATI stále nemá VS, PS 3.0 kompatibilní kartu (2005/II)
Shader model 3.0 GPU se blíží univerzálním výpočetním jednotkám velké množství instrukcí (tisíce, není omezen) podmíněné skoky, smyčky, podprogramy, rekurze, .. vertex shader má přístup do texturové paměti („vertex texturing“, 4 jednotky) OpenGL: ekvivalentní funkce přes NV_* rozšíření NV4x pokroky v HW: dvakrát více přístupů do textury v jednom cyklu FP16 a FP32 se dají použít všude, HDR grafika (128bpp) MRT (multiple render targets), 16x anizoatrop. filtr, SLI (více GPU), HW geometric instancing, lepší anti-alias, ...
SW shaders Pixar od 1989: RenderMan shaders univerzální popis lokálního světelného modelu aplikace textur, šumu, ... díky SW implementaci mohou být velmi silné inspirace pro návrháře HW a 3D API
film „Toy Story“ (na trhu v r. 1995) první veřejná ukázka schopností systému RenderMan finální generování grafiky („final rendering“): měsíce CPU na RISC stanicích Sun (farma: 117 SPARCstations) cca 1300 různých shaderů !
Příklad RenderMan shaderu (textura) surface turbulence ( float Kd =.8, Ka =.2 ) { float a, scale, sum; float IdotN; point M; /* convert to texture coordinate system */ M = transform( "marble", P ); scale = 1; sum = 0; a = sqrt( area(M) ); while ( a < scale ) { sum += scale * float noise( M/scale ); scale *= 0.5; } Oi = sum; Ci = Cs * Oi * (Ka + Kd * I.N * I.N / (I.I * N.N) ); }
Další příklady shaderů (svět. modely) light phong ( float intensity = 1.0; color color = 1; float size = 2.0; point from = point "shader" (0,0,0); point to = point "shader" (0,0,1); ) { uniform point R = normalize( to - from ); solar( R, PI/2 ) Cl = intensity * color * pow( R.L/length(L), size ); } light reflection ( string texturename = ""; float intensity = 1.0 ) { solar() Cl = intensity * color environment( texturename, -L ); }
Vektorový procesor nahrazuje modul zpracování vrcholů: transformace vrcholů transformace a normalizace normálových vektorů výpočet/transformace texturovacích souřadnic výpočet osvětlení (primární a sekundární barva ve vrcholu)
nemůže ovlivnit: počet vrcholů! (nelze přidat ani ubrat vrchol*) typ / topologii geometrických primitiv (neví o topologii!) −
*
částečné řešení: degenerace primitivu
Prostředí VS 1.1 Aplikace Konstanty („uniforms”) (až 96 vektorů)
Vstupní data vrcholu
Vertex-shader
Výstupní data vrcholu
(až 16 vektorů)
(až 128 instrukcí)
(až 13 vektorů)
Pomocné registry (až 12 vektorů)
Souřadnice, normála, 2 barvy, mlha, velikost bodu (sprite), 8 texturových souřadnic
VS 2.0, VS 3.0 VS 2.0: od NVIDIA GeForce FX, ATI Radeon 9500 jen kvantitativní vylepšení více instrukcí (256), více konstantních registrů (256)
VS 3.0: od NVIDIA GeForce 6xxx přístup do texturové paměti („vertex texturing“) − např. pro „displacement mapping“ − předpočítané složitější funkce (šum, ..) − pro opravdu konstantní a velká data
prakticky neomezený počet instrukcí (≥32k) − zřejmě se ani nevyužije
Fragmentový procesor nahrazuje modul zpracování fragmentů: aritmetické operace s interpolovanými hodnotami čtení dat z textur aplikace textur a jejich kombinace (včetně závislosti) výpočet osvětlení („Phong shading“), mlhy, .. závěrečná syntéza barvy fragmentu možnost modifikace hloubky fragmentu „z“
nemůže ovlivnit: počet fragmentů! (nelze přidat ani ubrat* fragment) polohu fragmentu na obrazovce [x,y]
Prostředí FS 1.x Pomocné registry
Konstanty („uniforms”)
Aplikace
Difusní a lesklé světlo
Texturové souřadnice
Fragment-shader ALU
Textury
RGBA hloubka „z”
Prostředí FS ≥2.0 Aplikace
Pomocné registry
Konstanty („uniforms”)
Libovolné atributy fragmentu
(barvy, tex. souř., normála, jiné vektory,..)
Fragment-shader ALU
Textury
RGBA hloubka „z”
Fragment shader model 2.0 FS 2.0: od NVIDIA GeForce FX, ATI Radeon 9500 první skutečný „shader model“ (podobný RenderMan-u) libovolná data (atributy) mohou být spojena s fragmentem (perspektivně-korektní interpolace) libovolné aritmetické operace s daty (texturovými souř.!) závislost textur (texel. data se dají použít k adresování) více instrukcí (96), více konstantních registrů (256?)
náhrada dřívějšího mechanismu „texture shaders“
Fragment shader model 3.0 FS 3.0: od NVIDIA GeForce 6xxx prakticky neomezená délka (≥32k) podmíněné skoky, smyčky, podprogramy, apod. silnější sada aritmetických operací (i rychlé transcendentní funkce, derivace) MRT („Multiple Render Targets“) – současný zápis do více výstupních fragmentů (do více bufferů) − odložené stínování, urychlení víceprůchodových alg., ..
důraz na výpočetní sílu FS (návrh HW) mnoho nezávislých „pipelines“ (2005/II: 16)
Spolupráce VS a FS VS povinně produkuje pouze 3D souřadnice vrcholu v „clip space“ ⇒ aby bylo možné 3D primitiva rasterizovat ostatní data jsou nepovinná (texturovací souřadnice, primární a sekundární barva, apod.) pokud se nepoužívá FS, musí být k dispozici všechna data pro FFP !
spolupráce VS a FS: grafický HW neví, jaká data si mezi sebou posílají rasterizační jednotka je interpoluje (perspektivně korektně)
Programovací jazyky „low-level“ programování (assembler) používalo se ve starších profilech (mezikód pro Cg, HLSL) jednoduchá sada instrukcí (např. 17 u VS 1.1)
vyšší programovací jazyky nutnost kvůli složité HW architektuře GPU (optimalizace) NVIDIA: Cg („C for graphics“) od 2002 NVIDIA a Microsoft: HLSL („High Level Shading Language“) od 2003 OpenGL ARB (původně 3Dlabs): GLSL („OpenGL Shading Language“) od 2001 syntakticky jsou si dost podobné (zejména Cg a HLSL)
Příklad v Cg (Phongovo stínování) void phongVertex ( float4 position float3 normal
: POSITION, : NORMAL,
out float4 oPosition : POSITION, out float4 color : COLOR, uniform uniform uniform uniform uniform uniform uniform uniform uniform
float4x4 modelViewProj, float3 globalAmbient, float3 lightColor, float3 lightPosition, float3 eyePosition, float3 Ka, float3 Kd, float3 Ks, float shininess )
{ // 3D variant of world space vertex position: float3 P = position.xyz; // 3D variant of world space normal vector: float3 N = normal; // light direction vector (world space, normalized): float3 L = normalize( lightPosition - P );
Příklad v Cg // max( cos(alpha), 0 ): float cosa = max( dot(N,L), 0 ); // view vector (world space, normalized): float3 V = normalize( eyePosition - P ); // Blinn's half vector (world space, normalized): float3 H = normalize( L + V ); // cos(beta)^shininess: float cosb = pow( max( dot(N,H), 0 ), shininess ): if ( cosa <= 0 ) cosb = 0; // total ambient color: float3 ambient = Ka * globalAmbient; // total diffuse color: float3 diffuse = Kd * lightColor * cosa; // total specular color: float3 specular = Ks * lightColor * cosb; // output oPosition = // sum of color.xyz = color.w = }
values: vertex position in clip space mul( modelViewProj, position ); all color components: ambient + diffuse + specular; 1;
Příklad v shader-assembleru !!ARBvp1.0 # ARB_vertex_program generated by NVIDIA Cg compiler PARAM c12 = { 0, 1, 0, 0 }; TEMP R0, R1, R2; ATTRIB v18 = vertex.normal; ATTRIB v16 = vertex.position; PARAM c0[4] = { program.local[0..3] }; PARAM c10 = program.local[10]; PARAM c5 = program.local[5]; PARAM c9 = program.local[9]; PARAM c4 = program.local[4]; PARAM c8 = program.local[8]; PARAM c11 = program.local[11]; PARAM c7 = program.local[7]; PARAM c6 = program.local[6]; DP4 result.position.x, c0[0], v16; DP4 result.position.y, c0[1], v16; DP4 result.position.z, c0[2], v16; DP4 result.position.w, c0[3], v16; ADD R2.xyz, c7.xyzx, -v16.xyzx; DP3 R0.x, R2.xyzx, R2.xyzx; RSQ R1.w, R0.x; ADD R0.yzw, c6.xxyz, -v16.xxyz; DP3 R0.x, R0.yzwy, R0.yzwy; RSQ R0.x, R0.x; MUL R1.xyz, R0.x, R0.yzwy; ...
Shaders v OpenGL nízká úroveň: assemblery OpenGL rozšíření různé profily, odlišné přístupy (ATI, NVIDIA, 3Dlabs)
vyšší jazyk GLSL vyvíjí 3Dlabs, součástí OpenGL 2.0 (malá podpora)
univerzální vyšší jazyk Cg vyvíjen firmou NVIDIA při běhu je zapotřebí „Cg runtime“ (např. „cg.dll“, „cgGL.dll“), dvoustupňový překlad Cg programy lze používat ≈beze změny i v DirectX
Související OpenGL rozšíření obecná rozšíření: ARB_vertex_program, ARB_vertex_shader, ARB_fragment_program, ARB_fragment_program_shadow, ARB_shader_objects, ARB_fragment_shader
specifická rozšíření NVIDIA: NV_vertex_program, NV_vertex_program1_1, NV_vertex_program2, NV_vertex_program2_option, NV_fragment_program, NV_fragment_program_option, NV_fragment_program2, NV_vertex_program3
specifická rozšíření ATI: EXT_vertex_shader, ATI_fragment_shader, ATI_text_fragment_shader
Vertex programy ARB_vertex_program základní verze programů pro „vertex procesor“ – profil „ARBvp1.0“ (ekvivalent DirectX 8.0 = VS 1.0) limity: 16 atributů vrcholu, 96 uniformních parametrů, 12 temp. vektorů, 1 index-registr, 128 instrukcí zdarma: „swizzling“, negace argumentů instrukční sada (27): ABS, ADD, ARL, DP3, DP4, DPH, DST, EX2, EXP, FLR, FLC, LG2, LIT, LOG, MAD, MAX, MIN, MOV, MUL, POW, RCP, RSQ, SGE, SLT, SUB, SWZ, XPD
EXT_vertex_shader (zavedla firma ATI) jiný způsob zadávání shaderu (volání glShaderOp*EXT) instrukční sada: trochu užší než ARBvp1.0
Vertex programy pro NVIDIA NV_vertex_program základní verze pro NVIDIA GPU – profil „VP1.0“ limity: přesně jako ARBvp1.0 rezidentní programy, „tracking“ matic z aplikace do VP „vertex state program“ (jednorázově pro uniform. par.) instrukční sada (17): ADD, ARL, DP3, DP4, DST, EXP, LIT, LOG, MAD, MAX, MIN, MOV, MUL, RCP, RSQ, SGE, SLT
NV_vertex_program1_1 („VP1.1“, „vp20“) přidány 4 instrukce (ABS, DPH, RCC, SUB) „position-invariant vertex program“ – počítá pozici úplně přesně jako OpenGL FFP (může být rychlejší)
Vertex programy pro NVIDIA II NV_vertex_program2 (profil „VP2.0“, „vp30“) podstatné rozšíření profilů VP1.x (dřív než „ARBvp1.0“) zhruba ekvivalentní DirectX VS 2.0 podmíněné, nepodmíněné skoky, podprogramy (4 úrovně) 4 podmínkové příznaky, podle nich podmíněný zápis uživatelské ořezávání zdarma: absolutní hodnota jakéhokoli argumentu limity: 16 atributů vrcholu, 256 uniformních parametrů, 16 temp. vektorů, 2 index-vektory (10bit), 256 instrukcí nové instrukce (+18): ARA, ARR, BRA, CAL, COS, EX2, FLC, FLR, LG2, RET, SEQ, SFL, SGT, SIN, SLE, SNE, SSG, STR, varianty zapisující do podmínkových příznaků („*C“)
Vertex programy pro NVIDIA III NV_vertex_program2_option rozšiřuje profil ARB_vertex_program, aby obsahoval možnosti NV_vertex_program2 (ten existoval dříve!) direktiva „OPTION NV_vertex_program2;“
NV_vertex_program3 („vp40“, cca DirectX VS 3.0) formálně: „OPTION NV_vertex_program3;“ přístup k texturám (TEX, TXB, TXL, TXP) zásobník pro adresové registry (PUSHA, POPA) relativní adresování (na vstupu i výstupu programu) druhý vektor podmínkových příznaků zdarma: saturace („clamping“) na výstupu instrukce
Fragment programy ARB_fragment_program základní verze programů pro „fragment procesor“ – profil „ARBfp1.0“ (silnější než DirectX PS 1.1) uniformní parametry, přístup ke stavům OpenGL limity: 10 atributů fragmentu (interpolovaných z vrcholů) , 24 uniformních parametrů, 16 temp. vektorů, 48 ALU instrukcí, 24 TEX instrukcí, 4 zřetězené textury zdarma: „swizzling“, negace argumentů, „clamping“ výsl. instrukční sada (33): ABS, ADD, CMP, COS, DP3, DP4, DPH, DST, EX2, FLR, FRC, KIL, LG2, LIT, LRP, MAD, MAX, MIN, MOV, MUL, POW, RCP, RSQ, SCS, SGE, SIN, SLT, SUB, SWZ, TEX, TXB, TXP, XPD
Fragment programy II ARB_fragment_program_shadow odstranění závislosti na ARB_shadow direktiva „OPTION ARB_fragment_program_shadow;“ přidány cíle „SHADOW1D“, „...2D“ a „...RECT“
ATI_fragment_shader zadávání operací přes „glColorFragmentOp*ATI()“ a „glAlphaFragmentOp*ATI()“ 1 až 2 „průchody“: celkem až 8+8 instrukčních párů podobá se NV_texture_shader, NV_register_combiners
ATI_text_fragment_shader jiný systém zadávání programu (zdrojový kód)
Fragment programy pro NVIDIA NV_fragment_program („FP1.0“, „fp30“, ≈PS2.0) „F32“ (R) i „F16“ (H) floating-point aritmetika, int12 (X) limity: 32-64 temp. vektorů, 16 tex. jedn., 1024 instrukcí, neomezené čtení z textur, neomezené řetězení textur „lokální“ parametry (konstanty), podmínkové příznaky, podmíněný zápis výsledku op., absolutní hodn. na vstupu, „clamping“ na výstupu, podmíněné zrušení fragmentu instrukční sada (45): ADD, COS, DDX, DDY, DP3, DP4, DST, EX2, FLR, FLC, KIL, LG2, LIT, LRP, MAD, MAX, MIN, MOV, MUL, PK2H, PK2US, PK4B, PK4UB, POW, RCP, RFL, RSQ, SEQ, SFL, SGE, SGT, SIN, SLE, SLT, SNE, STR, SUB, TEX, TXD, TXP, UP2H, UP2US, UP4B, UP4UB, X2D varianty: aritm. (R,H,X), zápis do podm. přízn., „clamping“
Fragment programy pro NVIDIA II NV_fragment_program_option rozšiřuje profil ARB_fragment_program, o možnosti NV_fragment_program (ten existoval dříve!) direktiva „OPTION NV_fragment_program;“
NV_fragment_program2 („fp40“, cca DX PS3.0) formálně: „OPTION NV_fragment_program2;“ podmíněné skoky, podprogramy, smyčky s pevným opakováním i s podmínkou (BRK) normalizace vektoru, dělení skalárem, 2D skalár. součin, .. explicitní LoD do textury, proměnná cyklu při adresaci instrukce (+14): BRK, CAL, DIV, DP2[A], IF/ELSE/ENDIF, LOOP/ENDLOOP, REP/ENDREP, RET, TXL
Rozšíření kolem GLSL ARB_shader_objects překlad programů, linkování, zapojování do GL stavu, hlášení o chybách, ...
ARB_vertex_shader vertex programy v jazyce GLSL
ARB_fragment_shader fragmentové programy v jazyce GLSL
ARB_shading_language_100 první verze GLSL (dnes existuje verze 1.10 – součást OpenGL 2.0)
Příklady NVIDIA GeForce FX 5200 ARB_vertex_program, ARB_shader_objects, NV_vertex_program, NV_vertex_program1_1, NV_vertex_program2, NV_vertex_program2_option, ARB_fragment_program, ARB_fragment_program_shadow, NV_fragment_program, NV_fragment_program_option, ARB_vertex_shader, ARB_fragment_shader, ARB_shading_language_100
Intel 82915 G ARB_vertex_program, ARB_fragment_program
ATI Radeon 8500 ARB_vertex_program, EXT_vertex_shader, ATI_fragment_shader
ATI Radeon 9000 ARB_vertex_program, EXT_vertex_shader, ATI_fragment_shader
Literatura Tomas Akenine-Möller, Eric Haines: Real-time rendering, 2nd edition, A K Peters, 2002, ISBN: 1568811829 Randima Fernando, Mark J. Kilgard: The Cg Tutorial, Addison-Wesley, 2003, ISBN: 0321194969 OpenGL ARB: OpenGL Programming Guide, 4th edition, Addison-Wesley, 2004, ISBN: 0321173481 Randi J. Rost: OpenGL Shading Language, Addison-Wesley, 2004, ISBN: 0321197895 http://developer.nvidia.com/ http://www.shadertech.com/