今天我取消了对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突然变坏的原因吗?
答案 0 :(得分:0)
如果要避免软件实现,选择像素格式的逻辑存在严重缺陷。回想一下(或第一次学习)WGL使用模式匹配启发式方法来查找最低限度满足的 所有 像素格式的集合您请求的参数。您留下的请求参数越多,设置为0,在解决“最佳”(最接近)匹配时,它离开的模糊程度就越大。
如果您想了解为什么0位深度缓冲区与32位颜色缓冲区相结合可能是个坏主意,您可以枚举显示驱动程序提供的所有像素格式,并检查哪些是全硬件加速(他们没有标志:PFD_GENERIC_FORMAT
或PFD_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
函数。在我用wgl
,ChoosePixelFormat
和SetPixelformat
替换了我的SwapBuffers
,wglChoosePixelFormat
和wglSetPixelformat
后,Mesa 3D工作得非常出色!神秘解决了。