Спящий режим с высокой точностью, или Как освободить процессор и поддерживать точную частоту кадров

Я работаю над 2D-движком, у которого есть функция LimitFrameRate, чтобы игра не запускалась так быстро, что пользователь не может играть в нее. В этом игровом движке скорость игры привязана к частоте кадров. Так что обычно нужно ограничить частоту кадров примерно 60 кадрами в секунду. Код этой функции относительно прост: вычислите количество времени, оставшееся до того, как мы должны начать работу над следующим кадром, преобразуйте это в миллисекунды, спите на это количество миллисекунд (которое может быть 0), повторяйте, пока не будет ' ровно в нужное время, затем выходите. Вот код:

public virtual void LimitFrameRate(int fps)
{
  long freq;
  long frame;
  freq = System.Diagnostics.Stopwatch.Frequency;
  frame = System.Diagnostics.Stopwatch.GetTimestamp();
  while ((frame - previousFrame) * fps < freq)
  {
     int sleepTime = (int)((previousFrame * fps + freq - frame * fps) * 1000 / (freq * fps));
     System.Threading.Thread.Sleep(sleepTime);
     frame = System.Diagnostics.Stopwatch.GetTimestamp();
  }
  previousFrame = frame;
}

Конечно, я обнаружил, что из-за неточного характера функции сна в некоторых системах частота кадров оказывается совсем другой, чем ожидалось. Точность функции сна составляет всего около 15 миллисекунд, так что вы не можете ждать меньше этого. Странно то, что некоторые системы достигают идеальной частоты кадров с помощью этого кода и могут идеально достигать диапазона частот кадров. Но другие системы этого не делают. Я могу удалить функцию сна, и тогда другие системы достигнут такой же частоты кадров, но тогда они перегружают процессор.

Я читал другие статьи о функции сна:

Что делать кодеру? Я' m не запрашивает гарантированную частоту кадров (или, другими словами, гарантированное время сна), а просто общее поведение. Я хотел бы иметь возможность засыпать (например) 7 миллисекунд, чтобы передать некоторый процессор в ОС и заставить его обычно возвращать управление через 7 миллисекунд или меньше (при условии, что он вернет часть своего времени процессора), и если это займет чаще, это нормально. Итак, у меня следующие вопросы:

  1. Почему спящий режим работает идеально и точно в некоторых средах Windows, а не в других? (Есть ли способ добиться одинакового поведения во всех средах?)
  2. Как добиться в целом точной частоты кадров, не перегружая ЦП кодом C #?

5
задан Community 23 May 2017 в 12:23
поделиться