2016-08-01 2 views
4

Недавно я загрузил отличную версию «Minecraft in 500 lines» от flegman от https://github.com/fogleman/Craft. Я использовал инструмент 2to3 и исправил некоторые детали вручную, чтобы сделать его выполнимым в python3. Теперь я задаюсь вопросом о вызове self.clear() в методе рендеринга. Это мой модифицированный метод рендеринга, который называется каждый кадр pyglet:Python minecraft pyglet glClear() skipping frames

def on_draw(self): 
    """ Called by pyglet to draw the canvas. 

    """ 
    frameStart = time.time() 
    self.clear() 
    clearTime = time.time() 
    self.set_3d() 
    glColor3d(1, 1, 1) 
    self.model.batch.draw() 
    self.draw_focused_block() 
    self.set_2d() 
    self.draw_label() 
    self.draw_reticle() 
    renderTime = time.time() 

    self.clearBuffer.append(str(clearTime - frameStart)) 
    self.renderBuffer.append(str(renderTime - clearTime)) 

Как вы можете видеть, я взял время исполнения self.clear() и остальную часть методы визуализации. Вызов self.clear() вызовов этого метода pyglet, что можно найти в .../pyglet/окне/__ init__.py:

def clear(self): 
    '''Clear the window. 

    This is a convenience method for clearing the color and depth 
    buffer. The window must be the active context (see `switch_to`). 
    ''' 
    gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT) 

Так что я в основном делаю вызов glClear().
Я заметил некоторые капли кадров во время тестирования игры (при 60 FPS), поэтому я добавил вышеприведенный код для измерения времени выполнения команд, и особенно того, что один из glClear(). Я узнал, что сам рендеринг не занимает больше 10 мс. Но длительность glClear() это немного другая история, здесь распределение для 3 измерений в различных условиях:
Duration of glClear() under different conditions.

Линии пурпурной показывает предел времени кадра. Итак, все, что стоит за первой линией, означает падение кадра.
Время выполнения glClear() похоже, имеет какое-то «эхо» после истечения первого кадра. Можете ли вы объяснить мне, почему? И как я могу сделать вызов быстрее?
К сожалению, я не эксперт по OpenGL, поэтому я благодарен за каждый ребята. ;)

+1

Возможно, ваше разрешение таймеров составляет всего 16 мс, что объясняет «эхо». См. Https://docs.python.org/2/library/time.html#time.time, в котором говорится, что «не все системы обеспечивают время с лучшей точностью, чем 1 секунда». Попробуйте использовать другой таймер и посмотрите, не важно ли это. – TWT

ответ

0

Ваш график неверен. Ну, по крайней мере, это не подходящий график для измерения производительности. Никогда не доверяйте функции gl*, выполняемой при ее передаче, и никогда не доверяйте ей, чтобы она выполнялась так быстро, как вы ожидали.

Большинство gl* функции не выполняются сразу, их не могло быть. Помните, что мы имеем дело с GPU, говоря, что делать что-то прямо медленно. Итак, вместо этого мы записываем список дел (очередь команд) для графического процессора и выгружаем его в VRAM, когда действительно нужно, чтобы графический процессор выдавал что-то. Этот «дамп» является частью процесса, называемого синхронизацией, и мы можем запустить его с помощью glFlush. Хотя OpenGL удобен для пользователей (по крайней мере, по сравнению с, например, Vulkan), и поэтому он не полагается на нас, чтобы явно сбросить очередь команд. Многие функции gl*, которые в точности зависят от вашего графического драйвера, будут неявно синхронизировать состояние CPU и GPU, которое включает флеш.

С glClear обычно инициирует фрейм, возможно, ваш драйвер считает, что было бы хорошо выполнить такую ​​неявную синхронизацию. Как вы можете себе представить, синхронизация является очень медленным процессом и блокирует выполнение ЦП до его завершения.

И это, вероятно, то, что здесь происходит. Часть процесса синхронизации заключается в выполнении транзакций памяти (например, glBufferData, glTexImage*), которые, вероятно, находятся в очереди, пока они не покраснеют вашим вызовом glClear. Что имеет смысл в вашем примере; всплески, которые мы можем наблюдать, вероятно, являются кадрами после того, как вы загрузили много данных блока.

Но имейте в виду, это просто чистая спекуляция, и я тоже не эксперт по этому поводу, поэтому не верьте мне точным деталям.This page в вики OpenGL - хороший ресурс для такого рода вещей.

Хотя одно можно сказать наверняка, ваш звонок glClear не займет столько времени, сколько ваш профайлер говорит, что он делает. Вы должны использовать профилировщик, посвященный профилированию графики.