Mesa3D不喜欢我的上下文创建代码?

时间:2013-09-20 12:19:47

标签: opengl winforms-interop mesa

今天我取消了对OpenTK的依赖;我的应用程序不再依赖OpenTK来创建OpenGL上下文。但是,在Mesa 3D(OpenGL的软件渲染实现)中运行时,我的代码不再具有可接受的功能;我的代码运行,但FPS约为0.001 FPS(与使用OpenTK上下文创建的大约16 + FPS相比),并且通常绘制到FBO的内容会在窗口中显示,因为它是由组成的。虽然在没有Mesa 3D的情况下运行我的代码会导致正常的性能(在Windows 7上),但我担心它可能恰好与它运行良好相符。 glGetError检查没有显示任何错误,这让我觉得我在创建上下文时可能做错了什么?

m_controlHandle = m_winForm.Handle; /* HWND */
m_controlDC = Win32.GetDC(m_controlHandle); /* HWND's DC*/
Win32.PixelFormatDescriptor pixelFormat = new Win32.PixelFormatDescriptor();
pixelFormat.Size = (short)Marshal.SizeOf(typeof(Win32.PixelFormatDescriptor));
pixelFormat.Version = 1;
pixelFormat.Flags =
    Win32.PixelFormatDescriptorFlags.DRAW_TO_WINDOW |
    Win32.PixelFormatDescriptorFlags.SUPPORT_OPENGL |
    Win32.PixelFormatDescriptorFlags.DOUBLEBUFFER;
pixelFormat.PixelType = Win32.PixelType.RGBA;
pixelFormat.ColorBits = 32;
pixelFormat.DepthBits = 0; /* yes, I don't use a depth buffer; 2D sprite game */
pixelFormat.LayerType = Win32.PixelFormatLayerType.MAIN_PLANE;
int formatCode = Win32.ChoosePixelFormat(m_controlDC, ref pixelFormat);
if (formatCode == 0)
    throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.SetPixelFormat(m_controlDC, formatCode, ref pixelFormat))
    throw new Win32Exception(Marshal.GetLastWin32Error());
m_openGLContext = Win32.wglCreateContext(m_controlDC);
if (m_openGLContext == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.wglMakeCurrent(m_controlDC, m_openGLContext))
    throw new Exception("Could not wglMakeCurrent.");

这是对的吗?有什么建议可以追踪可能导致Mesa3D突然变坏的原因吗?

2 个答案:

答案 0 :(得分:0)

如果要避免软件实现,选择像素格式的逻辑存在严重缺陷。回想一下(或第一次学习)WGL使用模式匹配启发式方法来查找最低限度满足的 所有 像素格式的集合您请求的参数。您留下的请求参数越多,设置为0,在解决“最佳”(最接近)匹配时,它离开的模糊程度就越大。

如果您想了解为什么0位深度缓冲区与32位颜色缓冲区相结合可能是个坏主意,您可以枚举显示驱动程序提供的所有像素格式,并检查哪些是全硬件加速(他们没有标志:PFD_GENERIC_FORMATPFD_GENERIC_ACCELERATED设置)。有一些软件会为你做到这一点,虽然我无法想到任何问题 - 如果你真的决定这样做的话,请准备好查看数百种像素格式的列表......

参数的许多奇怪组合在软件(GDI)中实现,但不在硬件中实现。为获得硬件格式而尝试的最佳位深度之一是32位RGBA,24位深度,8位模板。在现代硬件上,这几乎总是驱动程序将选择的最接近的输入参数组合的“最接近”匹配。您越接近选择精确硬件像素格式,就越有可能让Win32 / WGL无法为您提供GDI像素格式。


根据我自己的观察:

我不得不手动枚举像素格式并覆盖ChoosePixelFormat (...)的行为以解决远在过去的驱动程序错误;模式匹配行为并不总是对你有利。

在OpenTK的情况下,我怀疑它实际上使用wglChoosePixelFormatARB (...),这是一个更复杂的界面,用于选择像素格式(并且必须支持多重采样抗锯齿)。 wglChoosePixelFormatARB由可安装客户端驱动程序(ICD)实现,因此它永远不会尝试将输入参数与GDI像素格式匹配。

我怀疑GDI提供32位RGBA + 0位Z像素格式,但您的ICD却没有。由于最接近的匹配总是获胜,并且ChoosePixelFormat看到GDI像素格式,因此您可以看到为什么这是一个问题。

你应该尝试32位RGBA(24位彩色,8位Alpha)+ 24位Z + 8位模板,看看这是否会提高你的性能......


更新

还有另一个问题,可能绊倒了一些愚蠢的驱动程序。 ColorBits 假设是RGBA像素格式的RGB位数(通常为24)。 AlphaBits 假设是A位的数量(通常为8位)。许多驱动程序将看到32位ColorBits与0 AlphaBits结合并理解隐含行为(24位RGB + 8位填充),但您编写代码的方式可能很麻烦。从技术上讲,这种像素格式称为RGBX8(其中X表示未使用的位)。

24 ColorBits和8 AlphaBits可能会提供更便携的结果。

答案 1 :(得分:0)

好的......我希望没有人能够完成我试图解决的问题,所以这是解决方案:

虽然OpenTK会尝试使用wglChoosePixelFormatARB,但它在Mesa 3D上失败并退回到ChoosePixelFormat。但是,OpenTK实际调用ChoosePixelFormat DllImports而不是wglChoosePixelFormat的函数{/ 1}}。

是的,ChoosePixelFormat有两个版本:一个以 ChoosePixelFormat 为前缀,另一个没有前缀。来自OpenGL.org documentation

  

在Win32平台上,OpenGL ICD机制和GDI中复制了许多特定于平台的函数调用。这可能会导致混淆,因为它们看起来在功能上是相同的,唯一的区别在于wgl是否在函数名称的其余部分之前。为确保OpenGL的正确操作,请使用ChoosePixelformat,DescribePixelformat,GetPixelformat,SetPixelformat和SwapBuffers,而不是wgl等效项,wglChoosePixelformat,wglDescribePixelformat,wglGetPixelformat,wglSetPixelformat和wglSwapBuffers。在所有其他情况下,使用可用的wgl函数。 使用五个wgl函数只对开发人员运行时链接到OpenGL驱动程序感兴趣。不使用所描述的函数可能会导致黑色OpenGL窗口或Windows 9x中正常运行的应用程序在Windows NT / 2000上生成一个黑色的OpenGL窗口。

当我试图运行时连接到OpenGL驱动程序(Mesa 3D)时,我感兴趣的是五个wgl函数。在我用wglChoosePixelFormatSetPixelformat替换了我的SwapBufferswglChoosePixelFormatwglSetPixelformat后,Mesa 3D工作得非常出色!神秘解决了。