Perché non utilizzare GDI per riempire più volte una finestra con i dati RGB da un array?

StackOverflow https://stackoverflow.com/questions/4128441

Domanda

Questo è un follow-up a questa domanda . Attualmente sto scrivendo un gioco semplice e sto cercando il modo più veloce per (più volte) visualizzare una serie di dati RGB in una finestra Win32, senza sfarfallio o altri artefatti.

Diversi approcci differenti sono stati consigliati nelle risposte alla domanda precedente, ma non c'era consenso su quale sarebbe stato il più veloce. Così, ho buttato insieme un programma di test. Il codice visualizza semplicemente un framebuffer sullo schermo ripetutamente, il più velocemente possibile.

Questi sono i risultati che ho ottenuto, per i dati a 32 bit in esecuzione in modalità video a 32 bit - che possono sorprendere qualcuno:

- Direct3D (1):             500 fps
- Direct3D (2):             650 fps
- DirectDraw (3):          1100 fps
- DirectDraw (4):           800 fps
- GDI (SetDIBitsToDevice): 2000 fps

Alla luce di queste cifre:

  • Perché sono molte persone fermamente convinto che GDI è semplicemente troppo lento per questa operazione?
  • C'è qualche motivo per preferire DirectDraw o Direct3D oltre SetDIBitsToDevice?

Ecco un breve riassunto delle chiamate effettuate da ciascuno dei codepaths diretta *. Se qualcuno conosce un modo più efficiente di utilizzare DirectDraw / Direct3D, si prega di commento.

1. CreateTexture(D3DUSAGE_DYNAMIC, D3DPOOL_DEFAULT);
       LockRect(); memcpy(); UnlockRect(); DrawPrimitive()

2. CreateTexture(0, D3DPOOL_SYSTEMMEM); CreateTexture(0, D3DPOOL_DEFAULT);
       LockRect(); memcpy(); UnlockRect(); UpdateTexture(); DrawPrimitive()

3. CreateSurface(); SetSurfaceDesc(lpSurface = &frameBuffer[0]);
       memcpy(); primarySurface->Blt();

4. CreateSurface();
       Lock(); memcpy(); Unlock(); primarySurface->Blt();
È stato utile?

Soluzione

Ci sono un paio di cose da tenere a mente qui. Prima di tutto, un sacco di "conoscenza comune" si basa su alcuni fatti che non si applicano più davvero.

Nei giorni di AGP, quando la CPU ha parlato direttamente alla GPU, è sempre utilizzato il protocollo di base PCI, che è accaduto al tasso "1x" (sempre e inevitabilmente). AGX 2x / 4x / 8x solo applicata quando la GPU stava prendendo per il memoria del controllore direttamente. In altre parole, a seconda del quando si guardava, era fino a 8 volte più veloce per avere il carico della GPU una texture dalla memoria come è stato per la CPU di inviare gli stessi dati direttamente alla GPU. Naturalmente, la CPU ha avuto anche una grande quantità maggiore larghezza di banda di memoria rispetto al bus PCI supportato.

Quando le cose passati a PCI-E, tuttavia, che ha cambiato completamente. Mentre ci possono essere differenze di larghezza di banda a seconda del percorso, non c'è una regola generale che Memory-> GPU sarà più veloce di CPU-> GPU. Quello generalizzazione di quella (per lo più) sicuro è che se si ha una scheda grafica dedicata, quindi la GPU sarà quasi sempre maggiore larghezza di banda per la memoria sulla scheda grafica di quanto non faccia nella memoria principale sulla scheda madre .

Nel tuo caso, che non importa molto se - si sta parlando di spostamento di dati dallo spazio CPU alla GPU spazio a prescindere. La differenza di velocità principale con l'utilizzo di DirectX (o OpenGL) succede quando si mantiene tutto (o quasi) del calcolo sulla GPU, ed evitare di utilizzare la CPU (o la memoria principale) a tutti. Loro non lo fanno (ora che AGP è storia) forniscono un miglioramento sostanziale nella memoria-> larghezza di banda di visualizzazione.

