【发布时间】:2012-05-10 17:44:45
【问题描述】:
看看这个用 Go 编写的超级简单的小测试用例 OpenGL 程序:
package main
import (
"runtime"
"./glfw"
gl "github.com/chsc/gogl/gl21"
)
func onExit (err error) {
glfw.Terminate()
if err != nil { panic(err) }
}
func main () {
runtime.LockOSThread()
err := glfw.Init()
if err != nil { panic(err) }
err = glfw.OpenWindow(1280, 720, 0, 0, 0, 0, 0, 0, glfw.Windowed)
if err != nil { onExit(err) }
err = gl.Init()
if err != nil || gl.GetError() != 0 { onExit(err) }
for glfw.WindowParam(glfw.Opened) == 1 {
gl.Viewport(0, 0, 1280, 720)
gl.ClearColor(1, 0, 0, 1)
gl.Clear(gl.COLOR_BUFFER_BIT) // THE CRASH
gl.Begin(gl.TRIANGLES)
gl.Color3f(1, 0, 0)
gl.Vertex3f(-1, -1, 0)
gl.Color3f(0, 1, 0)
gl.Vertex3f(0, 1, 0)
gl.Color3f(0, 0, 1)
gl.Vertex3f(1, -1, 0)
gl.End()
glfw.SwapBuffers()
if glfw.Key(glfw.KeyEsc) == 1 {
glfw.CloseWindow()
}
}
onExit(nil)
}
这在 Windows 7 64 位和 Go 1.0.1 64 位下构建良好。
它也工作正常(OpenGL 绘制一个彩虹色的 2D 三角形,直到窗口关闭)如果你取出(或注释掉)gl.Clear(gl.COLOR_BUFFER_BIT) 行。
一旦调用 gl.Clear(无论传递什么参数),它就会崩溃,Windows 通知我“glfw-win.exe 已停止工作...”并且 Windows 事件查看器出现以下错误为我登录:
Faulting application name: glfw-win.exe, version: 0.0.0.0, time stamp: 0x4f9f5ec5
Faulting module name: glfw-win.exe, version: 0.0.0.0, time stamp: 0x4f9f5ec5
Exception code: 0xc0000005
Fault offset: 0x0000000000012883
Faulting process id: 0xd4c
Faulting application start time: 0x01cd274e4c69a3d3
Faulting application path: C:\mytmp\glfw-win\glfw-win.exe
Faulting module path: C:\mytmp\glfw-win\glfw-win.exe
Report Id: 8a5bacc0-9341-11e1-911a-d067e544ad7f
现在,有几点值得注意...
glfw 包只是一个自定义包,它公开与 github.com/jteeuwen/glfw 完全相同的 API,但在内部使用 LoadLibrary/GetProcAddress 来使用 glfw.dll 而不是编译时CGO/GCC/LD 链接——因为后者不能在 64 位 Windows 中工作,很遗憾,不确定是 mingw64 还是 gcc 或 cgo 是罪魁祸首。使用 LoadLibrary/GetProcAddress 调用我的 glfw.dll 的自定义 64 位版本运行良好。显然这里的问题是调用 gl 包,而不是 glfw。
gl 包确实只是 this one,未经修改。我尝试了一些 LDFLAGS 修改,例如 -m64 -lmingw32 -Wl,/windows/opengl32.dll 等,但没有区别,只要不调用 gl.Clear(),原始工作与修改后的工作一样好,所以我恢复到原来的。当然,稍后我会继续使用 OpenGL 4.2。
使用 Process Explorer,我可以看到我的进程是 64 位的,并且所有加载的 DLL 也是 64 位图像(包括 opengl32.dll 和 glfw.dll)。
“难道是gl21包无法为opengl32.dll导出的glClear()函数获取有效地址?” -- 不太可能:根据line 2926,如果是这种情况,我对 gl.Init() 的调用将失败。
GPU 驱动程序问题?更不可能了。安装了最新的官方 nVidia Quadro 5010M 驱动程序 296.35。还尝试了“性能驱动程序”,但无论如何似乎是完全相同的驱动程序。根据 nVidia 控制面板,完全支持 OpenGL 4.2(尽管 opengl32.dll 的日期为 2009 年——无论如何,我目前的目标是 2.1)。此外,“Geeks3D GPU Caps Viewer”和“Shader Toy Mark”中的 OpenGL 着色器运行,正如 GLFW 示例程序particles.exe 一样——它们都使用 glClear()。
使用 gl42 而不是 gl21 时会出现完全相同的问题,所以这也不是原因。
请注意所有其他 gl.SomeExportedFunc() 调用在此示例中不会崩溃...
做什么,如何进行?
如果这种情况只发生在 gl.Clear() 而没有其他函数,我可以忍受——无论如何,我只是用自定义内容渲染全屏四边形——但我在测试 Win64 方面相当早这里(有很多 gl42 代码在 Linux64 下工作得很好,现在即将“移植”到 Win64),我担心以后进一步的调用会暴露同样的问题,所以我现在报告这个。我很快就会知道还有哪些其他电话会受此影响。
【问题讨论】:
标签: opengl 64-bit go mingw-w64 cgo