API grafiche di basso livello multipiattaforma


11

Quando si crea un'astrazione del sistema è meglio avere la piattaforma diverse API nascoste da un'interfaccia comune al livello più basso che abbia senso.

Tenendo conto delle diverse API grafiche native moderne (senza pipeline a funzione fissa): OpenGLES 2.0+, OpengGL 3.0+, DirectX 10.0+, Xbox DirectX 9, LibGCM

Se si volesse creare un'API grafica di basso livello senza stato per sedersi al di sopra di tutti, quale sarebbe il modo migliore per renderlo il più sottile e veloce possibile?


Il requisito per l'API di essere apolide è interessante. OpenGL, ad esempio, è stateful, e penso che un'API stateless che lo avvolga avrebbe senso solo se fosse di livello molto più alto, quindi non dovrebbe, ad esempio, spingere e far apparire le stesse matrici per ogni singolo superficie che rende.
SpoonMeiser,

Evitare inutili cambiamenti di stato potrebbe comunque essere implementato a un livello superiore, ad esempio ordinando le chiamate di rendering in base al loro stato prima di inviarle al dispositivo. E impostando lo stato solo se è diverso da quello attuale.
Notturno Dragon

Questo non è apolide però. Forse mi sbaglio, ma quello che penso quando penso allo apolide è un'API in cui ogni chiamata non dipende affatto dalle chiamate precedenti. Ciò significa che qualsiasi informazione che verrebbe normalmente memorizzata nello stato da qualche parte deve essere passata in ogni chiamata che necessita di tali informazioni. Per OpenGL, ad esempio, si tratterebbe di matrici nello stack, illuminazione, z-buffering e opzioni di normalizzazione.
SpoonMeiser,

Sì, per ogni richiamo di cui hai bisogno, i dati mesh, lo stato di fusione, le trame da associare, gli stati di campionamento ecc. Le ottimizzazioni potrebbero essere fatte in seguito, senza modificare l'API. O forse sto leggendo il tuo commento in modo sbagliato ..
NocturnDragon

Risposte:


6

Il livello più basso che ha senso dal mio punto di vista è qualcosa che parla delle risorse coinvolte nel rendering - vb / ib, rendering superfici, trame, shader, blocchi di stato, ecc.

Il problema qui è che alcuni di questi devono essere in diversi formati, a seconda dell'API: è qui che diventa un po 'complicato. Il modo più semplice per aggirarlo è pre-elaborare le risorse statiche per la rispettiva API. Per quelli dinamici, usa solo shader per generarli, il che rende abbastanza semplice rimanere nei formati nativi.

Tutto ciò che fai quindi a livello superiore è impostare pipeline con risorse collegate e consegnarle alla GPU. Scoprirai che non tutto può essere estratto in modo gradevole in quel modo, specialmente se approfitti di trucchi specifici dell'hardware. Ma è un buon inizio.

(Sidenote: se tratti i trucchi specifici della piattaforma come un tipo speciale di risorsa, puoi spingere questo concetto abbastanza lontano.)

Quindi, in un certo senso, creerai due cose: un gestore risorse hardware, oltre a un kit di strumenti per impostare un DAG di queste risorse.


Non ho mai pensato di trattare le cose specifiche della piattaforma come risorse. Sembra un'ottima idea! Grazie.
Notturno Dragon

10

Data l'ampia gamma di API che si desidera trattare, è probabile che l'approccio di wrapping tipico sia inefficiente e soggetto a difficoltà nella mappatura dei concetti API su diverse altre API che potrebbero o meno supportare determinate funzioni a vari livelli.

Di conseguenza, l'approccio più sensato sarebbe quello di creare un'API incentrata sulle funzionalità . Mentre questo approccio impedisce all'utente API di utilizzare tutte le funzionalità disponibili, semplifica notevolmente l'implementazione di ciascun back-end e consente ottimizzazioni specifiche del back-end che altrimenti non sarebbero possibili.

Inoltre semplifica notevolmente la gestione di funzionalità non supportate per l'utente API; non devono più controllare se esiste la funzione X e determinare quali funzionalità sono interessate, ma devono solo interrogare la funzione stessa per vedere se è supportata con la configurazione corrente. Anche se si supportano modalità parziali o limitate per le funzionalità, il contesto fornito semplifica notevolmente la gestione.

