Qual è un buon approccio per maneggiare le uniformi nel moderno OpenGL?


8

Sto creando un renderer utilizzando OpenGL moderno (3.1 e versioni successive) e ora sto cercando di creare un modo efficiente ma flessibile di gestire le uniformi. Ho letto su oggetti buffer uniformi e su quale approccio "comune" è usare questi (purtroppo quest'ultimo non mi ha dato tutti i risultati sperati).

Al fine di ridurre le chiamate API OpenGL e l'archiviazione dei dati in memoria contigua, sto prendendo in considerazione la creazione di più buffer di grandi dimensioni per ogni struttura di dati che devono essere caricati nella GPU. Ogni buffer ha una dimensione massima di 16kb (come da quanto ho capito è garantito per essere disponibile per un UBO). Quando un oggetto vuole essere in grado di caricare uniformi nella GPU, recupera il primo buffer del tipo da caricare che non è ancora pieno e ottiene il successivo indice disponibile in quel buffer. Quando l'oggetto viene disegnato, lega l'UBO (se non ancora associato) e carica l'indice dell'elemento dell'UBO.

Ciò si traduce in qualcosa del genere:

layout(std140) uniform ModelData { 
    mat4 model_matrix[kNumInstancesPerModelUbo]; 
}
uniform int u_ModelDataIndex;

layout(std140) uniform SkeletonData { 
    mat4 bone_transforms[kNumInstancesPerSkeletonUbo][kMaxBones]; 
}
uniform int u_SkeletonDataIndex;

Tuttavia sto anche considerando quanto segue:

layout(std140) uniform MeshData {
    mat4 model_matrix[kNumInstancesPerMeshUbo];
    mat4 bone_transforms[kNumInstancesPerMeshUbo][kMaxBones];
}
uniform int u_MeshDataIndex;

In un certo senso questo sembra molto più pulito in quanto è necessario un singolo indice per accedere a tutti i dati relativi alla mesh da caricare. D'altra parte, ciò potrebbe sfuggire di mano (dimensioni del buffer maggiori di 16kb, gestione di dati irrilevanti (ad esempio una mesh senza scheletro) o problemi di sincronizzazione in quanto non è consentito l'accesso per dire le ossa durante il caricamento delle matrici del modello) e non sono sicuro di come ciò influenzerebbe il layout di memoria sulla GPU.

Francamente mi sembra di essere bloccato qui e non riesco a trovare un buon esempio concreto di come gestiresti la UBO in modo rapido e flessibile.

Hai qualche consiglio o risorsa per me che potrebbe aiutarmi qui?

Risposte:


2

La suballocazione da un buffer più grande è assolutamente la strada da percorrere, con avvertimenti. Sto venendo più da un lato delle cose DirectX / Vulkan, ma questo dovrebbe valere anche per OpenGL (non avrò chiamate API dirette qui in questa risposta). Le cose da considerare sono le seguenti:

  • Devi indicizzare nel buffer più grande o stai bene rilegando ogni volta la risorsa con l'offset?
  • Hai preso in considerazione tutte le restrizioni di allineamento per le tue uniformi che sono impacchettate insieme (l'allineamento a 256 byte è comune)?

Le API grafiche più recenti hanno un "offset dinamico" che puoi specificare con il comando draw che è un modo abbastanza veloce per accedere indirettamente a una sottoregione di un buffer. Tuttavia, supponendo che si tratti di dati a triplo buffering mutabili, nel driver dovrebbe esserci poca o nessuna contesa per l'associazione dei dati (solo un sovraccarico fisso).

In sintesi, sì, l'allocazione di aree più grandi di memoria / buffer e la sublocazione di tali aree è considerata la migliore pratica. Questo vale anche per oggetti con shader diversi (se l'allocatore può gestirlo).


0

Includere una fase di benchmarking per entrambe le soluzioni nell'applicazione e quindi selezionare la soluzione vincente in fase di esecuzione. Questo è semplice, portatile e a prova di futuro. Voglio dire, hai dei test per questo, giusto? ;-)

So che questa è una risposta piuttosto generica alle "migliori pratiche" per prestazioni elevate, ma se ci pensate ci sono migliaia di possibili configurazioni target e molti fornitori da considerare. Se hai bisogno di quel piccolo extra, vai a pagare il tuo fornitore per un driver ottimizzato per la tua applicazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.