Подтвердить что ты не робот

Каков наилучший способ отладки OpenGL?

Я нахожу, что много времени OpenGL покажет вам, что это не удалось, ничего не рисуя. Я пытаюсь найти способы отладки программ OpenGL, проверив стек матрицы преобразования и так далее. Каков наилучший способ отладки OpenGL? Если код выглядит и чувствует, что вершины находятся в нужном месте, как вы можете быть уверены, что они есть?

4b9b3361

Ответ 1

Нет прямого ответа. Все зависит от того, что вы пытаетесь понять. Поскольку OpenGL является конечным автоматом, иногда он не выполняет то, что вы ожидаете, поскольку требуемое состояние не задано или что-то в этом роде.

В общем, используйте такие инструменты, как glTrace/glIntercept (для просмотра трассировки вызовов OpenGL), gDebugger (для визуализации текстур, шейдеров, состояния OGL и т.д.) и бумаги/карандаша:). Иногда это помогает понять, как вы устанавливаете камеру и где она смотрит, что обрезается и т.д. Я лично полагался на последний раз, чем предыдущие два подхода. Но когда я могу утверждать, что глубина неверна, это помогает смотреть на след. gDebugger - это единственный инструмент, который можно эффективно использовать для профилирования и оптимизации вашего приложения OpenGL.

Помимо этого инструмента, в большинстве случаев это математика, что люди ошибаются, и ее невозможно понять с помощью какого-либо инструмента. Опубликуйте новую группу OpenGL.org для кодовых комментариев, вы никогда не будете разочарованы.

Надеюсь, это ответит на ваш вопрос!

Ответ 2

GLIntercept - ваш лучший выбор. На своей веб-странице:

  • Сохранить все вызовы функций OpenGL в текстовом или XML-формате с возможностью регистрации отдельных кадров.
  • Свободная камера. Летайте вокруг геометрии, отправленной на графическую карту, и включайте/отключите функцию wireframe/backface-culling/view frustum render
  • Сохранение и отслеживание отображаемых списков. Сохранение буфера кадров OpenGL (цвет/глубина/трафарет) до и после обработки вызовов. Также доступна возможность сохранения "diff" пре-и почтовых изображений.

Ответ 3

Apitrace - относительно новый инструмент от некоторых людей в Valve, но он отлично работает! Попробуйте: https://github.com/apitrace/apitrace

Ответ 4

Я обнаружил, что вы можете проверить с помощью glGetError после каждой строки кода ваш подозреваемый будет неправильным, но после этого код выглядит не очень чистым, но он работает.

Ответ 5

Для тех, кто на Mac, buit в отладчике OpenGL отлично подходит. Он позволяет проверять буферы, состояния и помогает в поиске проблем с производительностью.

Ответ 6

gDebugger - отличный бесплатный инструмент, но больше не поддерживается. Тем не менее, AMD подняла свое развитие, и этот отладчик теперь известен как CodeXL. Он доступен как автономное приложение, так и как плагин Visual Studio - работает как для собственных приложений на С++, так и для приложений Java/Python с использованием привязок OpenGL, как на графических процессорах NVidia, так и AMD. Это один из черт инструмента.

Ответ 7

Каков наилучший способ отладки OpenGL?

Без учета дополнительных и внешних инструментов (какие другие ответы уже есть).

Тогда общий способ - экстренно вызвать glGetError(). Однако лучшей альтернативой является использование Отладочный вывод (KHR_debug, ARB_debug_output). Это дает вам возможность настроить обратный вызов для сообщений различной степени серьезности.

Чтобы использовать вывод отладки, контекст должен быть создан с помощью флага WGL/GLX_DEBUG_CONTEXT_BIT. С GLFW это можно установить с помощью подсказки GLFW_OPENGL_DEBUG_CONTEXT.

glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

Обратите внимание, что если контекст не является контекстом отладки, то получение всех или даже любых сообщений не гарантируется.

