Perché i pixel shader non ci consentono di leggere direttamente dal framebuffer o dal buffer di profondità?


18

Consentirmi di campionare il framebuffer o il depthbuffer nel pixel shader sarebbe una funzione estremamente utile. Sarebbe utile anche solo essere in grado di conoscere la profondità o il colore di tutto ciò che è dietro il pixel corrente.

Perché sia ​​OpenGL che DirectX non mi permettono di farlo? Mi aspettavo che ci fosse una sorta di limitazione hardware, ma la fusione alfa usa il colore nel framebuffer per i calcoli di fusione, e il test Z campiona il buffer di profondità nella posizione corrente. Perché non esporre questi valori direttamente a noi? Posso sperare di vederlo in futuro?

Risposte:


20

Esso è una limitazione hardware. Il framment shader fa parte della pipeline programmabile, ma la fusione del colore finale con il / i buffer / i target non è programmabile in hardware ampiamente disponibile / merce a questo punto (è configurabile tramite stati di fusione, ma non è possibile scrivere arbitrariamente codice che sostituisce le operazioni di fusione integrate delle GPU).

Il motivo per cui l'hardware non è costruito per questo probabilmente ha a che fare con il fatto che le GPU sono massicciamente parallele; elaborano molti frammenti alla volta. Alcuni di questi frammenti possono in definitiva interagire tra loro all'interno dei buffer di destinazione, ma a causa della natura asincrona dell'elaborazione dei frammenti non è possibile sapere come fino a dopo che il frammento è stato elaborato e il colore finale è stato emesso ... succede sempre in modo deterministico.

Solo perché il pixel A sarà dietro il pixel B nel fotogramma finale non significa che il pixel A completerà sempre l'elaborazione dei frammenti e verrà scritto nella destinazione prima di B, specialmente su più fotogrammi di rendering. Quindi il valore letto dal buffer di destinazione durante l'elaborazione del pixel B non sarà sempre il pixel A, a volte saranno i valori chiari.

Quindi sospetto che non consentire le letture del buffer di destinazione diretto durante la fase del frammento abbia molto più a che fare con l'arresto del programmatore di shader dal spararsi nel piede ottenendo risultati potenzialmente non deterministici da quella lettura piuttosto che da qualsiasi effettiva limitazione tecnica nel rendere completamente la fase di fusione- programmabile. Mantenendo le operazioni di lettura strettamente controllate (il test di profondità, ad esempio), la GPU assicura che le operazioni eseguite con il valore di lettura abbiano un senso.

Detto questo, potrebbe esserci anche un rapporto costi / benefici. Rendere programmabile quell'aspetto della pipeline GPU complicherebbe un po 'la progettazione del chip e la necessità / domanda di letture del buffer di destinazione è stata relativamente bassa rispetto ad altre funzionalità.


Solo per approfondire questo, la ragione storica per cui l'accesso al framebuffer è stata lenta è perché le istruzioni sono pipeline molto pesantemente. Ottenere l'accesso a un determinato pixel framebuffer comporterebbe lo stallo della pipeline corrente fino a quando tutte le altre pipeline non fossero scaricate per completare qualsiasi rendering rilevante per il pixel interrogato. Anche nel caso strano di una GPU completamente non parallela, continueresti a svuotare l'intera pipeline per ogni query, il che è solo una cattiva idea. Senza dubbio le cose sono un po 'diverse nel mondo dell'hardware programmabile ora, ma mi aspetto che si applichi un principio simile.
Kylotan,

4

Sebbene fastidioso, offre ai produttori di hardware la flessibilità di ottimizzare il processo di rendering in numerosi modi e trasparenti.

Ad esempio, l'hardware PowerVR (sicuramente usato per tornare indietro nel tempo, non usato per molto tempo) aspetta fino a quando non viene inviata l'intera scena da sottoporre a rendering, quindi esegue l'ordinamento automatico della profondità usando l'algoritmo pittori e non è necessario generare un buffer di profondità. Dividerebbe lo schermo in tessere e le renderebbe ognuna a turno.


4

Il pixel shader non può leggere dai buffer di colore e profondità perché:

I pixel A e B possono essere ombreggiati esattamente nello stesso momento dell'hardware, anche se alla fine B viene visualizzato sopra ("dopo") il pixel A.

Se lo hai fatto in modo che l'hardware sia garantito per ombreggiare A prima di B, allora parti dell'hardware resterebbero in giro senza fare nulla mentre A è in ombra, e quindi parti dell'hardware starebbero in giro senza fare nulla mentre B è in ombra.

Nel peggiore dei casi immaginabile, tutti i pixel ombreggiati vengono visualizzati uno sopra l'altro e le migliaia e migliaia di thread GPU - tutti tranne uno - rimangono inattivi. Questo thread ombreggia pazientemente il pixel A, quindi B, quindi C ...

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.