OpenGL调试或详细信息控制台



是否有某种调试模式,OpenGL可以在哪里输出信息到控制台运行?我有一个应用程序在许多机器上运行良好,但它在一台真正重要的机器上失败得很惨。我不能直接访问那台机器,所以我想弄清楚它是怎么出问题的。目前我在控制台中没有看到任何输出。注意,该应用程序最初是一个没有控制台的windows应用程序,我通过项目属性将其切换为控制台。此外,如果它的关系一些对象不显示和另一个卡住,不动画-这对我来说没有任何意义。

不,不完全是。如果你真的想要一些详细的输出,你必须为OpenGL编写一个钩子并记录它所做的所有调用(这是像gDEBugger这样的工具所做的),但这需要相当多的工作(你可以使用像GLIntercept这样的东西)。从个人经验来看:最简单的可能是访问有问题的机器并在那里运行gDEBugger…或者找一台等效的机器,这样你就可以在附带图形调试器的情况下重现错误。

或者,您可以尝试使用ARB_debug_output扩展,理论上,它应该为您提供更多的输出。在实践中,你得到的只是在每个OpenGL API调用之后的glGetError调用,这可能对你的用例足够好(即你只是做一些打破GL状态的事情)。为了使用调试输出扩展,您必须修改您的应用程序以创建一个调试上下文。

这是在Windows 10上使用c++/GLEW/GLFW和Visual Studio 2019的方法,只是相关的部分:

/** Necessary includes */
#include <map>
#include <GL/glew.h>
#include <GLFW/glfw3.h>
/** Debug callback prototype */
void GLAPIENTRY GLDebugMessageCallback(GLenum Source,
    GLenum Type,
    GLuint Id,
    GLenum Severity,
    GLsizei Length,
    const GLchar* Message,
    const void* UserParam);
/** Create the window and set the OpenGL context */
int main(void)
{
    if (glfwInit() != GLFW_TRUE)
    {
        printf("Unable to initialize GLFWn");
        return EXIT_FAILURE;
    }
    /** Set the OpenGL Debug Context hint */
    glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
    GLFWwindow* Window = glfwCreateWindow(800, 600, "OpenGL", nullptr, nullptr);
    if (!Window)
    {
        glfwTerminate();
        printf("Unable to create a GLFW windown");
        return EXIT_FAILURE;
    }
    glfwMakeContextCurrent(Window);
    if (glewInit() != GLEW_OK)
    {
        printf("Unable to initialize GLEWn");
        return EXIT_FAILURE;
    }
    /** Check whether debug context is enabled and set the debug callback */
    GLint ContextFlags;
    glGetIntegerv(GL_CONTEXT_FLAGS, &ContextFlags);
    if (ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)
    {
        printf("OpenGL : Debug Context Is Enabled");
        glEnable(GL_DEBUG_OUTPUT);
        glDebugMessageCallback(GLDebugMessageCallback, 0);
    }
    while (!glfwWindowShouldClose(Window))
    {
        glfwPollEvents();
        // Edit here...
        glfwSwapBuffers(Window);
    }
    glfwDestroyWindow(Window);
    glfwTerminate();
    return EXIT_SUCCESS;
}
/** Debug callback definition */
void GLAPIENTRY GLDebugMessageCallback(GLenum Source,
    GLenum Type,
    GLuint Id,
    GLenum Severity,
    GLsizei Length,
    const GLchar* Message,
    const void* UserParam)
{
    static std::map<GLenum, const GLchar*> Sources =
    {
        {GL_DEBUG_SOURCE_API, "API"},
        {GL_DEBUG_SOURCE_WINDOW_SYSTEM, "WINDOW_SYSTEM"},
        {GL_DEBUG_SOURCE_SHADER_COMPILER, "SHADER_COMPILER"},
        {GL_DEBUG_SOURCE_THIRD_PARTY, "THIRD_PARTY"},
        {GL_DEBUG_SOURCE_APPLICATION, "APPLICATION"},
        {GL_DEBUG_SOURCE_OTHER, "OTHER"}
    };
    static std::map<GLenum, const GLchar*> Severities =
    {
        {GL_DEBUG_SEVERITY_HIGH, "HIGH"},
        {GL_DEBUG_SEVERITY_MEDIUM, "MEDIUM"},
        {GL_DEBUG_SEVERITY_LOW, "LOW"},
        {GL_DEBUG_SEVERITY_NOTIFICATION, "NOTIFICATION"}
    };
    static std::map<GLenum, const GLchar*> Types =
    {
        {GL_DEBUG_TYPE_ERROR, "ERROR"},
        {GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR, "DEPRECATED_BEHAVIOR"},
        {GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, "UNDEFINED_BEHAVIOR"},
        {GL_DEBUG_TYPE_PORTABILITY, "PORTABILITY"},
        {GL_DEBUG_TYPE_PERFORMANCE, "PERFORMANCE"},
        {GL_DEBUG_TYPE_MARKER, "MARKER"},
        {GL_DEBUG_TYPE_PUSH_GROUP, "PUSH_GROUP"},
        {GL_DEBUG_TYPE_POP_GROUP, "POP_GROUP"},
        {GL_DEBUG_TYPE_OTHER, "OTHER"}
    };
    printf("[OpenGL %s] - SEVERITY: %s, SOURCE: %s, ID: %d: %sn", Types[Type], Severities[Severity], Sources[Source], Id, Message);
}

[OpenGL ERROR] - SEVERITY: HIGH, SOURCE: API, ID: 1282: GL_INVALID_OPERATION error generated. Function glColor4fv is deprecated and not available in preview contexts.
[OpenGL ERROR] - SEVERITY: HIGH, SOURCE: API, ID: 1282: GL_INVALID_OPERATION error generated. Array object is not active.
[OpenGL OTHER] - SEVERITY: NOTIFICATION, SOURCE: API, ID: 131185: Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_DYNAMIC_DRAW) will use SYSTEM HEAP memory as the source for buffer object operations.
[OpenGL OTHER] - SEVERITY: NOTIFICATION, SOURCE: API, ID: 131185: Buffer detailed info: Buffer object 1 (bound to GL_ARRAY_BUFFER_ARB, usage hint is GL_DYNAMIC_DRAW) has been mapped WRITE_ONLY in SYSTEM HEAP memory (fast).
与<<p> 测试/strong>

OpenGL 4.6
GLSL 4.60 NVIDIA
渲染器:GeForce RTX 2070 with Max-Q Design/PCIe/SSE2
供应商:NVIDIA Corporation

打印到Visual Studio输出窗口

#include <windows.h> // For OutputDebugStringA 

将调试回调定义末尾的printf替换为以下内容:

char ErrorString[512];
sprintf_s(ErrorString, "[OpenGL %s] - SEVERITY: %s, SOURCE: %s, ID: %d: %sn", Types[Type], Severities[Severity], Sources[Source], Id, Message);
OutputDebugStringA(ErrorString);

调试上下文注意事项

简而言之,当OpenGL上下文在调试上下文模式下创建时,在应用程序,驱动程序和GPU之间的路径中会激活额外的层。这些附加层执行错误检查、参数分析等,并通过调试消息回调将其作为格式良好的消息报告。

启用OpenGL调试上下文是平台特定的,所以GLFW在这个意义上是有帮助的,因为它提供了一种通过glfwWindowHint配置OpenGL上下文的方法,应该在创建GLFW窗口之前配置。

来自OpenGL Wiki -启用调试输出:

除非启用调试输出,否则不会生成、检索或记录任何消息。它是通过使用glEnable和GL_DEBUG_OUTPUT枚举器来启用的。

在Debug上下文中,启动调试输出。在非调试环境中,即使启用了调试输出,OpenGL实现也可能不会生成消息。

我验证了在Windows 10上,一些输出实际上只是通过启用调试输出和设置回调而生成的,而没有激活调试上下文。

glDebugMessageCallback的详细信息可在docs中找到。GL和OpenGL Wiki和OpenGL Superbible第7版

相关内容

最新更新