1
\$\begingroup\$

I have an application that utilizes Direct3D 9 to render 3D graphics. I'm trying to manually control the number of frames rendered in a given second. Here is pseudocode:

while( bInGame )
{
    // handle window stuff
    dispatchEvents();

    // handle d3d9 stuff
    if( !windowMessages )
    {
        // process animation
        OnD3D9FrameMove(GetElapsedTime());

        // when work is done render a frame (30 frames per second)
        while(GetElapsedTime() < 0.03333333f){ Thread.Sleep(1); }
    }
}

The above code is very rough but explains what I'm trying to do. I want to allow time between frames to process work( i.e. visibility, animation, etc. ). The actual code works well except for one problem. Screen anomalies occur due to rendering frames out of sync with the screen's refresh rate. The anomalies are best described as horizontal tearing, an undesirable result.

When I activate vsync while using this code the screen anomalies do not appear. However, I can't use vsync because it prevents my game loop from continuing until the frame is rendered and thus consumes the spare time that I would like to set aside for work.

How can I get around this problem? I would like to sync with the monitor using my application rather than the Direct3D API. This way I can control the work flow...Any ideas?

\$\endgroup\$
  • \$\begingroup\$ "I want to allow time between frames to process work( i.e. visibility, animation, etc. )." - surely VSync shouldn't stop multithreading? also, any reason why you can't do that work before calling Present()? \$\endgroup\$ – snake5 Jul 5 '15 at 17:09
1
\$\begingroup\$
fixedTimeStep = false; //wide-open throttle
vsync = false;         //wide-open throttle

void OnD3D9FrameMove(float elapsedSeconds)
{
   Update(elapsedSeconds); //every frame
   static float oneFrameTime = (1.0f / 30);
   static float renderTime;
   renderTime += elapsedSeconds;
   if (renderTime >= oneFrameTime)
   {
      Render(renderTime); //All at once; skip animation frames after lag
      renderTime = 0;
      //Render(oneFrameTime); //Render exactly one frame's-worth of time
      //renderTime -= oneFrameTime; //But will render every frame to get caught up
   }
}

And avoid sleep(), obviously.

\$\endgroup\$
  • \$\begingroup\$ the code you supplied is great but i decided to use vsync with triple buffering. no other way to account for horizontal tearing. \$\endgroup\$ – P. Avery Apr 7 '15 at 23:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.