Расширение ARB_debug_output

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

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

Следующий листинг приводит пример такой callback-функции, просто выводящей на печать всю переданную ей информацию.

void    CALLBACK errorCallback ( GLenum source, GLenum type, GLuint id, 
                                 GLenum severity, GLsizei length, const GLchar * message, GLvoid * userParam )
{
    printf ( "-----------------------------------------------------------------------------------\n" );
    printf ( "Error:\n\tSource: %s\n\tType: %s\n\tId: %d\n\tSeverity: %s\n\tMessage: %s\n",
            stringForSource ( source ), stringForType ( type ), id, stringForSeverity ( severity ), message );
}

Обратите внимание, что обычно такая возможность поддерживается только для debug-контекстов. Допустимые значения для параметров source, type и severity перечислены в таблицах 1-3.

Таблица 1. Допустимые значения параметра source.

Константа Комментарий
GL_DEBUG_SOURCE_API_ARB OpenGL
GL_DEBUG_SOURCE_SHADER_COMPILER_ARB Компилятор GLSL
GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB Оконная система (WGL или GLX)
GL_DEBUG_SOURCE_THIRD_PARTY_ARB Внешние отладчики или библиотеки
GL_DEBUG_SOURCE_APPLICATION_ARB Само приложение
GL_DEBUG_SOURCE_OTHER_ARB Источник не относящийся ни к одной из вышеприведенных категорий

Таблица 2. Допустимые значения параметра type.

Константа Комментарий
GL_DEBUG_TYPE_ERROR_ARB Ошибка
GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB Устаревшее поведение
GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB Поведение, неопределенное по стандарту
GL_DEBUG_TYPE_PERFORMANCE_ARB Предупреждения о производительности
GL_DEBUG_TYPE_PORTABILITY_ARB Использование расширений или шейдеров привязанное к определенному производителю
GL_DEBUG_TYPE_OTHER_ARB Тип не относящийся ни к одной из вышеприведенных категорий

Таблица 3. Допустимые значения параметра severity.

Константа Комментарий
GL_DEBUG_SEVERITY_HIGH_ARB Любая ошибка OpenGL, опасное неопределенное поведение, ошибка компиляции или линковки шейдеров
GL_ DEBUG_SEVERITY_MEDIUM_ARB Важные предупреждения о производительности, ошибки компиляции и линковки шейдеров, использование deprecated функционала
GL_DEBUG_SEVERITY_LOW_ARB Сообщения о производительности из-за избыточных переключений состояния, неопределенное поведение

Для установки заданной функции в качестве callback'а служит команда glDebugMessageCallbackARB. Ниже приводится фрагмент кода, регистрирующий callback и осуществляющий вызов нескольких команд OpenGL, в результате чего возникают ошибки.

glDebugMessageCallbackARB ( errorCallback, NULL );
    
glPolygonMode ( GL_FRONT, GL_BACK );  // Error: not supported in core profile
glBindTexture ( 0, 0 );               // Error: illegal enum
glEnable      ( -1 );                 // Error: invalid enum
                                      // insert custom message
glDebugMessageInsertARB ( GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_ERROR_ARB, 1, 
                          GL_DEBUG_SEVERITY_HIGH_ARB, -1, "Custom message" );

Обратите внимание, что внутри самого callback'а нельзя вызывать ни команды OpenGL ни функции оконной системы - это может привести к непредсказуемым последствиям и падению программы.

Вызов callback-функции может происходить как в синхронном так и в асинхронном режиме. В случае синхронного режима callback вызывается до окончания работы той команды, которая и вызвала данную ошибку. В асинхронном случае драйвер сам решает когда ему вызвать callback. Для включения синхронного режима служит следующая команда:

glEnable ( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB );

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

При помощи команды glGetDebugMessageLogARB одно или несколько сообщений извлекаются из этой очереди и передаются приложению. Ниже приводится пример функции, печатающей (и удаляющей из лога) имеющиеся в нем сообщения.

GLuint glGetDebugMessageLogARB ( GLuint count,
                               GLsizei bufSize,
                               GLenum * sources,
                               GLenum * types,
                               GLenum * ids,
                               GLenum * severities,
                               GLsizei * lengths,
                               GLchar * messageLog );

Также существует команда, позволяющая добавлять пользовательские сообщение в лог (или вызывать для них callback).

void glDebugMessageInsertARB ( GLenum source,
                             GLenum type,
                             GLuint id,
                             GLenum severity,
                             GLint length, 
                             const GLchar *  buf );

Обратите внимание, что при вызове данной команды параметр source может принимать только следующие два значения - GL_DEBUG_SOURCE_APPLICATION_ARB и GL_DEBUG_SOURCE_THIRD_PARTY_ARB.

Также данное расширение предоставляет возможность при помощи команды glDebugMessageControlARB управлять тем о каких ошибках нужно сообщать и о каких - не нужно.

void glDebugMessageControlARB ( GLenum source,
                              GLenum type,
                              GLenum severity,
                              GLsizei count,
                              const GLuint * ids,
                              GLboolean enabled );

Если параметр enabled равен GL_TRUE, то остальные параметры задают фильтр для выдачи информации о заданном типе ошибки. В противном случае (GL_FALSE) они задают ошибки которые нужно игнорировать. Параметры source, type и severity задают условия на соответствующие параметры ошибки. Также они могут принимать значение GL_DONT_CARE, говорящее о том, что любое значение соответствующего параметра удовлетворяет условиям.

Также можно задать набор идентификаторов ошибки при помощи параметров count и ids. Обратите внимание что поскольку ошибка уникально идентифицируется параметрами type, source и ID, то при явном задании идентификаторов параметр severity должен быть равен GL_DONT_CARE и параметры type и source не должны одновременно равняться GL_DONT_CARE.

По этой ссылке можно скачать весь исходный код к этой статье. Также доступны для скачивания откомпилированные версии для M$ Windows и Linux.

Используются технологии uCoz