c – 创建OpenGL 4.3上下文崩溃了GLX

前端之家收集整理的这篇文章主要介绍了c – 创建OpenGL 4.3上下文崩溃了GLX前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用SDL2和C 11构建一个游戏引擎(就像个人项目一样,为了娱乐和练习),我想做的其中一件事就是尝试让图形驱动程序使用最新支持的OpenGL版本,并根据版本改变引擎的图形部分的呈现方式.这样我可以使用OpenGL的最新功能,它们相关且有用,但也支持旧硬件.我能想到两种方法

>检测最新支持的OpenGL版本并使用它,但我想不出任何方法可以做到这一点.是的,我试过谷歌.
>使用试验和错误,我从最新版本开始(4.3,但我的GTX 460仅支持最多4.2,即使我更新了驱动程序),如果失败(通过检查SDL返回NULL检测到)上下文),我降低版本号,然后再试一次.

我使用的方法(#2)在创建4.3上下文后立即失败.我知道我的图形驱动程序现在只支持4.2,但我原以为GLX被设计为抛出一个错误,给出一个NULL上下文,并让你的程序继续运行,但它无法通过上下文的失败创建.我的假设是关于GLX如何表现错误?有没有办法在不创建上下文的情况下检测最新支持的版本?

因为我知道有些人喜欢看到演示错误的完整和最小的来源,这里是:

#include <SDL2/SDL.h>
#include <SDL2/SDL_opengl.h>
int main() {
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 ) {
        return -1;
    }
    SDL_Window* window = SDL_CreateWindow( "SDL Window",800,600,SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN );
    if( window == nullptr ) {
        return -1;
    }
    unsigned int major = 4;
    unsigned int minor = 3;
    SDL_GLContext context = nullptr;
    while( context == nullptr ) {
        SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION,major );
        SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION,minor );
        context = SDL_GL_CreateContext( window );
        if( context == nullptr ) {
            if( minor == 0 && major > 1 ) {
                --major;
                minor = 9;
            }
            else if( minor > 0 ) {
                --minor;
            }
            else {
                SDL_DestroyWindow( window );
                return -1;
            }
        }
    }
    SDL_Delay( 5000 );
    SDL_GL_DeleteContext( context );
    SDL_DestroyWindow( window );
    return 0;
}

此外,如果我将该代码更改为以4.2上下文而不是4.3开头,则它可以正常工作.所以错误在于专门创建4.3上下文.

解决方法

这可能表明SDL的X11_GL_CreateContext()中存在错误(在网络上它表示SDL2仍然是实验性的).您找到支持的OpenGL版本的策略是有效的,但为了让SDL为您提供前向兼容的上下文,它首先需要创建一个临时上下文,调用glXGetProcAddress()来获取glCreateContextAttribsARB(它不能没有这样做一个活动的OpenGL上下文),然后它尝试初始化您请求的OpenGL版本.现在,如果失败,它将处置临时上下文并返回NULL.

我的猜测是第二次创建临时上下文失败,我建议使用调试信息构建SDL并尝试找出X11_GL_CreateContext()中的确切位置(或者至少插入几个printf).

另一方面,如果将SDL_GL_CONTEXT_MAJOR_VERSION和SDL_GL_CONTEXT_MINOR_VERSION保留为默认值,则已获得最大OpenGL版本.你只是没有得到一个前向兼容的上下文,这意味着它会让一些在未来版本中被认为是“错误”的行为漏掉.

此外,通常,创建具有最大版本的前向兼容上下文并不是一个好主意.例如.在OpenGL 3.2中,前向兼容配置文件强制使用顶点数组对象,这使得不使用VAO的旧代码被破坏.因此,如果为OpenGL 3.1(或任何其他版本)编写的应用程序试图获得最新的向前兼容配置文件,它实际上可能在将来停止工作.这不是一个好主意.

一种选择是决定使用一个向前兼容的配置文件,这通常非常有用,因为它报告有关已弃用功能错误.如果您真的想要使用更多版本,则需要更多代码路径(=游戏引擎的更多版本).为了检测OpenGL版本,我建议创建一个虚拟SDL窗口,初始化一个简单的OpenGL配置文件,获取版本并关闭所有内容,然后再次初始化,使用您决定的版本.这应该工作.

另一种选择是仅将前向兼容配置文件用于开发,并使用简单的旧配置文件进行分发.它是最兼容的并且涉及的工作量最少(您希望无论如何都要忽略发布版本中的大多数OpenGL错误 – 驱动程序甚至可能会禁用错误报告).

猜你在找的C&C++相关文章