[英]Creating an OpenGL 4.3 Context Crashes 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", 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.