C'era una volta, quando> era più veloce di <… Aspetta, cosa?


280

Sto leggendo un fantastico tutorial su OpenGL . È davvero fantastico, fidati di me. L'argomento in cui mi trovo attualmente è Z-buffer. Oltre a spiegare di cosa si tratta, l'autore menziona che possiamo eseguire test di profondità personalizzati, come GL_LESS, GL_ALWAYS, ecc. Spiega anche che il significato effettivo dei valori di profondità (che è in alto e che non lo è) può anche essere personalizzato. Ho capito fino ad ora. E poi l'autore dice qualcosa di incredibile:

L'intervallo zNear può essere maggiore dell'intervallo zFar; se lo è, i valori dello spazio finestra verranno invertiti, in termini di ciò che costituisce il più vicino o il più lontano dallo spettatore.

In precedenza, si diceva che il valore Z dello spazio finestra di 0 fosse il più vicino e 1 fosse il più lontano. Tuttavia, se i nostri valori Z dello spazio clip fossero negati, la profondità di 1 sarebbe la più vicina alla vista e la profondità di 0 sarebbe la più lontana. Tuttavia, se invertiamo la direzione del test di profondità (da GL_LESS a GL_GREATER, ecc.), Otteniamo lo stesso risultato esatto. Quindi è davvero solo una convention. In effetti, capovolgere il segno di Z e il test di profondità era una volta un'ottimizzazione delle prestazioni vitale per molti giochi.

Se ho capito bene, dal punto di vista delle prestazioni, capovolgere il segno di Z e il test di profondità non è altro che cambiare un <confronto in un >confronto. Quindi, se ho capito bene e l'autore non sta mentendo o fare le cose, quindi modificando <ad >usato per essere un'ottimizzazione di vitale importanza per molti giochi.

L'autore sta inventando le cose, sto fraintendendo qualcosa o è davvero il caso che una volta <fosse più lento ( vitale , come dice l'autore) di >?

Grazie per aver chiarito questa questione piuttosto curiosa!

Dichiarazione di non responsabilità: sono pienamente consapevole che la complessità dell'algoritmo è la fonte primaria di ottimizzazioni. Inoltre, sospetto che oggigiorno sicuramente non farebbe alcuna differenza e non sto chiedendo questo per ottimizzare nulla. Sono solo estremamente, dolorosamente, forse proibitivamente curioso.


6
Il link a questo tutorial sembra essere (recentemente) morto. :(
TZHX

@TZHX: Poiché la risposta accettata è stata creata dall'autore del tutorial, speriamo di ritrovarla. Vedi il mio ultimo commento alla sua risposta :)
Armen Tsirunyan il

3
Il tutorial OpenGL di riferimento è disponibile qui .
Fons,

(a <b) è identico a (b> a), quindi non è assolutamente necessario implementare entrambe le operazioni di confronto nell'hardware. La differenza nelle prestazioni è il risultato di ciò che accade come risultato dell'operazione di confronto. Questa è una strada lunga e tortuosa da percorrere per spiegare tutti gli effetti collaterali, ma qui ci sono alcuni suggerimenti. I giochi utilizzati per riempire il buffer di profondità per evitare l'elaborazione di frammenti più costosa per i frammenti che non hanno superato il test di profondità. Quake usava dividere il range di profondità in due metà per evitare di cancellare il frame buffer perché il gioco riempiva sempre tutti i pixel sullo schermo e così via.
t0rakka,

2
@Fons sembra che il link sia morto, di nuovo :(
nalzok il

Risposte:


350

Se ho capito bene, dal punto di vista delle prestazioni, capovolgere il segno di Z e il test di profondità non è altro che cambiare un confronto tra <confronto con>. Quindi, se capisco correttamente e l'autore non sta mentendo o inventando cose, cambiare <in> era un'ottimizzazione vitale per molti giochi.

Non l'ho spiegato particolarmente bene, perché non era importante. Ho solo pensato che fosse un po 'di curiosità interessante da aggiungere. Non intendevo approfondire l'algoritmo in modo specifico.

Tuttavia, il contesto è la chiave. Non ho mai detto che un <confronto fosse più veloce di un> confronto. Ricorda: stiamo parlando di test di profondità dell'hardware grafico, non della tua CPU. Non operator<.

Quello a cui mi riferivo era una vecchia ottimizzazione specifica in cui un fotogramma da utilizzare GL_LESScon un intervallo di [0, 0,5]. Il fotogramma successivo, si esegue il rendering con GL_GREATERun intervallo di [1,0, 0,5]. Vai avanti e indietro, letteralmente "capovolgendo il segno di Z e il test di profondità" ogni fotogramma.

Questo perde un po 'di precisione di profondità, ma non è stato necessario cancellare il buffer di profondità, che una volta era un'operazione piuttosto lenta. Poiché la pulizia di profondità non è solo gratuita in questi giorni ma in realtà più veloce di questa tecnica, le persone non lo fanno più.


1
Il motivo per cui la cancellazione del buffer di profondità è più rapido in questi giorni ha due ragioni, entrambe basate sul fatto che la GPU utilizza un buffer di profondità gerarchico. Pertanto, è sufficiente deselezionare gli stati del riquadro su clear (che è veloce), modificando il segno di confronto della profondità, tuttavia, significa che è necessario svuotare l'intero buffer HiZ perché memorizza solo un valore minimo o massimo a seconda del segno di confronto.
Jasper Bekkers,

3
@NicolBolas: il commento di PerTZHX, il link al tuo tutorial nella mia domanda è morto. Potresti farci sapere dove sono spostati i tutorial e, facoltativamente, modificare la domanda, per favore?
Armen Tsirunyan,

2
I tutorial sono disponibili nell'archivio web. Se @NicolBolas lo consente, sarebbe utile per la community se potessimo spostarli in una posizione più accessibile. Forse GitHub o qualcosa del genere. web.archive.org/web/20150215073105/http://arcsynthesis.org/…
ApoorvaJ

3

La risposta è quasi certamente che per qualunque incarnazione di chip + driver sia stata usata, la Hierarchical Z ha funzionato solo in una direzione - questo era un problema abbastanza comune nel passato. L'assemblaggio / ramificazione di basso livello non ha nulla a che fare con esso - il buffering Z viene eseguito nell'hardware a funzione fissa ed è pipeline - non vi è alcuna speculazione e quindi nessuna previsione di diramazione.


0

Un'ottimizzazione del genere comprometterà le prestazioni su molte soluzioni grafiche integrate perché renderà meno efficiente la risoluzione del framebuffer. La cancellazione di un buffer è un chiaro segnale per il driver che non è necessario archiviare e ripristinare il buffer durante il binning.

Poche informazioni di base: un rasterizzatore di piastrellatura / binning elabora lo schermo in un numero di tessere molto piccole che si adattano alla memoria su chip. Ciò riduce le scritture e le letture su memoria esterna, riducendo il traffico sul bus di memoria. Quando un frame è completo (lo swap viene chiamato, oppure i FIFO vengono scaricati perché sono pieni, i collegamenti del framebuffer cambiano, ecc.) Il framebuffer deve essere risolto; questo significa che ogni cestino viene elaborato a sua volta.

Il driver deve presumere che i contenuti precedenti debbano essere conservati. La conservazione significa che il cestino deve essere scritto nella memoria esterna e successivamente ripristinato dalla memoria esterna quando il cestino viene nuovamente elaborato. L'operazione chiara indica al conducente che i contenuti del cestino sono ben definiti: il colore chiaro. Questa è una situazione banale da ottimizzare. Ci sono anche estensioni per "scartare" il contenuto del buffer.


-8

Ha a che fare con bit di flag in assembly altamente ottimizzati.

x86 ha entrambe le istruzioni jl e jg, ma la maggior parte dei processori RISC ha solo jl e jz (no jg).


2
Se questa è la risposta, solleva nuove domande. Il "ramo preso" è stato più lento del "ramo ignorato" sui primi processori RISC? Certamente non è così adesso in alcun modo misurabile per quanto ne so. Avresti dovuto scrivere forloop con un ramo incondizionato all'indietro e un ramo condizionato, portato raramente in avanti per uscire dal ciclo allora? Sembra imbarazzante.
Pascal Cuoq,

54
-1: questa domanda non ha nulla a che fare con le CPU . GL_LESS e GL_GREATER sono operazioni di confronto di profondità, che vengono eseguite su GPU.
Nicol Bolas,

8
Divertente quanto rappresentante puoi ottenere per una risposta corretta al titolo ma che ha ben poco a che fare con la vera domanda.
Giosuè,

7
+1 No, questa risposta è corretta per almeno una parte della domanda. La domanda è: "L'autore sta inventando le cose, sto fraintendendo qualcosa o è davvero il caso che una volta <era più lento (vitale, come dice l'autore) di>?". Sono disponibili tre opzioni. Questa risposta risponde alla possibilità dell'opzione 3. In nessun punto dell'articolo è la tecnologia della CPU / GPU fornita, né che deve essere una GPU (primi giochi 3D in cui la CPU). Ok ... Non credo che ci fossero molti giochi 3d su RISC :-)
xanatos,

3
(e il tag GPU è stato aggiunto alle 20:34. La prima revisione aveva solo il tag CPU. Questa risposta è stata scritta alle 18:44)
xanatos
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.