• Non ci sono risultati.

OpenGL [7] `e la pi`u famosa API ideata per l’utilizzo della GPU per il processo di rendering. E’ considerata uno standard ed `e adottata dalla maggioranza delle case del settore. Sono disponibili diverse versioni di OpenGL e l’ultima disponibile `e la 4.6. Per i sistemi embedded, `e disponibile una specifica pi`u ristretta della libreria denominata OpenGL ES (Open Graphics Library for Embedded Systems). OpenGL

`e sprovvista di codice sorgente essendo quest’ultima solo una specifica adottata dai principali produttori di schede grafiche.

La versione al quale VitaGL punta maggiormente `e la specifica OpenGL ES 1.1. Essa

`e sprovvista di rendering tramite shader ed implementa una fixed function pipeline correlata con una macchina a stati per la gestione delle feature da utilizzare durante la fase di rendering.

Alcune feature della specifica OpenGL ES 2.0 sono state implementate in VitaGL an-che se quest’ultime non sono feature richieste per lo sviluppo di vitaQuakeIII e pertanto non verranno prese in esame durante la scrittura di questo documento.

3 VitaGL, l’implementazione

Figura 8: Struttura del lavoro di porting effettuato

VitaGL `e la libreria intermedia sviluppata utilizzando SceGxm che permetter`a l’utilizzo in maniera indiretta di OpenGL su Sony PlayStation Vita e, come mostrato nellaR

fig. 8, `e il principale componente per quanto riguarda il porting del codice relativo al rendering di ioquake3. Il suo sviluppo `e iniziato il 29 Dicembre 2017 ed `e tutt’ora in corso sebbene sia gi`a utilizzabile per progetti non estremamente complessi.

L’obiettivo finale della libreria `e di fornire un’implementazione completa e performante di OpenGL 1.x ed OpenGL 2.x. L’enfasi attuale `e riposta nell’implementazione di feature senza fare estrema attenzione alle performance (che vengono comunque prese in esame in fase di sviluppo).

Allo stato attuale essa implementa un buon numero di feature di OpenGL 1.x ed alcune feature core di OpenGL 2: depth testing, alpha testing, scissor testing pixel based, cul-ling, rendering tramite fixed function pipeline o tramite shader personalizzati, funzioni basilari di texture environment, etc.

Una release ufficiale non `e disponibile per via della natura fortemente sperimentale della libreria ma il codice sorgente `e completamente fruibile su GitHub [11].

VitaGL `e completamente scritta in C (7400 righe di codice circa), con l’eccezione di alcuni shader, del quale parleremo pi`u avanti, scritti in Cg (243 righe di codice), un linguaggio sviluppato da NVIDIA con l’idea di essere simile al C ma utilizzabile per sviluppare programmi per la GPU [1]. Essa presenta alcune funzioni specifiche per l’i-nizializzazione di sceGxm ed alcune funzioni uniche, non presenti nell’originale spe-cifica di OpenGL, per la gestione del rendering (operazioni che normalmente vengono gestite da SDL per applicazioni utilizzanti OpenGL, come ad esempio l’aggiornamento della schermata dell’applicazione).

1 // vgl*

2 void vglEnd(void);

3 void *vglGetTexDataPointer(GLenum target);

4 void vglInit(uint32_t gpu_pool_size);

5 void vglInitExtended(uint32_t gpu_pool_size, int width, int height, \

6 int ram_threshold, SceGxmMultisampleMode msaa);

7 void vglMapHeapMem(void);

Codice 1: Prototipi delle funzioni uniche di VitaGL.

Le funzioni non facenti parti della specifica di OpenGL, come mostrato nel cod. 1, han-no come suffisso vgl per differenziarsi dalle han-normali funzioni di OpenGL con suffisso gl.

Per l’implementazione delle funzioni standard di OpenGL, VitaGL presenta una mac-china a stati che si occupa della gestione delle molteplici feature attivabili e persona-lizzabili tramite le funzioni proposte da OpenGL (glEnable, glDisable, glBlendFunc, etc...). Ogni volta che una di queste funzioni viene chiamata, lo stato della macchina viene alterato ed i settaggi di sceGxm vengono aggiornati di conseguenza.

1 static void update_polygon_offset(){

28 break;

44 void glPolygonOffset(GLfloat factor, GLfloat units){

45 pol_factor = factor;

46 pol_units = units;

47 update_polygon_offset();

48 }

Codice 2: Implementazione di glPolygonOffset in VitaGL.

Un esempio `e dato dal cod. 2 che mostra l’implementazione di glPolygonOffset e come al variare di settaggi in OpenGL corrispondano variazioni nella macchina a stati di VitaGL (righe 45-46) e come queste variazioni vengono poi utilizzate per alterare i settaggi di sceGxm (righe 2-41).

