OpenGL驱动的陷阱:ATI篇

1407 篇文章 2 订阅
1277 篇文章 12 订阅
转载请注明出处为KlayGE游戏引擎,本文的永久链接为http://www.klayge.org/?p=276

在下一版的KlayGE中,D3D9插件光荣退休,OpenGL插件将要取代它在WinXP下的位置。众所周知,ATI的OpenGL驱动一直毛病众多。因此解决OpenGL插件在ATI卡上出现的错误成了当务之急。本文就讨论一下在增强OpenGL插件的过程中遇到的陷阱及其解决方法。测试的显卡为HD5870,所有问题在9.12-10.10的驱动中都会出现。

glBlitFramebufferEXT

在以前的版本里,OpenGL插件在ATI显卡上的文字显示总是乱码。一开始怀疑是vbo或者shader造成的,最后定位在texture本身。在texture的局部拷贝过程中,OpenGL插件用的是GL_EXT_framebuffer_blit扩展的glBlitFramebufferEXT。ATI驱动对GL_EXT_framebuffer_blit的支持似乎并不完善,结果是虽然什么错误都没发生,但拿目标texture来使用的时候总是一团乱麻,如下图所示:

错误的text结果

如果这个时候用glGetTexImage获取texture数据,却又是正确的。绕开这个问题的方法就是用pbo把源texture和目标texture都map出来,然后memcopy;或者更传统的gluScaleImage。此问题修好之后,所有例子的文字显示在ATI卡上恢复了正常:

正确的Text结果

glClearBufferfi/glClearBufferfv/glClearBufferiv

在一些例子,比如Parallax中,出现了画面空白的现象。clear color buffer能起作用,但depth/stencil buffer却没有被正确地清除。在支持OpenGL3及以上的情况下,OpenGL插件会默认调用glClearBuffer*的函数来直接清除buffer,而不用传统的方法:先调用glClearColor,glClearDepth,glClearStencil设置清除的值,然后调用glClear来完成清除的工作。在ATI卡上,似乎glClearBufferfi/glClearBufferfv/glClearBufferiv这些用来清除depth/stencil的函数并没有起作用。解决方法只能是退回到传统的Clear方法。

这么做之后,绝大部分例子都能正常渲染了:

正确的Parallax结果

glBeginConditionalRender

Deferred shading的例子用query conditional来判断一个光源是否可见。原先的版本在ATI卡上一执行就发生系统死锁,必须强制冷启动才能解决,破坏性极大,而且完全没有机会调试。(难道是因为query conditional是NV提出来的缘故?)一次凑巧看了http://www.g-truc.net/post-0318.html,确定就是因为query conditional造成了死锁。

把相关语句绕开之后Deferred shading恢复正常了。正确的DeferredShading结果

GLSL

GLSL的问题其实不能算是陷阱,但值得关注。ATI驱动的GLSL编译器可谓中规中矩,符合GLSL标准的shader一般没啥问题,但不符合标准的会死得很难看。NVIDIA的GLSL编译器则大不相同,兼容很多NV自己的“扩展”,比如支持数组的varying。所以其实在ATI卡上能工作的GLSL基本也能在NV的卡上工作。如果你希望你的GLSL可以在ATI平台上跑,我的推荐是用AMD GPU ShaderAnalyzer测试一下(GPU ShaderAnalyzer是个纯软件的分析器,在NV的平台上也能运行)。如果GLSL有问题,就会立刻显现出来。

经过一系列的尝试,Cg到GLSL的转化终于可以在ATI平台上顺利执行,包括Geometry shader:

正确的Geometry shader结果

以上就是我在KlayGE中遇到的ATI OpenGL驱动陷阱。希望对大家以后遇到的问题有所帮助。


上个月的一篇帖子提到了ATI OpenGL驱动的一些陷阱,随着ATI驱动每个月的新版本不断发布,这些问题是否得到改善呢?

glBlitFramebufferEXT

情况一样,没有任何变化,还是没法用:(。

glClearBuffer*

WTF,没有任何变化,还是没法用。

glBeginConditionalRender

已经改进!如果glBeginConditionalRender和glEndConditionalRender完全严格地配对使用,就能正常工作,不会造成恐怖的死锁。如果一旦不小心没有遵循配对使用的规则,照死锁不误。NVIDIA的驱动上不配对也没发生任何错误,虽然确实不该那么用。

新发现的问题

在改进海洋渲染的过程中,displacement texture从ABGR16f改成了ABGR8,结果在ATI OpenGL的情况下一片平坦。经过其他测试后的结论是,ABGR8和ARGB8这样格式的纹理,在vertex shader中读取总是会返回0。这也是个莫名其妙的bug,按理说在D3D10+的卡上vs和ps对纹理读取的能力完全一样才对。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值