Qual é a melhor maneira de depurar o OpenGL?
10 answers
Em geral, use ferramentas como o glTrace / glIntercept( para olhar para o traço de chamada OpenGL), gDebugger (para visualizar texturas, shaders, estado OGL, etc.) e papel / lápis:). Às vezes ajuda a entender como você configurou a câmera e onde ela está olhando, o que é a ser cortado, etc. Pessoalmente, confiei mais no último do que nas duas abordagens anteriores. Mas quando posso argumentar que a profundidade está errada, então ajuda a olhar para o traço. gDebugger também é a única ferramenta que pode ser usada eficazmente para a análise e optimização da sua aplicação OpenGL.
Além desta ferramenta, na maioria das vezes é a matemática que as pessoas erram e não pode ser entendida usando qualquer ferramenta. Publicação OpenGL.org grupo de notícias para comentários específicos de código, você irá nunca fiques desapontado.
O GLIntercept é a tua melhor aposta. Da sua página web:
- gravar todas as chamadas da função OpenGL para o formato de texto ou XML com a opção de registar as imagens individuais. Câmara livre. Voe em torno da geometria enviada para a placa gráfica e Active/desactive o desenho de arames/backface-culling / view frustum render
- gravar e seguir as listas de visualização. Gravação do buffer de imagens OpenGL (cor/profundidade/stencil) pré e pós-renderização das chamadas. A capacidade de salvar o "diff" de pre e post as imagens também estão disponíveis.
Descobri que podes verificar usando {[[0]} depois de cada linha de código o teu suspeito estará errado, mas depois de o fazer, o código não parece muito limpo, mas funciona.
Qual é a melhor maneira de depurar o OpenGL?
sem considerar ferramentas adicionais e externas (o que outras respostas já fazem).
Então o modo geral é chamar extensivamenteglGetError()
. No entanto, uma melhor alternativa é usar o resultado de depuração (Khr_ Dug, Arb_debug_ output ). Isto fornece-lhe a funcionalidade de definir uma chamada de resposta para mensagens de nível de gravidade variável.
Por ordem para usar o resultado de depuração, o contexto deve ser criado com a opção WGL/GLX_DEBUG_CONTEXT_BIT
. com o GLFW isto pode ser definido com a dica GLFW_OPENGL_DEBUG_CONTEXT
da janela .
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
Note que se o contexto não é um contexto de depuração, então receber todas ou mesmo quaisquer mensagens não são garantidas.
Se TEM ou não um contexto de depuração pode ser detectado se verificar GL_CONTEXT_FLAGS
:
GLint flags;
glGetIntegerv(GL_CONTEXT_FLAGS, &flags);
if (flags & GL_CONTEXT_FLAG_DEBUG_BIT)
// It's a debug context
Você então iria em frente e especificar um callback:
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
}
Cada valor possível para os enums pode ser visto aqui. Lembre-se especialmente de verificar a gravidade, como algumas mensagens podem ser apenas notificações e não Erros.
Agora podes fazer o que quiseres e registar a chamada.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);
Pode mesmo injectar as suas próprias mensagens usando glDebugMessageInsert()
.
glDebugMessageInsert(GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0,
GL_DEBUG_SEVERITY_NOTIFICATION, -1, "Vary dangerous error");
Quando se trata de shaders e programas você sempre quer estar verificando
GL_COMPILE_STATUS
, GL_LINK_STATUS
e GL_VALIDATE_STATUS
Se algum deles reflete que algo está errado, então adicionalmente sempre verificar 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;
}
o texto devolvido por glGetProgramInfoLog()
será nulo terminado.
Você também pode ir um pouco mais extremo e utilizar algumas macros de depuração em uma compilação de depuração. Assim, usando as funções glIs*()
para verificar se o tipo esperado é o tipo real também.
assert(glIsProgram(program) == GL_TRUE);
glUseProgram(program);
Se o resultado de depuração não estiver disponível e você só quiser usar {[[12]}, então você está livre para fazê-lo.
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR)
printf("OpenGL Error: %u\n", err);
Como um código de erro numérico não ajuda muito, poderia torná-lo um pouco mais legível ao mapear os códigos de erro numérico para uma mensagem.
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";
}
}
Depois verificar assim:
printf("OpenGL Error: [%u] %s\n", err, glGetErrorString(err));
Isso ainda não é muito útil ou melhor dito intuitivo, como se tivesse aspergido alguns aqui e ali. Em seguida, localizar qual registrou um erro pode ser problemático.
Mais uma vez macros vem em Socorro.
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));
}
Basta definir uma macro como esta:
#define glCheckErrors() _glCheckErrors(__FILE__, __LINE__)
E voila agora podes ligar depois tudo o que você quer, e em caso de erros ele vai dizer-lhe o arquivo exato e linha que foi detectado em.
O gDebugger é uma excelente ferramenta livre, mas já não é suportada. No entanto, AMD pegou seu desenvolvimento, e este depurador é agora conhecido como CodeXL. Ele está disponível tanto como uma aplicação autônoma ou como um plugin de estúdio Visual-funciona tanto para aplicações nativas de C++, ou aplicações Java/Python usando ligações OpenGL, tanto em Nvidia e AMD GPUs. É uma grande ferramenta.
Existe também o glslDevil livre: http://www.vis.uni-stuttgart.de/glsldevil/
Permite-te depurar os shaders glsl extensivamente. Também mostra chamadas OpenGL falhadas. No entanto, faltam características para inspeccionar texturas e buffers fora do ecrã.A Nsight é uma boa ferramenta de depuração se tiver um cartão NVidia.
Actualizar o título da janela dinamicamente é conveniente para mim.
Exemplo (usar o GLFW, C++11):
glfwSetWindowTitle(window, ("Now Time is " + to_string(glfwGetTime())).c_str());