Когда следует вызывать glGetError? - PullRequest
16 голосов
/ 26 декабря 2009

glLoadIdentity говорит

GL_INVALID_OPERATION генерируется, если glLoadIdentity выполняется между исполнение glBegin и соответствующее исполнение glEnd.

Но GL_INVALID_OPERATION это флаг, возвращаемый glGetError .

У меня вопрос, когда мы должны вызвать glGetError (чтобы узнать, вызываем ли мы opengl в правильной последовательности)?

Ответы [ 3 ]

22 голосов
/ 01 января 2010

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

То, что вы можете сделать между glBegin и glEnd, очень ограничено. Это сделано специально, поскольку вы ставите GL в очень специфический режим - в середине ничьей. Таким образом, все, что не связано непосредственно с атрибутами для каждой вершины, просто недопустимо. Даже glGetError в этом контексте недопустим. Попробуйте и подумайте о glBegin + все вызовы GL между + glEnd как об одном вызове Draw для GL, который в любом случае помогает приблизиться к тому, что GL в действительности делает.

Теперь у вас никогда не должно быть ошибки GL, возникающей внутри пары Begin / End, если вы придерживаетесь простого правила только для вызова методов атрибута (glNormal, glTexCoord, glColor, glSecondaryColor, glIndex, glMultiTexCoord, glVertexAttrib, glVertex и пара других). Все остальное вызовет ошибку. (э-э ... ну, glMaterial - это немного исключение. Он работает, но его использование не рекомендуется)

Если ваш вопрос заключается в том, когда вы можете вызвать glGetError, когда ошибка возникла в паре Начало / Конец, ChrisF ответил в комментарии: после вызова glEnd.

Теперь, в более широком смысле, используйте glGetError только в качестве инструмента отладки. Мой личный уклон в два раза:

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

Конечно, поскольку методы атрибута можно вызывать за пределами пары Начало / Конец, немного сложно понять их правильно. Но на практике эти методы в любом случае никогда не заканчиваются, поэтому я не пытаюсь их проверять на макроуровне.

Трюк с мелочами: GL API был изначально спроектирован так, чтобы клиентская реализация могла фактически не знать, была ли ошибка на сайте вызова. Например. если GL был фактически реализован на удаленной машине (как в дни SGI), вызов, скажем, glTexEnv с целью, не равной GL_TEXTURE_ENV, мог быть просто добавлен в буфер команд, и в этот момент не было бы зарегистрировано никакой ошибки.

Если вы затем вызвали glGetError, клиентская сторона должна была бы сбросить буфер команд на GL-сервер, дождаться обработки буферизованных команд, вернуть код ошибки и вернуть соответствующий код ошибки применение.

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

В заключение, всякий раз, когда я говорю о Begin / End, я чувствую, что должен сказать, что вам, вероятно, следует обратить внимание на то, что он вообще не используется. Это худший способ рисовать с GL.

4 голосов
/ 26 декабря 2009

Обычно вы должны вызывать glGetError после каждого другого gl... вызова, так как один из эффектов вызова - очистка ошибки из стека ( от MSDN ):

При возникновении ошибки флаг ошибки устанавливается на соответствующее значение кода ошибки. Другие ошибки не записываются до тех пор, пока не будет вызван glGetError, возвращен код ошибки и установлен флаг GL_NO_ERROR.

Однако, если у вас есть вызовы, включенные в glBegin и glEnd, звоните glError после glEnd. Это должно вернуть вам правильный код ошибки (если он был) и очистить стек ошибок.

3 голосов
/ 26 декабря 2009

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

В первом случае, диагностируя проблему, я использую одну из двух стратегий. Поскольку OpenGL не записывает новые ошибки до тех пор, пока не будет вызван glGetError, я могу либо проверять ошибки один раз каждый раз через мой основной цикл. Это говорит мне о первой ошибке, которую я затем отслеживаю и, надеюсь, исправлю. Другая стратегия, которую я использую, когда я сузился до некоторого проблемного кода, но я не уверен, какой вызов вызывает проблему. После каждого гл ... звоните снаружи glBegin. , , Блок glEnd Я вызову glGetError и сообщу о любых ошибках. Это точно скажет мне, какой вызов gl ... вызывает проблему, и, надеюсь, поможет мне найти путь к исправлению.

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

...