如何正确使用glewInit()?假设我有一个多窗口应用程序,我应该在应用程序(即全局)级别调用glewInit()一次吗?或者为每个窗口调用glewInit()(即每个OpenGL渲染上下文)?
glewInit()
OpenGL
7xzttuei1#
根据所使用的GLEW构建,防水方法是在每次上下文 * 更改 * 之后调用glewInit!使用X11/GLX函数,指针是不变的。但在Windows中,OpenGL函数指针是特定于每个上下文的。GLEW的一些构建是多上下文感知的,而另一些则不是。所以为了涵盖这种情况,技术上你必须调用它,每次上下文发生变化。
glewInit
(编辑:由于要求澄清)
对于每个窗口(即每个OpenGL渲染上下文)?第一件事:OpenGL上下文不与窗口绑定。拥有一个窗口但拥有多个渲染上下文是非常好的。在Microsoft Windows中,对OpenGL来说重要的是与窗口关联的设备上下文(DC)。但它也可以反过来工作:你可以有一个OpenGL上下文,但多个窗口使用它(只要窗口的像素格式与OpenGL上下文兼容)。所以这是合法的:
HWND wnd = create_a window() HDC dc = GetDC(wnd) PIXELFORMATDESCRIPTOR pf = select_pixelformat(); SetPixelFormat(dc, pf); HGLRC rc0 = create_opengl_context(dc); HGLRC rc1 = create_opengl_context(dc); wglMakeCurrent(dc, rc0); draw_stuff(); // uses rc0 wglMakeCurrent(dc, rc1); draw_stuff(); // uses rc1
字符串这个也是
HWND wnd0 = create_a window() HDC dc0 = GetDC(wnd) HWND wnd1 = create_a window() HDC dc1 = GetDC(wnd) PIXELFORMATDESCRIPTOR pf = select_pixelformat(); SetPixelFormat(dc0, pf); SetPixelFormat(dc1, pf); HGLRC rc = create_opengl_context(dc0); // works also with dc1 wglMakeCurrent(dc0, rc); draw_stuff(); wglMakeCurrent(dc1, rc); draw_stuff();
型这里是扩展进入图片的地方。像glActiveTexture这样的函数不是OpenGL规范的一部分,它已经被固定在Windows应用程序二进制接口(ABI)中。因此,你必须在运行时获取指向它的函数指针。这就是GLEW所做的。内部看起来像这样:首先,它为函数指针定义类型,将它们声明为外部变量,并使用一点预处理器魔法来避免名称空间冲突。
glActiveTexture
typedef void (*PFNGLACTIVETEXTURE)(GLenum); extern PFNGLACTIVETEXTURE glew_ActiveTexture; #define glActiveTexture glew_ActiveTexture;
型在glewInit中,函数指针变量被设置为使用wglGetProcAddress获得的值(为了可读性,我省略了类型转换)。
wglGetProcAddress
int glewInit(void) { /* ... */ if( openglsupport >= gl1_2 ) { /* ... */ glew_ActiveTexture = wglGetProcAddress("glActiveTexture"); /* ... */ } /* ... */ }
型现在重要的部分:wglGetProcAddress使用调用时当前的OpenGL渲染上下文。所以不管在它之前的最后一个wglMakeCurrent调用是什么。如已经解释的,扩展函数指针被绑定到它们的OpenGL上下文,并且不同的OpenGL上下文可以针对相同的函数给予不同的函数指针。所以如果你这么做
wglMakeCurrent
wglMakeCurrent(…, rc0); glewInit(); wglMakeCurrent(…, rc1); glActiveTexture(…);
型它可能会失败。因此,一般来说,使用GLEW,每个对wglMakeCurrent的调用后面必须紧跟一个glewInit。GLEW的一些构建是多上下文感知的,并且在内部这样做。其他人则不然。但是,多次调用glewInit是完全安全的,所以安全的方法是调用它,只是为了确保安全。
ua4mk5z42#
它不应该是必要的,以获得多个函数ptrs每个上下文根据这个... https://github.com/nigels-com/glew/issues/38 in 2016.nigels-com回答了来自kest-relm的这个问题...你认为每次上下文更改都调用glewInit()是正确的吗?以上是处理多个opengl上下文的有效方法吗?和...我不认为为每个上下文更改调用glewInit是可取的,甚至是必要的,这取决于具体情况。显然,无论如何,这种方案不适合多线程。Kest-relm接着说。。从我的测试来看,似乎不需要反复调用glewInit();代码在多个上下文下运行良好,文档如下:https://www.opengl.org/wiki/Load_OpenGL_Functions的其中规定:实际上,如果两个上下文来自同一供应商并引用同一GPU,则从一个上下文提取的函数指针将在另一个上下文中工作。我想这应该是大多数主流的Windows GL驱动程序的真实情况?
rjzwgtxy3#
我认为只调用一次glewInit()就足够了。为每个上下文更改调用它可能会产生大量开销。微软的wglGetProcAddress文档说“扩展函数地址对于每个 * 像素格式 * 都是唯一的。给定像素格式的所有渲染上下文共享相同的扩展函数地址。”https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-wglgetprocaddress请注意,这里说的是 * 像素格式 * 而不是 * 上下文 *,这是一个重要的区别。大多数创建多个GL上下文的应用程序将在每个上下文上使用相同的像素格式。在这种情况下,函数指针应该是相同的,这意味着您应该只调用一次glewInit()。但是,如果您碰巧使用不同的像素格式,wglGetProcAddress并不能严格保证函数指针相同。也就是说,我在实践中的经验是,即使在WIN32上使用不同的像素格式,它们在两个不同的上下文中通常是相同的,这种经验似乎与这里所说的一致:https://www.opengl.org/wiki/Load_OpenGL_Functions的如果性能不那么重要,并且您希望使用具有不同像素格式的多个上下文,那么您可以考虑在每个像素格式更改时调用一次glewInit()。然而,对于大多数应用程序,我认为对glewInit()的单个调用就足够了。
3条答案
按热度按时间7xzttuei1#
根据所使用的GLEW构建,防水方法是在每次上下文 * 更改 * 之后调用
glewInit
!使用X11/GLX函数,指针是不变的。
但在Windows中,OpenGL函数指针是特定于每个上下文的。GLEW的一些构建是多上下文感知的,而另一些则不是。所以为了涵盖这种情况,技术上你必须调用它,每次上下文发生变化。
(编辑:由于要求澄清)
对于每个窗口(即每个OpenGL渲染上下文)?
第一件事:OpenGL上下文不与窗口绑定。拥有一个窗口但拥有多个渲染上下文是非常好的。在Microsoft Windows中,对OpenGL来说重要的是与窗口关联的设备上下文(DC)。但它也可以反过来工作:你可以有一个OpenGL上下文,但多个窗口使用它(只要窗口的像素格式与OpenGL上下文兼容)。
所以这是合法的:
字符串
这个也是
型
这里是扩展进入图片的地方。像
glActiveTexture
这样的函数不是OpenGL规范的一部分,它已经被固定在Windows应用程序二进制接口(ABI)中。因此,你必须在运行时获取指向它的函数指针。这就是GLEW所做的。内部看起来像这样:首先,它为函数指针定义类型,将它们声明为外部变量,并使用一点预处理器魔法来避免名称空间冲突。
型
在
glewInit
中,函数指针变量被设置为使用wglGetProcAddress
获得的值(为了可读性,我省略了类型转换)。型
现在重要的部分:
wglGetProcAddress
使用调用时当前的OpenGL渲染上下文。所以不管在它之前的最后一个wglMakeCurrent
调用是什么。如已经解释的,扩展函数指针被绑定到它们的OpenGL上下文,并且不同的OpenGL上下文可以针对相同的函数给予不同的函数指针。所以如果你这么做
型
它可能会失败。因此,一般来说,使用GLEW,每个对
wglMakeCurrent
的调用后面必须紧跟一个glewInit
。GLEW的一些构建是多上下文感知的,并且在内部这样做。其他人则不然。但是,多次调用glewInit
是完全安全的,所以安全的方法是调用它,只是为了确保安全。ua4mk5z42#
它不应该是必要的,以获得多个函数ptrs每个上下文根据这个... https://github.com/nigels-com/glew/issues/38 in 2016.
nigels-com回答了来自kest-relm的这个问题...你认为每次上下文更改都调用glewInit()是正确的吗?以上是处理多个opengl上下文的有效方法吗?
和...
我不认为为每个上下文更改调用glewInit是可取的,甚至是必要的,这取决于具体情况。显然,无论如何,这种方案不适合多线程。
Kest-relm接着说。。
从我的测试来看,似乎不需要反复调用glewInit();代码在多个上下文下运行良好,文档如下:
https://www.opengl.org/wiki/Load_OpenGL_Functions的
其中规定:
实际上,如果两个上下文来自同一供应商并引用同一GPU,则从一个上下文提取的函数指针将在另一个上下文中工作。
我想这应该是大多数主流的Windows GL驱动程序的真实情况?
rjzwgtxy3#
我认为只调用一次glewInit()就足够了。为每个上下文更改调用它可能会产生大量开销。
微软的wglGetProcAddress文档说“扩展函数地址对于每个 * 像素格式 * 都是唯一的。给定像素格式的所有渲染上下文共享相同的扩展函数地址。”
https://learn.microsoft.com/en-us/windows/win32/api/wingdi/nf-wingdi-wglgetprocaddress
请注意,这里说的是 * 像素格式 * 而不是 * 上下文 *,这是一个重要的区别。
大多数创建多个GL上下文的应用程序将在每个上下文上使用相同的像素格式。在这种情况下,函数指针应该是相同的,这意味着您应该只调用一次glewInit()。
但是,如果您碰巧使用不同的像素格式,wglGetProcAddress并不能严格保证函数指针相同。也就是说,我在实践中的经验是,即使在WIN32上使用不同的像素格式,它们在两个不同的上下文中通常是相同的,这种经验似乎与这里所说的一致:https://www.opengl.org/wiki/Load_OpenGL_Functions的
如果性能不那么重要,并且您希望使用具有不同像素格式的多个上下文,那么您可以考虑在每个像素格式更改时调用一次glewInit()。然而,对于大多数应用程序,我认为对glewInit()的单个调用就足够了。