Я пытаюсь выполнять рендеринг с вертикальной синхронизацией, чтобы на каждую вертикальную синхронизацию выполнялся ровно один рендеринг, без пропуска или повторения каких-либо кадры. Мне нужно, чтобы это работало под Windows 7 и (в будущем )Windows 8.
В основном это будет состоять из рисования последовательности QUADS
, которая будет соответствовать экрану, чтобы пиксель из исходных изображений соответствует 1 :1 пикселю на экране. Часть рендеринга не является проблемой ни с OpenGL, ни с DirectX. Проблема в правильной синхронизации.
Раньше я пытался использовать OpenGL с расширением WGL_EXT_swap_control
, рисуя, а затем вызывая
SwapBuffers(g_hDC);
glFinish();
Я пробовал все комбинации и перестановки этих двух инструкций вместе с glFlush (), и это было ненадежно.
Затем я попытался использовать Direct3D 10, нарисовав и вызвав
g_pSwapChain->Present(1, 0);
pOutput->WaitForVBlank();
, где g_pSwapChain
— это IDXGISwapChain*
, а pOutput
— это IDXGIOutput*
, связанный с этой цепочкой обмена.
Обе версии, OpenGL и Direct3D, дают один и тот же результат. :Первая последовательность, скажем, из 60 кадров,не длится так, как должно (вместо примерно 1000 мс при 60 Гц, длится что-то вроде 1030 или 1050 мс ), следующие, похоже, работают нормально (около 1000,40 мс ), но время от времени кажется, пропускает кадр. Я делаю измерения с помощью QueryPerformanceCounter
.
В Direct3D при попытке выполнить цикл только из WaitForVBlank продолжительность 1000 итераций постоянно составляет 1000,40 с небольшими изменениями.
Так что проблема здесь в том, что мы не знаем точно, когда каждая из вызываемых функций возвращается, и выполняется ли подкачка во время вертикальной синхронизации (или раньше, чтобы избежать разрыва ).
В идеале (если я не ошибаюсь ), чтобы добиться того, чего я хочу, было бы выполнить один рендер, дождаться начала синхронизации, поменяться местами во время синхронизации, затем дождаться завершения синхронизации. Как это сделать с OpenGL или DirectX?
Редактировать:
Тестовый цикл всего WaitForVSync
60-кратного последовательно занимает от 1000,30 мс до 1000,50 мс. Тот же цикл с Present(1,0)
до WaitForVSync
, ни с чем другим, без рендеринга, занимает столько же времени, но иногда дает сбой и занимает 1017 мс, как будто повторил кадр. Рендера нет, так что тут что-то не так.