Ich schreibe ein Programm, das extrem niedrige Latenz Textur zum Bildschirm Streaming (unter 10ms) erfordert, habe ich dies mit GL_ARB_buffer_storage
, die gut funktioniert für das Streaming und vsync zu verhindern, dass reißen funktioniert.Verhindern OpenGL von Pufferrahmen
Allerdings habe ich entdeckt, dass die NVidia-Pipeline von 2 bis 8 Frames puffern wird, wenn sie Swap-Puffer aufrufen, bevor sie blockiert, muss ich dies verhindern.
Was ich getan habe ist folgendes:
uint64_t detectPresentTime()
{
// warm up first as the GPU driver may have multiple buffers
for(int i = 0; i < 10; ++i)
glxSwapBuffers(state.renderer);
// time 10 iterations and compute the average
const uint64_t start = microtime();
for(int i = 0; i < 10; ++i)
glxSwapBuffers(state.renderer);
const uint64_t t = (microtime() - start)/10;
// ensure all buffers are flushed
glFinish();
DEBUG_INFO("detected: %lu (%f Hz)", t, 1000000.0f/t);
return t;
}
Dann in der Zugfaden ich folgendes tun:
uint64_t presentTime = detectPresentTime();
if (presentTime > 1000)
presentTime -= 1000;
while(running)
{
const uint64_t start = microtime();
glClear();
// copy the texture to the screen
glxSwapBuffers();
const uint64_t delta = microtime() - start;
if (delta < presentTime)
{
glFlush();
usleep(delta);
glFinish();
}
}
Diese Lösung funktioniert auf NVidia Hardware, sondern wird berichtet, dass kein berechnen richtige Gegenwart auf AMD GPUs.
Gibt es einen besseren Weg, dies zu tun? Ich weiß, dass glFinish
normalerweise nicht in einer Anwendung mit Ausnahme von Profiling verwendet werden sollte, aber ich kann keinen anderen Weg finden, um sicherzustellen, dass die GPU-Pipeline Frames nicht puffert.
Edit: Für diejenigen, die dies interessiert effektiv emuliert FastSync unter Linux, aber ohne Vsync zu deaktivieren.
Edit2: Vielleicht ist die gegenwärtige Zeit Funktion sollte etwas anders implementiert werden:
uint64_t detectPresentTime()
{
glFinish();
// time 10 iterations and compute the average
const uint64_t start = microtime();
for(int i = 0; i < 10; ++i)
{
glxSwapBuffers(state.renderer);
glFinish();
}
const uint64_t t = (microtime() - start)/10;
DEBUG_INFO("detected: %lu (%f Hz)", t, 1000000.0f/t);
return t;
}
Die OpenGL Wiki einen interessanten Artikel über diese hat: https://www.khronos.org/opengl/wiki/Swap_Interval – bernie