簡體   English   中英

創建OpenGL 4.3上下文崩潰了GLX

[英]Creating an OpenGL 4.3 Context Crashes GLX

我正在使用SDL2和C ++ 11構建一個游戲引擎(就像個人項目一樣,為了娛樂和練習),我想要做的一件事就是嘗試讓圖形驅動程序使用最新支持的版本OpenGL,並根據版本改變引擎的圖形部分的呈現方式。 這樣我可以使用OpenGL的最新功能,它們相關且有用,但也支持舊硬件。 我能想到兩種方法:

  1. 檢測最新支持的OpenGL版本並使用它,但我想不出有任何方法可以做到這一點。 是的,我試過谷歌。

  2. 使用試驗和錯誤,從最新版本開始(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", 0, 0, 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上下文。

這有點晚了,但我最近遇到了這個問題(在嘗試創建SDL2中不支持的opengl上下文時仍然崩潰)

我只是創建了一個虛擬上下文,然后使用該上下文來獲取GL版本。 然后破壞那個上下文(除非它正是我想要的)並制作另一個。

//Create Dummy Context
context = SDL_GL_CreateContext(window);

//Get OpenGL Version
const GLubyte* sGLVersion =  glGetString(GL_VERSION);

version = (sGLVersion[0]-'0')*10;
version += (sGLVersion[2]-'0');

//Now Check that it can support the version that you want to make and stop if you can't
//or in your case set it to that version

//If you need to make another context destroy the old one
SDL_GL_DeleteContext(context);

//and make a new one
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, majorVersion );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, minorVersion );

context = SDL_GL_CreateContext(window);

這也比通過版本號強制執行更快,直到您碰巧落在有效的版本號上。 (你通過谷歌搜索找不到的解決方案1))

'豬'被誤認為默認版本是支持的最大版本(至少在我的默認版本中它默認為2.1,我有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錯誤 - 驅動程序甚至可能會禁用錯誤報告)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM