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)
}
これは、Go1.0.164ビットを使用するWindows764ビットで正常にビルドされます。
また、 gl.Clear (gl.COLOR_BUFFER_BIT)行を削除(またはコメントアウト)すると、正常に機能します(OpenGLは、ウィンドウが閉じるまで単一の虹色の2D三角形を描画します) 。
ただし、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を公開する単なるカスタムパッケージですが、コンパイル時のCGO / GCC/LDリンクではなくglfw.dllを使用するためにLoadLibrary/GetProcAddressを内部的に使用します。悲しいことに、64ビットWindowsで動作するように作られていますが、mingw64、gcc、cgoのいずれが原因かはわかりません。LoadLibrary / GetProcAddressを呼び出すと、glfw.dllのカスタム64ビットビルドが非常にうまく機能します。明らかに、ここでの問題は、glfwではなくglパッケージの呼び出しにあります。
glパッケージは、実際にはこれだけで、変更されていません。-m64 -lmingw32 -Wl、/ windows / opengl32.dllなどのいくつかのLDFLAGSの変更を試しましたが、違いはありません。gl.Clear()が呼び出されない限り、元の変更は変更されたものと同じように機能します。そのため、元に戻しました。もちろん、後でOpenGL4.2に移ります。
Process Explorerを使用すると、プロセスが64ビットであり、ロードされたすべてのDLLも64ビットイメージ(opengl32.dllおよびglfw.dllを含む)であることがわかります。
「gl21パッケージがopengl32.dllによってエクスポートされたglClear()関数の有効なアドレスを取得できなかった可能性がありますか?」-ありそうもない:2926行目によると、この場合、gl.Init()の呼び出しは失敗します。
GPUドライバーの問題?さらにありそうもない。最新の公式nVidiaQuadro5010Mドライバー296.35がインストールされています。「パフォーマンスドライバー」も試してみましたが、とにかくまったく同じドライバーのようです。nVidiaコントロールパネルによるOpenGL4.2の完全サポート(opengl32.dllの日付は2009年ですが、とにかく、現在ターゲットにしている2.1には十分です)。さらに、「Geeks3D GPU CapsViewer」および「ShaderToyMark」のOpenGLシェーダーは、GLFWサンプルプログラムparticles.exeと同様に実行されます。これらはすべて、glClear()も使用します。
gl21の代わりにgl42を使用した場合もまったく同じ問題が発生するため、それも原因ではありません。
この例では、他のすべてのgl.SomeExportedFunc()呼び出しがクラッシュしないことに注意してください...
何をすべきか、どのように進めるか?
これがgl.Clear()でのみ発生し、他の機能がこれまでにない場合、これで生きることができます-とにかくカスタムコンテンツでフルスクリーンクワッドをレンダリングするだけです-しかし、ここでWin64をテストするのはかなり早いです(多くのgl42コードはLinux64で問題なく動作し、Win64に「移植」されようとしています)。後でさらに呼び出しを行うと同じ問題が発生するのではないかと心配しているので、今報告します。これによって影響を受ける他の呼び出しはすぐにわかります。