Почему пустой цикл использует так много GPU (OpenGL)? - PullRequest
0 голосов
/ 13 января 2019

Я пытаюсь создать библиотеку GUI, используя современный OpenGL. Но я замечаю, что, когда другие игры и программы используют ~ 16-20% моего времени на GPU (когда игра не запускается в главном меню), мои простые вызовы glClear () и разменных буферов используют ~ 25-26% ( в полноэкранном режиме).

Я использую glfw и glew со следующим кодом:

#include <GL/glew.h>
#include <GLFW/glfw3.h>

int main() {
    if(!glfwInit()) return -1;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_DECORATED, false);
    glfwWindowHint(GLFW_RESIZABLE, false);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //glfwWindowHint(GLFW_REFRESH_RATE, 60);

    GLFWwindow *window = glfwCreateWindow(960, 540, "Untitled Window", nullptr, nullptr);
    if(window == nullptr) return -2;

    glfwMakeContextCurrent(window);
    if(glewInit() != GLEW_OK) return -3;
    //glfwSwapInterval(1);

    glClearColor(1, 1, 1, 1);
    while(!glfwWindowShouldClose(window)) {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glfwPollEvents();
        glfwSwapBuffers(window);
    }

    glfwTerminate();
    return 0;
}

Например, пусковая установка Hearts of Iron IV потребляет около 6-7% времени моего GPU, тогда как программа, которую я запускаю с кодом выше, использует около 13% времени моего GPU.

На самом деле моя программа запускается с 4% и через несколько секунд увеличивается до 13%.

У меня есть NVIDIA GeForce GTX 980M и Intel HD Graphics 4600 (которые используют ~ 4% с приведенным выше кодом, в отличие от NVIDIA).

Что-то не так с моим компьютером или с компилятором / api?

Кстати, я тестировал как с комментариями, так и без, и результаты были очень похожи. Я также пытался использовать OpenGL 4, но это никак не отразилось.

VSync включен как для NVIDIA, так и для Intel GPU.

1 Ответ

0 голосов
/ 13 января 2019

Есть несколько причин высокого использования графических процессоров, которые вы видите в этой (казалось бы) простой программе, но самая большая причина в ...

Это не пустой цикл

Рассмотрим, к примеру, однострочный вызов функции, который вы сделали в конце цикла: glfwSwapBuffers(window);. Это вызов функции, отвечающий за указание графическому процессору сбросить текущий отображаемый кадр и отобразить следующий. Даже при отсутствии реальных объектов для рисования, это все же требует, чтобы графический процессор перерисовывал несколько миллионов пикселей (в зависимости от размера вашего монитора), и поскольку ваш цикл будет только ждать ввода от пользователя, цикл будет выполняться так быстро, как он физически способен; на моем компьютере этот цикл сам по себе будет работать на частоте около 13 кГц.

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

Если вы включите вертикальную синхронизацию или добавите преднамеренное ожидание, использование графического процессора будет более разумным

Самое простое решение - просто включить вертикальную синхронизацию, то есть графический процессор будет отображаться только тогда, когда монитор готов к следующему кадру, с частотой 60 Гц (или 120 Гц, или 144 Гц, независимо от частоты, с которой работает ваш монитор).

Ваш пост утверждает , что вертикальная синхронизация включена, но у вас уже есть функция, которая сделает это закомментированной. Раскомментируйте glfwSwapInterval(1);, и вы увидите, что использование графического процессора резко снизится, даже если нет никакого рендеринга, который требуется графическому процессору. Если у вас есть дисплей FPS, вы должны увидеть падение FPS с того места, где оно было, до относительно плоских 60 Гц; или 16,67 мсек, если вы отслеживаете это.

...