Если у вас есть контекст отладки или нет, можно обнаружить, проверив GL_CONTEXT_FLAGS:

GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);

if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
    // It a debug context

Затем вы переходите и указываете обратный вызов:

void debugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length,
                  const GLchar *message, const void *userParam)
{
    // Print, log, whatever based on the enums and message
}

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

Теперь вы можете выполнить и зарегистрировать обратный вызов.

glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(debugMessage, NULL);

glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);

Вы даже можете вводить свои собственные сообщения, используя glDebugMessageInsert().

glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,
                     GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Vary dangerous error");

Когда речь идет о шейдерах и программах, вы всегда хотите проверить GL_COMPILE_STATUS, GL_LINK_STATUS и GL_VALIDATE_STATUS. Если какой-либо из них отражает то, что что-то не так, тогда дополнительно проверяйте glGetShaderInfoLog()/glGetProgramInfoLog().

GLint linkStatus;
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);

if (!linkStatus)
{
    GLchar *infoLog = new GLchar[infoLogLength + 1];
    glGetProgramInfoLog(program, infoLogLength * sizeof(GLchar), NULL, infoLog); 

    ...

    delete[] infoLog;
}

Строка, возвращаемая glGetProgramInfoLog(), будет завершена нулем.


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

assert(glIsProgram(program) == GL_TRUE);
glUseProgram(program);

Если отладочный вывод недоступен, и вы просто хотите использовать glGetError(), то вы, конечно, можете это сделать.

GLenum err;
while ((err = glGetError()) != GL_NO_ERROR)
    printf("OpenGL Error: %u\n", err);

Поскольку числовой код ошибки не так полезен, мы могли бы сделать его более понятным для человека, сопоставив числовые коды ошибок с сообщением.

const char* glGetErrorString(GLenum error)
{
    switch (error)
    {
    case GL_NO_ERROR:          return "No Error";
    case GL_INVALID_ENUM:      return "Invalid Enum";
    case GL_INVALID_VALUE:     return "Invalid Value";
    case GL_INVALID_OPERATION: return "Invalid Operation";
    case GL_INVALID_FRAMEBUFFER_OPERATION: return "Invalid Framebuffer Operation";
    case GL_OUT_OF_MEMORY:     return "Out of Memory";
    case GL_STACK_UNDERFLOW:   return "Stack Underflow";
    case GL_STACK_OVERFLOW:    return "Stack Overflow";
    case GL_CONTEXT_LOST:      return "Context Lost";
    default:                   return "Unknown Error";
    }
}

Затем проверьте его следующим образом:

printf("OpenGL Error: [%u] %s\n", err, glGetErrorString(err));

Это все еще не очень полезно или лучше сказано интуитивно, как будто вы посыпали несколько glGetError() здесь и там. Тогда обнаружение того, кто зарегистрировал ошибку, может быть неприятным.

Снова макросы приходят на помощь.

void _glCheckError(const char *filename, int line)
{
    GLenum err;
    while ((err = glGetError()) != GL_NO_ERROR)
        printf("OpenGL Error: %s (%d) [%u] %s\n", filename, line, err, glGetErrorString(err));
}

Теперь просто определите макрос следующим образом:

#define glCheckError() _glCheckError(__FILE__, __LINE__)

и voila теперь вы можете вызвать glCheckError() после всего, что захотите, а в случае ошибок он скажет вам точный файл и строку, в которой он был обнаружен.

Ответ 8

Существует также бесплатный glslDevil: http://www.vis.uni-stuttgart.de/glsldevil/

Это позволяет вам отлаживать шейдеры glsl широко. Он также показывает неудачные вызовы OpenGL.

Однако в нем отсутствуют функции для проверки текстур и буферов экрана.

Ответ 9

Nsight - хороший инструмент отладки, если у вас есть карта NVidia.

Ответ 10

Динамическое изменение названия окна.

Пример (используйте GLFW, С++ 11):

glfwSetWindowTitle(window, ("Now Time is " + to_string(glfwGetTime())).c_str());