Каков наилучший способ отладки OpenGL?
Я считаю, что много времени OpenGL покажет вам, что это не удалось, ничего не рисуя. Я пытаюсь найти способы отладки программ OpenGL, проверяя стек матрицы преобразования и так далее. Каков наилучший способ отладки OpenGL? Если код выглядит и чувствует, что вершины находятся в правильном месте, как вы можете быть уверены, что они есть?
10 ответов:
прямого ответа нет. Все зависит от того, что вы пытаетесь понять. Поскольку OpenGL-это конечный автомат, иногда он не делает то, что вы ожидаете, поскольку требуемое состояние не установлено или что-то в этом роде.
В общем, используйте такие инструменты, как glTrace / glIntercept (для просмотра трассировки вызовов OpenGL), gDebugger (для визуализации текстур, шейдеров, состояния OGL и т. д.) и бумага/карандаш :). Иногда это помогает понять, как вы настроили камеру и куда она смотрит, что такое быть обрезанным и т. д. Я лично полагался больше на последний, чем на предыдущие два подхода. Но когда я могу утверждать, что глубина неверна, тогда это помогает смотреть на след. gDebugger тоже the
GLIntercept это ваш лучший ставку. С их веб-страницы:
- сохранить все вызовы функций OpenGL в текстовом или XML формате с возможностью регистрации отдельных кадров.
- свободная камера. Облетите геометрию, отправленную на графическую карту, и включите / отключите каркас / backface-culling/view frustum render
- сохранение и отслеживание списков отображения. Сохранение буфера кадров OpenGL (цвет / глубина / трафарет) до и после вызова рендеринга. Возможность сохранения "разница" до и после картинки тоже имеются.
Apitrace-это относительно новый инструмент от некоторых людей в Valve, но он отлично работает! Дайте ему попробовать: https://github.com/apitrace/apitrace
Я нашел, что вы можете проверить с помощью
glGetError
после каждой строки кода ваш подозреваемый будет ошибаться, но после этого код выглядит не очень чистым, но он работает.
каков наилучший способ отладки 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's 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()
завершится null.
вы также можете пойти немного более экстремальным и использовать несколько макросов отладки в сборке отладки. Таким образом, используя
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 _glCheckErrors(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 glCheckErrors() _glCheckErrors(__FILE__, __LINE__)
и вуаля теперь вы можете звонить
glCheckErrors()
после всего, что вы хотите, и в случае ошибок он сообщит вам точный файл и строку, в которой он был обнаружен.
для тех, кто на Mac, buit в отладчике OpenGL также отлично подходит. Он позволяет проверять буферы, состояния и помогает находить проблемы с производительностью.
gDebugger является отличным бесплатным инструментом, но больше не поддерживается. Тем не менее, AMD подхватила свою разработку, и этот отладчик теперь известен как CodeXL. Он доступен как в качестве автономного приложения, так и в качестве плагина Visual Studio - работает как для собственных приложений C++, так и для приложений Java/Python с использованием Привязок OpenGL, как на графических процессорах NVidia, так и AMD. Это чертовски хороший инструмент.
есть также бесплатный glslDevil:http://www.vis.uni-stuttgart.de/glsldevil/
Это позволяет широко отлаживать шейдеры glsl. Он также показывает неудачные вызовы OpenGL.
однако отсутствуют функции для проверки текстур и буферов вне экрана.
Nsight это хороший инструмент отладки, если у вас есть карта NVidia.