Sto provando a eseguire rendering sincronizzati verticali in modo che venga eseguito esattamente un rendering per sincronizzazione verticale, senza saltare o ripetere alcun frame. Avrei bisogno di questo per funzionare con Windows 7 e (in futuro) Windows 8.Come eseguire esattamente un rendering per sincronizzazione verticale (senza ripetere, senza saltare)?
Fondamentalmente consisterebbe nel disegnare una sequenza di QUADS
adatta allo schermo in modo che un pixel delle immagini originali corrisponda a 1: 1 a pixel sullo schermo. La parte di rendering non è un problema, sia con OpenGL o DirectX. Il problema è la sincronizzazione corretta.
Ho già provato ad utilizzare OpenGL, con l'estensione WGL_EXT_swap_control
, disegnando e quindi chiamando
SwapBuffers(g_hDC);
glFinish();
Ho provato tutte le combinazioni e le permutazioni di queste due istruzioni insieme a glFlush(), e non era affidabile.
Ho poi provato con Direct3D 10, disegnando e quindi chiamando
g_pSwapChain->Present(1, 0);
pOutput->WaitForVBlank();
dove g_pSwapChain
è un IDXGISwapChain*
e pOutput
è la IDXGIOutput*
associato a tale SwapChain.
Entrambe le versioni, OpenGL e Direct3D, hanno lo stesso risultato: La prima sequenza di, ad esempio, 60 fotogrammi, non dura quello che dovrebbe (invece di circa 1000ms a 60hz, dura qualcosa come 1030 o 1050ms), i seguenti sembrano funzionare bene (circa 1000.40 ms), ma ogni tanto sembra saltare un frame. Faccio la misurazione con QueryPerformanceCounter
.
Su Direct3D, provando un loop solo di WaitForVBlank, la durata di 1000 iterazioni è costantemente 1000.40 con poca variazione.
Quindi il problema qui non è sapere esattamente quando ciascuna delle funzioni chiamate restituisce e se lo scambio viene eseguito durante la sincronizzazione verticale (non prima, per evitare lo strappo).
Idealmente (se non sbaglio), per ottenere ciò che voglio, sarebbe eseguire un rendering, attendere fino all'avvio della sincronizzazione, scambiare durante la sincronizzazione, quindi attendere fino al termine della sincronizzazione. Come farlo con OpenGL o DirectX?
Edit: Un ciclo di prova di soli WaitForVSync
60x prende costantemente dal 1000.30ms a 1000.50ms. Lo stesso ciclo con Present(1,0)
prima dello WaitForVSync
, con nient'altro, nessun rendering, prende lo stesso tempo, ma a volte fallisce e prende 1017 ms, come se avesse ripetuto un frame. Non c'è rendering, quindi c'è qualcosa di sbagliato qui.
È disponibile anche in DX10? Sto creando il dispositivo con 'D3D10CreateDeviceAndSwapChain', che per quanto posso dire non ha alcun Parametro Presente. – slazaro
Ho paura che DX10 non abbia questa opzione. Scusate, non sono molto interessato a DX10. – miloszmaki
In realtà si desidera impostarlo anche: D3DPRESENT_INTERVAL_ONE ... e D3D10 esegue vsync attraverso il suo metodo attuale 'swapChain-> Present (vSync, 0);' – zezba9000