Altri suggerimenti

Jerry Coffin rende alcuni punti buoni. La cosa da tenere a mente è quello che il DI è sinonimo di in SetDIBitsToDevice. E 'l'acronimo di Device Independent. Il che significa che erano sempre in balia di autisti. Alcuni driver usato per essere completa spazzatura e ha interessato le prestazioni in maniera massiccia. DirectDraw sofferto di problemi simili, come pure ... ma si doveva anche l'accesso alle blitter hardware così è stato generalmente più utile. IHV anche la tendenza a mettere più tempo per la scrittura di driver corretti per DirectDraw a causa della sua associazione di gioco. Chi vuole essere il fondo della pila prestazioni quando l'hardware è perfettamente in grado di fare meglio?

In questi giorni molte schede grafiche possono accettare i bit di dati direttamente in modo che nessun conversione avviene. Se si ha bisogno di essere swizzled questo è anche incredibilmente veloce in questo giorno ed età.

La ragione le prestazioni Direct3D è così terribile, in confronto, è che Direct3D, dalla natura del fatto che è pensato per essere utilizzato totalmente internamente per la GPU, utilizza formati strani e complessi per migliorare le prestazioni della cache e così via.

Coppia che con il fatto che non si sta verificando come per come (con DDraw e D3D) creando una trama / superficie, bloccandolo, copiando, sbloccando quindi disegnare il buffer posteriore (tramite vari metodi). Per ottenere migliori prestazioni si sarebbe migliore fuori bloccando direttamente il backbuffer utilizzando un blocco DISCARD poi memcpy'ing direttamente nel buffer restituito prima di sblocco. Questo porterà le prestazioni molto più vicino alla SetDIBitsToDevice. Mi aspetterei ancora D3D di essere più lento di DDraw, tuttavia, per le ragioni sopra esposte.

La ragione si sente la gente Trounce su GDI è che ha usato per essere solo chiamate vecchie API di Windows. Le versioni più recenti di esso (che sono stati chiamati GDI + ultima volta che ho guardato em) sono in realtà solo un'API posto sulla cima di chiamate DirectX. Quindi, utilizzando GDI può sembrare abbastanza semplice programmazione saggia, a volte, ma l'aggiunta di uno strato tra le cose rallenta sempre le cose. Come accennato nella risposta da Jerry Coffin, i tuoi esempi sono di spostare i dati, e che è il tempo lento. Sono un po 'sorpreso che DirectX è che molto più lento se, ma non posso essere molto più aiuto con fuori scavando attraverso la documentazione di DirectX (che è stato abbastanza impressionante per un bel po' di tempo davvero .. Potrebbe voler controllare www.codesampler.com . ho sempre trovato bene a partire luoghi da lui e in realtà, mentre posso essere pazzo per dire questo, io giurerei i miglioramenti al DirectX SDK nel doc e gli esempi sono stati fatti sulla base di questo lavoro ragazzi!)

Per quanto riguarda il DirectDraw vs Direct3D (e non le chiamate GDI) discussione. Io direi di andare a Direct3D. Credo DirectDraw è stato deprecato dal 8.0 o giù di lì, e 9,0 è stato intorno per un po 'lungo abbastanza. E alla fine della giornata tutti DirectX è 3D, varia solo a livello di API 2D utili che sono in giro, ma si possono trovare si possono fare alcune cose molto interessanti in un ambiente 2D, quando in realtà si sta utilizzando spazio 3D. (Avevo un piuttosto pulito un'arma fulmine generato in modo casuale per un clone space invaders in una sola volta:))

Anywho, spero che questo ha aiutato!

PS: Va notato che DirectX non è sempre il più veloce. Per l'input da tastiera (a meno che questo è cambiato in 10 o 11) si è quasi sempre stato raccomandato di utilizzare gli eventi di Windows .. come DirectInput era in realtà solo un wrapper per quel sistema .. XInput però è -awesome -! !!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top