Tramite questo meccanismo, la maggior parte delle funzioni pu`o essere implemen-tata tuttavia vi sono alcuni passaggi che meritano un approfondimento sulle scelte implementative adottate.

Vedremo ora come le numerose discrepanze funzionali tra OpenGL e SceGxm sono state risolte durante lo sviluppo di VitaGL rendendo possibile la nascita di vitaQua-keIII.

3.1 Fixed Function Pipeline

Come spiegato precedentemente, OpenGL 1.x, utilizzato da id Tech 3 per il renderer, non supporta shader personalizzati bens`ı presenta una fixed function pipeline che si occupa di gestire, mediante vari stati programmabili, tutti gli effetti da applicare du-rante il rendering. Per ovviare a questo problema, VitaGL presenta alcuni shader di default che verranno utilizzati nel caso in cui shader personalizzati non siano richiesti.

Tali shader, tramite alcune uniform (variabili globali di uno shader al quale `e possibi-le assegnare un valore tramite codice C dall’applicazione), emulano il comportamento della fixed function pipeline presente in OpenGL 1.x e pertanto permettono l’utilizzo

di alcune feature che normalmente non sono disponibili con sceGxm (allo stato attua-le, VitaGL implementa, tramite questo meccanismo, i sistemi di texture environment, alpha testing e fogging).

14 float4 texColor = tex2D(tex, vTexcoord);

15

16 // Texture Environment

17 if (texEnv < 4){

18 if (texEnv == 0){ // GL_MODULATE

19 texColor = texColor * vColor;

20 }else if (texEnv == 1){ // GL_DECAL

21 texColor.rgb = lerp(vColor.rgb, texColor.rgb, texColor.a);

22 texColor.a = vColor.a;

23 }else if (texEnv == 2){ // GL_BLEND

24 texColor.rgb = lerp(vColor.rgb, texEnvColor.rgb, texColor.rgb);

25 texColor.a = texColor.a * vColor.a;

26 }else{ // GL_ADD

27 texColor.rgb = texColor.rgb + vColor.rgb;

28 texColor.a = texColor.a * vColor.a;

29 }

46 }else if (alphaOp == 3){

65 texColor.rgb = lerp(fogColor.rgb, texColor.rgb, vFog);

66 }

67

68 return texColor;

69 }

Codice 3: Fragment Shader per texture con tinta di VitaGL

Il codice mostrato qui sopra (cod.3) mostra uno dei fragment shader (codice eseguito dalla GPU per ogni frammento da processare dopo la rasterizzazione dei vertici ese-guita da un vertex shader) di default utilizzati da VitaGL. Da come si evince da esso, una volta venuti a conoscenza degli algoritmi implementativi utilizzati da OpenGL per le feature richieste [2], `e possibile applicare tali conoscenze negli shader in modo da ricreare la fixed function pipeline utilizzata da OpenGL 1.x. Da notare come l’imple-mentazione di nuove feature richieda di aggiungere branching negli shader stessi infatti lo shader mostrato in figura presenta 3 branch ossia quello relativo all’implementazio-ne del texture environment (righe 16-30), quello relativo all’alpha testing (righe 32-61) e quello relativo al fogging (righe 63-66). Considerando che i fragment shader vengono eseguiti per ogni frammento da processare, aggiungere molte feature pu`o ri-sultare degradante per le performance della libreria in quanto, differentemente da come accade con del normale codice C, gli shader non vengono ottimizzati in fase di com-pilazione pertanto le if in cascata potranno arrivare ad essere eseguite per un numero estremamente alto di volte per frame in base a quanto complessa `e la scena da rende-rizzare. Un modo per evitare ci`o sarebbe quello di suddividere gli shader in pi`u file a seconda di quali feature sono attive e quali non lo sono nella pipeline (Ad esempio, creare uno shader che non presenti il branching relativo al fogging se quest’ultimo non

`e attivo). Allo stato attuale per`o, tale possibilit`a non `e stata presa in considerazione per via del fatto che le feature implementate sono ancora relativamente poche; inoltre l’as-senza di un runtime shader compiler renderebbe questa operazione piuttosto tediosa e complicherebbe in maniera significativa il codice stesso della libreria.

Documenti correlati