我进行了一些快速测试。
在Windows AMD Radeon (Ryzen 7)上:
- 请求任何上下文版本,最高可达2.1,将得到4.6兼容性上下文。这正是我想要的。
- 请求任何高于2.1的上下文版本,将得到所请求版本的上下文。
- 我认为在Linux专有驱动程序上也是同样的情况。
- 在英特尔和NVIDIA上可能也是同样的情况,但我现在无法测试。
在Windows 20.3.2的Mesa上:
- 请求任何上下文版本,最高可达3.1,将得到3.1上下文。
- 请求任何高于3.1的上下文版本,将得到4.5核心上下文。这正是我想要的。
- 我认为在Linux开源驱动程序上也是同样的情况。
- 请求OpenGL ES 2.0-3.2之间的任何版本,将得到3.2上下文。这正是我想要的。
在Android(Adreno 640)上:
- 请求任何OpenGL ES版本在2.0-3.2之间的结果都会得到一个3.2上下文。
- 我认为在Android上其他供应商的情况也是如此。
似乎只有第一次创建上下文时速度较慢。在这两种情况下,尝试创建上下文的额外尝试会在我的系统上增加约4毫秒的应用程序启动时间,而整个上下文+窗口创建时间大约为300毫秒(使用本地驱动程序)或70毫秒(使用Mesa)。
我没有macOS进行测试,所以我将采用保守的方法,先尝试向前兼容4.1、3.3、3.2,然后再尝试2.1。不管怎样,大多数Mac都支持正好4.1,因此对于它们来说,上下文将在第一次尝试时创建。
这就是iOS OpenGL ES文档建议做的事情:
为了在应用程序中支持多个OpenGL ES版本作为渲染选项,您应该首先尝试初始化您想要定位的最新版本的渲染上下文。如果返回的对象为空,则初始化旧版本的上下文。因此,在GLFW伪代码中,我的OpenGL策略如下:
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
GLFWwindow* wnd;
#ifdef __APPLE__
const std::array<char, 2> versions[] = {{4, 1}, {3, 3}, {3, 2}, {2, 1}};
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
for(auto ver: versions)
{
if(ver[0] < 3) glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, false);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, ver[0]);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, ver[1]);
wnd = glfwCreateWindow(...);
if(wnd) break;
}
glfwMakeContextCurrent(wnd);
#else
glfwWindowHint(GLFW_VISIBLE, false);
wnd = glfwCreateWindow(...);
glfwMakeContextCurrent(wnd);
std::string_view versionStr = glGetString(GL_VERSION);
if(versionStr[0] < '4' && versionStr.contains("Mesa"))
{
glfwDestroyWindow(wnd);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
wnd = glfwCreateWindow(...);
glfwMakeContextCurrent(wnd);
}
glfwShowWindow(wnd);
#endif
OpenGL ES的代码看起来类似但更简单。移动平台将使用不同的库,而不是GLFW(GLFM / SDL或本地EGL)。对于iOS,我必须尝试ES 3.0然后尝试ES 2.0。对于Mesa和Android,我只需请求一个2.0上下文并获取最新的上下文(3.2)。但是,对于Android,我假设Mali和其他供应商的工作方式相同。请在评论中让我知道您是否可以测试我的假设以确认或否认它们。