La modifica di una trama (dipingendo su di essa) è considerata un "cambiamento di stato"?


11

La convenzione nella grafica è che eseguire meno cambi di stato è meglio che eseguire più cambi di stato (commutazione di shader, buffer di associazione, trame di associazione, ecc.) Per le trame, è più veloce il rendering di molti poligoni usando un singolo atlante (per il rendering di sprite / testo) piuttosto che legare individualmente una nuova trama per ciascun poligono.

Questo è vero se continuo a dipingere su una trama via glTexSubImage2D? Ho un flusso di dati in arrivo (su una rete) che viene sottoposto a elaborazione e viene quindi dipinto su una trama una riga alla volta. I dati sono presentati visivamente in una pergamena infinita.

Sarebbe meglio dipingere su una trama renderizzata su un grande rettangolo (facendo scorrere i dati dipinti in vista)? L'idea qui è che avrei legato una (o due) trame in un dato momento mentre continuavo a dipingerlo.

O dovrei dipingere un sacco di piccoli rettangoli (rivelando il rettangolo solo quando la pittura è finita)? Presumo che legherei una trama per rettangolo.

Risposte:


11

L'aggiornamento di un'area di memoria nel dispositivo grafico (una trama, un buffer e simili) non equivale a cambiare uno stato di rendering.

Ciò che rende costoso un cambiamento dello stato di rendering è la quantità di lavoro che il driver deve fare per convalidare i nuovi stati e riordinare la pipeline. Molto probabilmente ciò comporterà anche una certa sincronizzazione tra CPU e dispositivo grafico. Tuttavia, la quantità di dati trasferiti tra i dispositivi dovrebbe essere piccola per un cambio di stato (probabilmente solo alcuni comandi).

Per un aggiornamento texture / buffer, d'altra parte, il costo principale risiede nel trasferimento dei dati stesso. In teoria, a meno che non si rileggano i dati di trama sulla CPU dopo l'aggiornamento, non dovrebbero esserci sincronizzazioni o blocchi della pipeline. Tuttavia, è necessario considerare un altro aspetto: sovraccarico dell'API. Anche se la quantità di dati che stai inviando al dispositivo grafico è piccola, se lo fai abbastanza spesso, alla fine il costo della comunicazione con il driver / dispositivo diventerà maggiore del costo del trasferimento dei dati. Questo è un altro motivo per cui il batch è così importante quando si ottimizza un renderer.

Quindi nel tuo caso, l'approccio migliore, a mio avviso, sarebbe quello di mantenere una copia della memoria di sistema della trama che aggiorni ogni volta che arrivano nuovi dati. Imposta un flag sporco e consolida il maggior numero possibile di aggiornamenti in uno glTexSubImageper l'intera trama (o una grande porzione sequenziale di esso). Puoi anche giocare con Pixel Buffer Objects e provare a eseguire il trasferimento di dati asincrono per ridurre il più possibile le bancarelle della pipeline. Se è possibile implementare un tipo di doppio buffering, è possibile scrivere su una copia della trama mentre viene eseguito il rendering dell'altra. Questo tutorialesplora quello scenario. Questo è il mio approccio intuitivo, proverei a ridurre il numero di chiamate API e "raggruppare" gli aggiornamenti delle trame. Detto questo, questo è molto speculativo e dovresti profilarlo e confrontarlo con altri approcci, come fare diversi piccoli aggiornamenti, per sapere con certezza qual è il più performante nel tuo caso d'uso.

Come nota a margine, anche questa presentazione di NVidia è rilevante e fornisce molte buone intuizioni: avvicinarsi a Zero Driver Overhead in OpenGL .


5
Non lo so per certo, ma sospetterei sicuramente che glTexSubImage su una trama che è stata renderizzata nell'ultimo fotogramma o due bloccherà la pipeline, poiché i driver del PC spesso provano a bufferizzare un fotogramma o due e non è probabile voler fare copie di intere trame a causa di un piccolo aggiornamento. Quindi mi aspetterei un doppio o triplo buffering delle trame (o oggetti buffer pixel) necessari per la massima prestazione.
John Calsbeek,
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.