I dati della GUI accelerati hardware sono conservati sulla GPU

8

Sto facendo qualche ricerca su come funziona la maggior parte delle librerie GUI con accelerazione hardware. In realtà mi preoccupo solo dei rendering backend di loro qui. Sto cercando di capire quale sarebbe il modo migliore per provare a scrivere il mio come una sorta di progetto parallelo. Sto cercando di andare per la massima performance qui invece di funzioni troppo stravaganti. Voglio poter disegnare primitive, testo e animazioni.

Alcune buone librerie che conosco sono Qt, Skia e Cairo (anche se non sono sicuro di quale sia lo stato di HWA su di esso). Ho anche guardato NanoVG che è una piccola libreria che sembra avere un seguito decente. Tuttavia, non sono riuscito a ottenere prestazioni decenti con NanoVG ...

L'unica cosa che mi ha colpito è che tutte queste librerie sembrano utilizzare il concetto di "pittura" dove sembra che ogni forma primitiva venga estratta da zero più e più volte. Quello che intendo è che dalle API, non sembra che le forme siano create come "oggetti" sulla GPU o qualunque sia la terminologia e quindi lasciate lì per essere rese "automaticamente". In altre parole, non vengono lasciati nella memoria della GPU per essere ridisegnati in un grande loop. Per elaborare, sembra che per ogni i.e. rettangolo che deve essere disegnato, un intero stato OpenGL è impostato solo per il rendering di quel rettangolo e quindi viene nuovamente distrutto. Tuttavia, sembra che queste forme renderizzate siano almeno renderizzate nelle loro destinazioni finali, consentendo alla GPU di comporre l'intera scena.

Il modo in cui mi aspettavo che queste librerie funzionassero è in realtà l'archiviazione dell'intera scena sulla GPU (scusate la terminologia orribile). Per esempio, le primitive sarebbero state triangolate e lasciate in memoria dove dopo un processo complesso sarebbe stato usato per avere un ciclo di rendering principale per la scena. Inoltre, ci sarebbero i meccanismi per aggiornare gli attributi o eliminare o aggiungere le primitive. Questa è una descrizione abbastanza vaga, ma penso che tu abbia l'idea.

Quello che vorrei chiedere ora è se c'è un vantaggio in termini di prestazioni nell'approccio "pittura" rispetto all'approccio "salvato" (di nuovo, non c'è idea se esistano nomi propri per queste cose ...). Forse alcuni complicati meccanismi di caching? O è molto più semplice lavorare con?

Mi rendo conto che l'approccio "salvato" potrebbe utilizzare più memoria sulla GPU ma tutte le chiamate OpenGL necessarie per l'approccio "pittura" non sono molto costose? Immagino che si possa essere in grado di compensare questo problema memorizzando nella cache le forme renderizzate, ma la GPU offre davvero un vantaggio così grande quando si esegue una rasterizzazione così una tantum (o non molto regolare) rispetto alla CPU, specialmente data la comunicazione in testa? Inoltre, questo overhead di comunicazione non pone seri problemi alle animazioni quando si deve eseguire il disegno per ogni frame?

Sono abbastanza certo che NanoVG non abbia un meccanismo di caching interno e presumo che questo potrebbe essere responsabile delle sue prestazioni piuttosto scialbe. Qt d'altra parte sembra avere prestazioni eccellenti, quindi deve fare qualcosa di giusto. Google sembra anche in grado di mettere Skia a buon uso.

PS. Non sono un professionista di nessun tipo e solo di recente ho iniziato ad imparare OpenGL.

EDIT: Un'altra possibilità che ho pensato è che forse l'approccio alla "pittura" è stato ritenuto necessario unicamente a causa dei benefici della memoria? La ragione per cui penso sarebbe che tutte queste librerie sono state ovviamente avviate in un'era diversa e hanno anche indirizzato le piattaforme embedded, il che significa che la memoria della GPU potrebbe essere così scarsa sulle piattaforme target (ed) e che usare il meno possibile di essa potrebbe essere più importante delle prestazioni. Tuttavia, in una situazione come questa, non sono convinto che la rasterizzazione della GPU frame-by-frame data l'overhead della comunicazione possa sovraperformare una CPU, specialmente considerando il numero di pixel probabilmente basso su piattaforme con così poca memoria.

Inoltre ho letto su link che Qt apparentemente unisce il codice shader dei segmenti precodificati in fase di esecuzione prima di "dipingere" e quindi spera che il compilatore OGL inserisca correttamente il codice in fase di runtime. Questo suona come l'ulteriore inizializzazione OGL per me ...

    
posta Gerharddc 09.09.2015 - 19:13
fonte

1 risposta

6

Salvare l'intera finestra come un singolo oggetto in GPU (sarebbe un mucchio di rettangoli salvati come VBO) e quindi renderlo in una singola chiamata di disegno OpenGL sarebbe veloce, ma ha diversi svantaggi:

  • L'intera geometria dovrebbe essere resa utilizzando un singolo shader. È più utile avere shader separati (per copie opache, copia trasparente, gradiente, ...)
  • L'intera geometria potrebbe utilizzare solo da una quantità limitata di trame. Anche se usi gli atlanti, hai bisogno di molte trame per la GUI. (Pezzi del tema della GUI, icone, caratteri, ...)
  • Devi ricostruire e ricaricare l'intero oggetto in GPU dopo ogni modifica.
  • Ogni widget deve essere in grado di produrre il proprio pezzo di geometria che è più difficile da astrarre rispetto alla pittura 2D.
  • Su alcune GPU è possibile eseguire il rendering di materiale 2D (riempimento dell'area con colori, copia da immagine a immagine, ...) con comandi 2D più veloce rispetto all'utilizzo della pipeline 3D.

Se lo si suddivide in più oggetti, alla fine si finisce con singoli o pochi rettangoli per oggetto. È più facile e veloce renderli senza oggetti memorizzati.

Quali framework della GUI tracciano quali parti della finestra sono state modificate e le ridipinge solo. La vecchia immagine è memorizzata nella cache della GPU. Questo approccio può essere utilizzato con vari back-end di disegno, non solo il rendering accelerato OpenGL / DirectX.

Se vuoi controllare l'esempio di una libreria della GUI che genera geometrie che puoi alimentare in OpengGL (o in diverse API 3D), guarda librocket . Può effettivamente fondere insieme le geometrie statiche e renderle in una sola chiamata, ma qualsiasi elemento che cambierà spesso o che avrà bisogno di renderizzare con il proprio shader deve rimanere separato.

    
risposta data 10.09.2015 - 13:18
fonte

Leggi altre domande sui tag