Как измерить временную производительность вычислительного шейдера?

Мне нужно измерить время вычислительного шейдера. Но, конечно, это не тривиально. Из OpenGL Wiki - Performance я понял, что полезно использовать glFinish() до и после вызова шейдера. Но они также говорят, что это не так хорошо, чтобы использовать его. Есть ли хорошая возможность измерить время моего шейдера? Есть ли возможность измерять время вычислительного шейдера?

Мой код выглядит примерно так:

renderloop()
{
  //(1)
  //(2)
  if(updateFunction) //this is done just one time at the beginning
  {
    //update Texture with a compute shader
    //...
    glDispatchCompute();
    glMemoryBarrier(GL_ALL_BARRIER_BITS);
  }
  //(3)
  //(1)

  //use the texture to do some marching cubes rendering
}

Я думаю, я должен вставить glFinish() на позициях (1) и запустить таймер в (2) и остановить это на (3), Но я не уверен, что это действительно работает и будет давать правильные результаты синхронизации, потому что в справке они говорили о рендеринге, а вычислительный шейдер - это не рендеринг, не так ли?

Существует также OpenGL Timer_Query, но я не уверен, как он работает, и не знаю, полезно ли мне его использовать или нет. Это новость для меня, и я не уверен, полностью ли я понимаю это сейчас.

Ответ здесь говорит о том, что практически невозможно точно измерить часть кода. Лучший способ - измерить время рендеринга кадра, но мне просто нужна вычисляемая часть шейдера времени рендеринга кадра для моих целей.

Как вы думаете, это лучшая альтернатива для этого? Просто измерить все время рендеринга кадра и использовать его? Или вы получили лучший опыт с другими методами измерения?

1 ответ

Решение

Запросы по таймеру - это определенно лучший способ.

Общий принцип заключается в том, что вы создаете "объекты запроса", которые вставляете между вызовами функций GL.

Поскольку графические процессоры работают асинхронно, эти запросы будут вставляться в очередь команд графического процессора и "заполняться", когда команды действительно обрабатываются.

Итак, в вашем случае вам нужно создать запрос, скажем, glGenQueries(1, &myQuery);

Затем вместо запуска таймера вы запускаете запрос в (2), используя glBeginQuery(GL_TIME_ELAPSED, myQuery)и "остановить" его в (3), используя glEndQuery(GL_TIME_ELAPSED),

Чтобы получить результат, вы можете просто позвонить glGetQueryObject функция.

Вы можете узнать больше здесь, например: http://www.lighthouse3d.com/tutorials/opengl-short-tutorials/opengl-timer-query/

Конечно, есть некоторые "ловушки" - главная из них заключается в том, что вам нужно подождать, пока не будет готов результат синхронизации, так что вы можете синхронизировать как GPU, так и CPU, что замедлит ваше приложение (но все же даст вам хорошее время GL), или иметь несколько запросов в полете.

Другие вопросы по тегам