Tipi di risorsa
Diversi tipi di risorse hanno un layout distinto (o footprint di memoria). Tutte le risorse usate dalla pipeline Direct3D derivano da due tipi di risorse basilari: buffer e texture. Un buffer è una raccolta di dati non elaborati (elementi); una texture è una raccolta di texel (elementi texture).
Esistono due modi per specificare completamente il layout (o il footprint di memoria) di una risorsa:
Articolo | Descrizione |
---|---|
Tipizzato |
Specificare completamente il tipo quando viene creata la risorsa. |
Senza tipo |
Specificare completamente il tipo quando la risorsa è associata alla pipeline. |
Risorse di buffer
Una risorsa di buffer è una raccolta di dati completamente tipizzati. Internamente, un buffer contiene elementi. Un elemento è costituito da 1 a 4 componenti. Esempi di tipi di dati degli elementi includono: un valore di dati compresso (ad esempio R8G8B8A8), un intero singolo a 8 bit, quattro valori float a 32 bit. Questi tipi di dati vengono usati per archiviare i dati, ad esempio un vettore di posizione, un vettore normale, una coordinata di texture in un buffer dei vertici, un indice in un buffer dell'indice o lo stato del dispositivo.
Un buffer viene creato come risorsa non strutturata. Poiché non è strutturato, un buffer non può contenere alcun livello mipmap, non viene filtrato durante la lettura e non può essere multicampionato.
Tipi di buffer
Buffer dei vertici
Un buffer è una raccolta di elementi; un buffer dei vertici contiene dati per vertice. L'esempio più semplice è un buffer dei vertici che contiene un tipo di dati, ad esempio i dati di posizione. Può essere visualizzato come illustrato di seguito.
Più spesso, un buffer di vertice contiene tutti i dati necessari per specificare completamente i vertici 3D. Un esempio di questo potrebbe essere un buffer dei vertici che contiene coordinate normali e di texture per ogni posizione vertice. Questi dati sono in genere organizzati come set di elementi per vertice, come illustrato nella figura seguente.
Questo buffer dei vertici contiene dati per otto vertici; ciascun vertice archivia tre elementi (coordinate di posizione, normale e texture). La posizione e la normale vengono in genere specificate usando tre float a 32 bit e le coordinate della texture usando due float a 32 bit.
Per accedere ai dati da un buffer di vertice, è necessario conoscere il vertice a cui accedere e questi altri parametri del buffer:
- Offset : il numero di byte dall'inizio del buffer ai dati per il primo vertice.
- BaseVertexLocation : numero di byte dall'offset al primo vertice utilizzato dalla chiamata di disegno appropriata.
Prima di creare un buffer dei vertici, è necessario definirne il layout creando un oggetto input-layout. Dopo aver creato l'oggetto input-layout, associarlo alla fase Input assembler (IA).
Buffer indice
Un buffer di indice contiene un set sequenziale di indici a 16 bit o a 32 bit; ogni indice viene usato per identificare un vertice in un buffer dei vertici. L'uso di un buffer di indice con uno o più buffer di vertice per fornire i dati alla fase IA è detto indicizzazione. Un buffer di indice può essere visualizzato come illustrato di seguito.
Gli indici sequenziali archiviati in un buffer di indice si trovano con i parametri seguenti:
- Offset : il numero di byte dall'inizio del buffer al primo indice.
- StartIndexLocation : numero di byte dall'offset al primo vertice utilizzato dalla chiamata di disegno appropriata.
- IndexCount : numero di indici di cui eseguire il rendering.
Un buffer di indice può unire più strisce di linee o triangoli (topologie primitive) separandole ognuna con un indice di taglio a strisce. Un indice di taglio a strisce consente di disegnare più strisce di linee o triangoli con una singola chiamata di disegno. Un indice di taglio con strip è il valore massimo possibile per l'indice (0xffff per un indice a 16 bit, 0xffffffff per un indice a 32 bit). L'indice di taglio a strisce reimposta l'ordine di avvolgimento nelle primitive indicizzate e può essere usato per rimuovere la necessità di degenerare triangoli che potrebbero altrimenti essere necessari per mantenere l'ordine di avvolgimento corretto in una striscia di triangoli. Nella figura seguente viene illustrato un esempio di un indice a taglio di strisce.
Buffer costante
Direct3D dispone di un buffer per la fornitura delle costanti dello shader, denominato buffer di shader costante o semplicemente buffer costante. Concettualmente, è simile a un buffer di vertici a singolo elemento, come illustrato nella figura seguente.
Ogni elemento archivia una costante componente da 1 a 4, determinata dal formato dei dati archiviati.
I buffer costanti riducono la larghezza di banda necessaria per aggiornare le costanti shader consentendo di raggruppare le costanti shader e di eseguirne il commit contemporaneamente anziché effettuare singole chiamate per eseguire il commit di ogni costante separatamente.
Uno shader continua a leggere le variabili in un buffer costante direttamente in base al nome della variabile nello stesso modo in cui le variabili che non fanno parte di un buffer costante vengono lette.
Ogni fase dello shader consente fino a 15 buffer costanti shader; ogni buffer può contenere fino a 4096 costanti.
Usare un buffer costante per archiviare i risultati della fase di output del flusso.
Vedere Costanti shader (DirectX HLSL) per un esempio di dichiarazione di un buffer costante in uno shader.
Risorse di texture
Una risorsa texture è una raccolta strutturata di dati progettata per archiviare i texel. A differenza dei buffer, le texture possono essere filtrate in base ai campioni di texture mentre vengono lette dalle unità shader. Il tipo di texture influisce sulla modalità di filtro della stessa texture. Un texel rappresenta l'unità più piccola di una texture in cui è possibile leggere o scrivere dalla pipeline. Ogni texel contiene da 1 a 4 componenti, disposti in uno dei formati DXGI (vedere DXGI_FORMAT).
Le Texture vengono create come risorsa strutturata in modo che le dimensioni siano note. Tuttavia, ogni texture può essere tipizzata o senza tipizzazione in fase di creazione risorse, purché il tipo venga specificato completamente usando una visualizzazione quando la texture è associata alla pipeline.
Tipi di trama
Esistono diversi tipi di texture: 1D, 2D, 3D, ognuno dei quali può essere creato con o senza mipmap. Direct3D supporta anche matrici di texture e texture multicampionamento.
Texture 1D
Una texture 1D nella sua forma più semplice contiene dati di texture che possono essere indirizzati con una singola coordinata; può essere visualizzata come una matrice di texel, come illustrato nella seguente figura.
Ogni texel contiene un numero di componenti di colore a seconda del formato dei dati archiviati. Aggiungendo maggiore complessità, è possibile creare una texture 1D con livelli mipmap, come illustrato nella figura seguente.
Un livello mipmap è una texture corrispondente a una potenza di due dimensioni inferiori rispetto al livello sopra lo stesso. Il livello più alto contiene il maggior dettaglio, ogni livello successivo è più piccolo; per un mipmap 1D, il livello più piccolo contiene un texel. I diversi livelli sono identificati da un indice denominato LOD (livello di dettaglio); è possibile usare il LOD per accedere a una trama più piccola quando si esegue il rendering di geometria che non è così vicina alla fotocamera.
Matrice di texture 1D
Direct3D 10 ha anche una nuova struttura di dati per una matrice di texture. Una matrice di texture 1D è concettualmente simile alla figura seguente.
Questa matrice di texture contiene tre texture. Ognuna delle tre texture ha una larghezza di texture pari a 5 (ovvero il numero di elementi nel primo livello). Ogni texture contiene anche una mipmap a 3 livelli.
Tutte le matrici di texture in Direct3D sono una matrice omogenea di texture; ciò significa che ogni texture in una matrice deve avere lo stesso formato e dimensioni dei dati (inclusa la larghezza della texture e il numero di livelli mipmap). È possibile creare matrici di texture di dimensioni diverse, purché tutte le texture in ogni matrice corrispondano in base alle dimensioni.
Texture 2D e matrice di texture 2D
Una risorsa texture2D contiene una griglia 2D di texel. Ogni texel è indirizzabile da un vettore u, v. Poiché si tratta di una risorsa di texture, può contenere livelli mipmap e sottorisorse. Una risorsa texture 2D completamente popolata è simile alla figura successiva.
Questa risorsa texture contiene una singola texture 3x5 con tre livelli mipmap.
Una risorsa Texture2DArray è una matrice omogenea di texture 2D; ovvero, ogni texture ha lo stesso formato di dati e dimensioni (inclusi i livelli mipmap). Ha un layout simile a quello della matrice di texture 1D, ad eccezione del fatto che le texture contengono ora dati 2D e quindi hanno un aspetto simile alla figura seguente.
Questa matrice di texture contiene tre texture; ogni texture è 3x5 con due livelli mipmap.
Uso di texture2DArray come cubo texture
Un cubo texture è una matrice di texture 2D che contiene 6 texture, una per ogni faccia del cubo. Un cubo di texture completamente popolato è simile alla figura seguente.
Una matrice 2D contenente 6 texture può essere letta dagli shader con le funzioni intrinseche della mappa del cubo, dopo che sono associate alla pipeline con una visualizzazione di texture cubo. I cubi di texture vengono indirizzati dallo shader con un vettore 3D che punta dal centro del cubo di texture.
Texture 3D
Una risorsa Texture3D (nota anche come texture del volume) contiene un volume 3D di texel. Poiché si tratta di una risorsa texture, può contenere livelli mipmap. Una texture 3D completamente popolata è simile alla figura seguente.
Quando una sezione mipmap texture 3D è associata come output di destinazione del rendering (con una visualizzazione di destinazione di rendering), la texture 3D si comporta in modo identico a una matrice di texture 2D con n sezioni. La sezione di rendering specifica viene scelta dalla fase geometry-shader.
Non esiste alcun concetto di matrice di texture 3D; pertanto una sottorisorsa di texture 3D è un singolo livello mipmap.
Sottorisorse
L'API Direct3D fa riferimento a intere risorse o subset di risorse. Per specificare una parte delle risorse, Direct3D ha coniato il termine sottorisorse, ovvero un sottoinsieme di una risorsa.
Un buffer viene definito come una singola sottorisorsa. Le texture sono leggermente più complesse perché esistono diversi tipi di texture (1D, 2D e così via) alcuni dei quali supportano livelli mipmap e/o matrici di texture. A partire dal caso più semplice, una texture 1D viene definita come una singola sottorisorsa, come illustrato nella figura seguente.
Ciò significa che la matrice di texel che costituiscono una texture 1D è contenuta in una singola sottorisorsa.
Se si espande una texture 1D con tre livelli mipmap, può essere visualizzata in questo modo.
Si pensi a questa come una texture singola costituita da tre sottotexture. Ciascuna sottotexture viene conteggiata come sottorisorsa, quindi questa texture 1D contiene 3 sottorisorse. Una sottotexture (o sottorisorsa) può essere indicizzata usando il livello di dettaglio (LOD) per una singola texture. Quando si usa una matrice di texture, l'accesso a una particolare sottotexture richiede sia il LOD che la texture specifica. In alternativa, l'API combina queste due informazioni in un singolo indice di sottorisorsa in base zero, come illustrato di seguito.
Selezione di sottorisorse
Alcune API accedono a un'intera risorsa, altre accedono a una parte di una risorsa. Le API che accedono a una parte di una risorsa usano in genere una descrizione di visualizzazione per specificare le sottorisorse a cui accedere.
Queste figure illustrano i termini usati da una descrizione di visualizzazione quando si accede a una matrice di texture.
Sezione matrice
Data una matrice di texture, ciascuna texture con mipmap, una sezione di matrice (rappresentata dal rettangolo bianco) include una texture e tutte le relative sottotexture, come illustrato nella figura seguente.
Sezione Mip
Una sezione mip (rappresentata dal rettangolo bianco) include un livello mipmap per ogni texture in una matrice, come illustrato nella figura seguente.
Selezione di una singola sottorisorsa
È possibile usare questi due tipi di sezioni per scegliere una singola sottorisorsa, come illustrato nella figura seguente.
Selezione di più sottorisorse
In alternativa, è possibile usare questi due tipi di sezioni con il numero di livelli mipmap e/o il numero di texture, per scegliere più sottorisorse.
Indipendentemente dal tipo di texture in uso, con o senza mipmap, con o senza una matrice di texture, sono spesso disponibili funzioni helper per calcolare l'indice di una determinata sottorisorsa.
Tipizzazione forte e debole
La creazione di una risorsa completamente tipizzata limita la risorsa al formato con cui è stata creata. Ciò consente al runtime di ottimizzare l'accesso, soprattutto se la risorsa viene creata con flag che indicano che non può essere mappata dall'applicazione. Le risorse create con un tipo specifico non possono essere reinterpretate usando il meccanismo di visualizzazione.
In una risorsa senza tipi, il tipo di dati è sconosciuto quando la risorsa viene creata per la prima volta. L'applicazione deve scegliere tra i formati senza tipi disponibili. È necessario specificare le dimensioni della memoria da allocare e se il runtime dovrà generare le sottotexture in un mipmap.
Tuttavia, il formato esatto dei dati (se la memoria verrà interpretata come numeri interi, valori a virgola mobile, numeri interi senza segno e così via) non viene determinato fino a quando la risorsa non è associata alla pipeline con una visualizzazione. Poiché il formato della texture rimane flessibile fino a quando la stessa non viene associata alla pipeline, la risorsa viene definita risorsa di archiviazione tipizzata in modo debole. L'archiviazione tipizzata in modo debole ha il vantaggio che può essere riutilizzata o reinterpretata (in un altro formato), purché il bit del componente del nuovo formato corrisponda al numero di bit del formato precedente.
Una singola risorsa può essere associata a più fasi della pipeline, purché ognuna abbia una visualizzazione univoca, che qualifica completamente i formati in ogni posizione. Ad esempio, una risorsa creata con un formato senza tipi può essere usata come formato FLOAT e un formato UINT in posizioni diverse nella pipeline contemporaneamente.