In termini di creazione di un renderer senza stato (noto anche come basato su invio ), in genere viene utilizzata una chiave a 64 bit per comprimere e inviare comandi per il rendering. Da quel momento c'è una grande flessibilità in termini di come eseguire i comandi e quali informazioni inviare a seconda delle caratteristiche e capacità che si desidera supportare.


Questa è in realtà una buona idea. Ed è parte del progetto che sto cercando di creare, ma quello che avevo in mente era implementare queste funzionalità su un'API comune di basso livello. Ma potrebbe essere il caso che per alcune funzionalità avresti ancora bisogno di approfondire l'API nativa per alcuni casi più particolari.
NocturnDragon,

Parte dell'idea è quella di evitare la creazione di un'API comune di basso livello e di dover affrontare il wrapping con un approccio con il minimo comune denominatore. Spostando il livello di astrazione di un livello, restringi un po 'il set di funzionalità, ma ottieni anche la possibilità di sfruttare ciascuna piattaforma. Per gestire la necessità occasionale di un accesso più profondo, preferisco fornire un'intestazione che esponga le intestazioni della piattaforma e alcuni helper interni; potrebbe interrompere la versione in versione, ma è lì se ne hai bisogno.
Jason Kozak,

1

Per cominciare, ogni API fa le cose in modo diverso, quindi dovrebbe essere ovvio che il confezionamento di tutte le API di cui sopra sarebbe difficile. Detto questo, a volte è necessario farlo: ad un certo punto un gioco deve semplicemente funzionare su più di una piattaforma indipendentemente da quanto sia difficile farlo.

Penso che il modo migliore per farlo sia quello di inventare le funzionalità che possono essere implementate su tutte le API sottostanti e astrarre questo e solo quello. Se stai sviluppando un gioco multipiattaforma, non implementeresti ogni oscura funzionalità supportata da ciascuna API, implementeresti solo ciò di cui hai bisogno. Questo aiuta anche a mantenere l'API piccola e veloce.

Per evitare che il disordine dell'implementazione di ciascuna API diversa venga impacchettato nell'output, la compilazione deve essere eseguita con file di intestazione neutri della piattaforma e file di codice specifici della piattaforma. Quindi, il file di codice specifico per la piattaforma di destinazione sarebbe l'unico compilato mantenendo l'API piccola.



-4

Potresti voler dare un'occhiata alla libreria SDL o Allegro . Entrambe sono librerie di giochi di basso livello e altamente portatili, che hanno un modo per collegarle in un contesto OpenGL in modo da poter eseguire il rendering della grafica lì. SDL ha la fama di essere stato usato dal defunto Loki Games per portare alcuni giochi popolari dagli anni 2000 a Linux, e Allegro ha molto tempo a disposizione e ha una grande comunità di sviluppatori di giochi amatoriali.


4
Questo in realtà non risponde alla domanda, per non parlare del fatto che è possibile avvolgere sia OpenGL che DirectX (vedi Ogre3D, Irrlicht, ecc.).
Jason Kozak,

Considera i giochi a cui hai giocato. Quanti di loro hanno opzioni per usare DirectX o OpenGL? Ecco quanti creano wrapper per le due librerie per essere in grado di supportare una delle due. Hai un'immaginazione limitata. :-P
Ricket,

Riconosco che ci sono alcuni giochi che ti consentono di scegliere se vuoi rendere la grafica con OpenGL o DirectX, ma la domanda riguarda un'API multipiattaforma, quindi penso che la risposta sia adeguata, modificherò il primo paragrafo, anche se.
chiguire,

1
la domanda riguarda un'API di livello basso stateless multipiattaforma. SDL e Allegro non hanno nulla a che fare con esso.
NocturnDragon,

@NocturnDragon - il titolo della domanda è un po 'fuorviante. A prima vista, mi aspettavo che la domanda riguardasse le scelte di API disponibili e presumo che anche questo risponditore lo abbia fatto.
a_m0d
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.