В рамках оптимизации моего движка 3D-игры/моделирования я пытаюсь сделать движок самооптимизирующимся.
Собственно, мой план таков. Во-первых, заставьте движок измерять количество циклов процессора на кадр. Затем измерьте, сколько циклов ЦП потребляют различные подсистемы (мин., среднее, макс.).
Учитывая эту информацию, всего в нескольких конкретных точках цикла кадра механизм может оценить, сколько «дополнительных циклов ЦП» у него есть для выполнения «дополнительной обработки», которую эффективно выполнять сейчас (соответствующие данные сейчас находятся в кэше). ), но в противном случае может быть отложено до какого-то следующего кадра, если текущему кадру угрожает нехватка циклов ЦП.
Идея состоит в том, чтобы как можно дальше опережать игру по черновой работе, чтобы каждый возможный цикл ЦП был доступен для обработки «требовательных кадров» (например, «множество столкновений в одном кадре»), которые можно было бы обработать без отказа вызвать glXSwapBuffers( ) успеть поменяться бэк/фронт буферами до самого позднего возможного момента для vsync).
Приведенный выше анализ предполагает, что замена заднего/переднего буферов является фундаментальным требованием для обеспечения постоянной частоты кадров. Я видел утверждения, что это не единственный подход, но я не понимаю логики.
Я зафиксировал время тактового цикла 64-битного ЦП непосредственно до и после glXSwapBuffers(), и обнаружил, что кадры различаются примерно на 2 000 000 тактовых циклов! По-видимому, это связано с тем фактом, что glXSwapBuffers() не блокируется до vsync (когда он может обмениваться буферами), а вместо этого немедленно возвращается.
Затем я добавил glFinish() непосредственно перед glXSwapBuffers(), что уменьшило вариацию примерно до 100 000 тактов ЦП... но затем glFinish() заблокировало где-то от 100 000 до 900 000 тактов ЦП (предположительно, в зависимости от того, как много работает драйвер nvidia). должен был завершиться, прежде чем он мог поменять местами буферы). С такими различиями в том, сколько времени может потребоваться glXSwapBuffers() для завершения обработки и замены буферов, мне интересно, есть ли надежда на какой-либо «умный подход».
Суть в том, что я не уверен, как достичь своей цели, которая кажется довольно простой и, похоже, не требует слишком многого от базовых подсистем (например, драйвер OpenGL). Тем не менее, я все еще вижу около 1 600 000 циклов изменения «времени кадра», даже с glFinish() непосредственно перед glXSwapBuffers(). Я могу усреднить измеренные частоты «тактовых циклов ЦП на кадр» и предположить, что среднее значение дает фактическую частоту кадров, но с таким большим разбросом мои вычисления могут на самом деле заставить мой движок пропускать кадры, ошибочно предполагая, что он может зависеть от этих значений.
Я буду признателен за любое понимание специфики различных задействованных функций GLX/OpenGL или общих подходов, которые могут работать на практике лучше, чем то, что я пытаюсь сделать.
PS: Тактовая частота процессора моего процессора не меняется, когда ядра замедляются или ускоряются. Следовательно, это не источник моей проблемы.