2014-06-24 153 views
3

我正在使用visual studio 2012,並想知道high_resolution_clock的準確性。std :: chrono :: high_resolution_clock和屏幕刷新率的準確性(不精確)

基本上我正在寫一些代碼來顯示聲音和圖像,但我需要它們很好地同步,並且圖像必須是無撕裂的。我使用directX提供無淚圖像,並使用high_resolution_clock在計時屏幕刷新。顯示器聲稱是60 fps,但是,high_resolution_clock的時序提供了60.035 fps的刷新率,平均超過10000次屏幕刷新。取決於哪一個是正確的,我的音頻會在一秒鐘後的0.5毫秒內結束,即一小時後約2秒。我希望任何時鐘都比這更準確 - 更像1秒鐘漂移一年,而不是一個小時。

有沒有人曾經看過這種東西。我應該期望我的聲卡時鐘再次變得不同嗎?

編輯 這是我的計時代碼。這個while循環在我的渲染線程中運行。 m_renderData是包含渲染場景所需數據的結構數組,每個屏幕都有一個元素。爲了測試我只在一個屏幕上運行,所以它只有一個chrono::high_resolution_clock沒有使用RDTSC元素

while(!TestDestroy()) 
{ 
    for(size_t i=0; i<m_renderData.size(); ++i) 
    { 
     //work out where in the vsync cycle we are and increment the render cycle 
     //as needed until we need to actually render 
     D3DRASTER_STATUS rStatus; 
     m_renderData[i].deviceD3D9->GetRasterStatus(0, &rStatus); 
     if(m_renderData[i].renderStage==inVBlankRenderingComplete) 
     { 
      if(!rStatus.InVBlank) 
       m_renderData[i].renderStage=notInVBlank; 
     } 
     else if(m_renderData[i].renderStage==notInVBlank) 
     { 
      if(rStatus.InVBlank) 
       m_renderData[i].renderStage=inVBlankReadyToRender; 
     } 

     //check for missing the vsync for rendering 
     bool timeOut=false; 
     if(m_renderData[i].durations.size()>0) 
     { 
      double timeSinceLastRender=std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now()-m_renderData[i].durations.back()).count(); 
      if (timeSinceLastRender>expectedUpdatePeriod*1.2) 
       timeOut=true; 

     } 

     if(m_renderData[i].renderStage==inVBlankReadyToRender || timeOut) 
     { 
      //We have reached the time to render 

      //record the time and increment the number of renders that have been performed 
      m_renderData[i].durations.push_back(std::chrono::high_resolution_clock::now()); 
      ++m_renderData[i].nRenders; 

      //we calculate the fps using 10001 times - i.e. an interval of 10000 frames 
      size_t fpsUpdatePeriod=10001; 
      if(m_renderData[i].nRenders<fpsUpdatePeriod) 
      { 
       //if we don't have enough times then display a message 
       m_renderData[i].fpsString = "FPS: Calculating"; 
      } 
      else 
      { 
       //we have enough timing info, calculate the fps 
       double meanFrameTime = std::chrono::duration_cast<std::chrono::microseconds>(m_renderData[i].durations.back()-*(m_renderData[i].durations.end()-fpsUpdatePeriod)).count()/double(fpsUpdatePeriod-1); 
       double fps = 1000000.0/meanFrameTime; 
       saveFps(fps); 
      } 

      //render to the back buffer for this screen 
      renderToBackBuffer(i); 

      //display the back buffer 
      if(!TestDestroy()) 
       m_renderData[i].deviceD3D9->Present(NULL, NULL, NULL, NULL); 
      //make sure we render to the correct back buffer next time 
      m_renderData[i].bufferToRender--; 
      //update the render cycle 
      m_renderData[i].renderStage=inVBlankRenderingComplete; 
     } 
    } 
} 
+0

你賠償了時鐘漂移嗎? (即確保你設置你的截止日期相對於最後期限,而不是當前時間) – Erbureth

+0

另請參閱:http://stackoverflow.com/questions/8386128/how-to-get-the-precision-of-high-resolution-時鐘和http://stackoverflow.com/questions/16299029/resolution-of-stdchronohigh-resolution-clock-doesnt-correspond-to-measureme(第二個問題的接受答案是關於MSVS2012) – Ilya

+0

大多數SO和其他帖子意味着C++ 11 chrono :: high_resolution_clock正在使用RDTSC/RDTSCP指令(未確認)。 MS關於高分辨率定時器的指導是改用QPC API(例如http://msdn.microsoft.com/en-us/library/windows/desktop/dn553408%28v=vs.85%29.aspx) – holtavolt

回答

0

不幸的是,在VS 2012和2013。這對於將來的VS版本是固定的。請參閱VS Connect。同時,使用QPC代替。

+0

RDTSC是不可靠的方法來測量時間,因此不應該用於此目的 – JarkkoL

+0

正確使用RDTSC是具有挑戰性的,這就是爲什麼我說過要使用QPC。 QPC唯一不可靠的時間就是沒有更新處理器驅動程序的Athlon 64 X2系統。 –

+0

那麼有沒有辦法使用RDTSC「正確」的時機。您處於CPU限制和可能的HW線程交換的擺佈之中。 QPC很好。 – JarkkoL