Как сделать ровно один рендеринг на вертикальную синхронизацию (без повторов, без пропусков )?

Я пытаюсь выполнять рендеринг с вертикальной синхронизацией, чтобы на каждую вертикальную синхронизацию выполнялся ровно один рендеринг, без пропуска или повторения каких-либо кадры. Мне нужно, чтобы это работало под 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?

Редактировать: Тестовый цикл всего WaitForVSync60-кратного последовательно занимает от 1000,30 мс до 1000,50 мс. Тот же цикл с Present(1,0)до WaitForVSync, ни с чем другим, без рендеринга, занимает столько же времени, но иногда дает сбой и занимает 1017 мс, как будто повторил кадр. Рендера нет, так что тут что-то не так.

11
задан slazaro 8 May 2012 в 15:29
поделиться