Una delle principali difficoltà nello sviluppo di applicativi e giochi 3D è il doversi confrontare con un numero di configurazioni pressoché infinite. Con ogni nuova versione di Direct3D vengono introdotte caratteristiche che richiedono nuove schede video. Di conseguenza se si vuole che il proprio gioco sfrutti le nuove caratteristiche Direct3D ma allo stesso tempo sia compatibile con i vecchi hardware bisogna interrogare la scheda video ed abilitare o disabilitare funzionalità in base a questa.
Fino alla versione 9 le schede si differenziavano in tantissimi particolari e nessuna caratteristica poteva essere data per scontata. Con la versione 10 invece è stato dato un set di caratteristiche specifiche da dover rispettare. In questo modo una scheda o supportava Direct3D10 in tutte le sue caratteristiche o non lo supportava affatto. Con la versione 11 la cosa è stata ulteriormente migliorata ed ora esistono 6 configurazioni che prendono il nome di FeatureLevel
- Level9_1
- Level9_2
- Level9_3
- Level10
- Level10_1
- Level11
Le feature level 9 permettono di utilizzare DirectX11 anche su hardware DirectX9 seppur fortemente limitate. L’ help contenuto nella SDK contiene una tabella con le caratteristiche che ogni versione supporta. Utilizzare una caratteristica non valida per la propria FeatureLevel restituirà un errore. Durante l’inizializzazione di Direct3D sarà inoltre possibile indicare quale versione utilizzare in modo da poter verificare le funzionalità anche su hardware inferiori a quello su cui si sviluppa.
D3D_FEATURE_LEVEL maxFeature;
D3D11CreateDevice(NULL,D3D_DRIVER_TYPE_HARDWARE,NULL,NULL,NULL,0,D3D11_SDK_VERSION,NULL,&maxFeature,NULL);
Utilizzando il metodo D3D11CreateDevice passando tutti valori Null viene valorizzato il parametro maxFeature con il livello massimo supportato dalla scheda.
Ci sono comunque altre caratteristiche che si devono controllare. La prima è il conteggio delle schede video in quanto in un computer possono esserne presenti diverse oppure una sola scheda ad identificarsi in più modi. A sua volta ogni scheda video può avere una o più uscite ed ogni uscita può supportare un certo numero di risoluzioni.
Questo viene fatto dal framework DGXI, indipendente dalla versione di Direct3D. Innanzittutto è sufficiente creare un oggetto Factory
IDXGIFactory1 * factoryPointer;
CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void**)(&factoryPointer) );
Quindi utilizzare il metodo EnumAdapters1 per ottenere tutte le schede video installate.
IDXGIAdapter1 * adapterPointer;
factoryPointer->EnumAdapters1(i, & adapterPointer)
Dove i è il numero della scheda da controllare. Basta ciclare partendo da 0 finchè il metodo non restituisce un errore DXGI_ERROR_NOT_FOUND. In modo identico l’interfaccia IDXGIAdapter1 restituisce tutti gli output tramite il metodo EnumOutputs
IDXGIOutput * outputPointer;
adapterPointer->EnumOutputs(i, & outputPointer)
Infine l’oggetto IDXGIOutput restituisce una lista con tutte le risoluzioni supportate.
UINT num = 0;
outputPointer->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &num, 0);
DXGI_MODE_DESC * desc = new DXGI_MODE_DESC[num];
outputPointer->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &num, desc);
Il metodo GetDisplayModeList restituisce nell’intero num il numero di risoluzioni supportate se viene passato 0 all’ultimo parametro mentre restituisce un array di strutture DXGI_MODE_DESC se valorizzato.
Questo array contiene tutte le risoluzioni differenziate sia per larghezza ed altezza che per frequenza dello schermo. Per ottenere informazioni sulla scheda e sull’output è sufficiente utilizzare per entrambi il metodo GetDesc che restituisce una struttura valorizzata con tutte le caratteristiche supportate, dal nome alla quantità di memoria.
Per comprendere appieno il funzionamento vi lascio ai 2 esempio, il primo in C++, il secondo in .Net tramite il wrapper ManagedDirectX.
Demo C++
Demo .Net