OpenGL的glClear()导致Windows 64中的访问冲突(0xc0000005)

时间:2012-05-01 04:40:33

标签: opengl 64-bit go mingw-w64 cgo

看看这个用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三角形,直到Window关闭) IF 你取出(或注释掉) 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

现在,有几个值得注意的要点......

  1. glfw 包只是一个自定义包,暴露与github.com/jteeuwen/glfw完全相同的API,但在内部使用LoadLibrary / GetProcAddress来使用glfw.dll而不是编译时CGO / GCC / LD链接 - 因为后者不能令人遗憾地在64位Windows中工作,不确定mingw64或gcc或cgo是否应该受到指责。使用LoadLibrary / GetProcAddress调用我的自定义64位构建的glfw.dll工作非常好。显然,这里的问题是调用gl包,而不是glfw。

  2. gl 包确实只是this one,未经修改。我尝试了一些LDFLAGS修改,如-m64 -lmingw32 -Wl,/ windows / opengl32.dll等,但没有区别,只要没有调用gl.Clear(),原始的工作就像修改后的一样好,所以我又恢复了原来的状态。当然,稍后我将转向OpenGL 4.2。

  3. 使用Process Explorer,我可以看到我的进程是64位,所有加载的DLL也是64位图像(包括opengl32.dll和glfw.dll)。

  4. “可能是gl21包无法获取opengl32.dll导出的glClear()函数的有效地址吗?” - 不太可能:根据line 2926,如果是这种情况,我对gl.Init()的调用会失败。

  5. 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()。

  6. 使用gl42代替gl21时会出现同样的问题,所以这也不是原因。

  7. 请注意此示例中所有其他gl.SomeExportedFunc()调用是否都不会崩溃...

    怎么办,怎么办?

    如果这只发生在gl.Clear()并且没有其他功能发生的话,我可以忍受这个 - 我只是用自定义内容渲染全屏四边形 - 但我在测试Win64时还算早在这里(有很多gl42代码在Linux64下正常工作,现在即将“移植到Win64”)我担心稍后会有更多的进一步调用会暴露同样的问题,所以我现在正在报告这个问题。我很快就会发现其他哪些电话会受到影响。

2 个答案:

答案 0 :(得分:1)

如果没有CGO生成的存根,则无法调用C函数。

答案 1 :(得分:0)

Go,GLFW和Mingw-w64的最新版本不再是问题。