発生している問題・エラーメッセージ
以下のコードのように,スレッドを生成する処理をした後に,OpenGLのSwapBufferをした後に,glFinishでopenGLの命令の同期待ちをするとglFinishの部分で1フレームにつき100~200msecの大きな遅延が発生してしまいます(実際の開発しているコードではCUDAとOpenGLを連携させるためのマッピングをしており,その際にOpenGLの同期待ちをしてしまうようなので今回は代わりにglFinishを使用しています).スレッドを生成する処理をコメントアウトすると,そのような遅延がなくなります.マルチスレッドの処理を残しつつ,遅延を抑える方法や,このようなことが起きている原因の手がかりなどご教授いただければと思います..
該当のソースコード
C++のコードです.
C++
1/** VisualStudioの環境でsscanfを使用する際にエラー回避のために必要.*/ 2#define _CRT_SECURE_NO_WARNINGS 3#include <GL/glew.h> 4#include <GL/glut.h> 5 6#include <fstream> 7#include <iostream> 8 9#include <GL/freeglut_std.h> 10#include <GL/freeglut_ext.h> 11#include <chrono> 12 13#include <process.h> 14#include <thread> 15 16using namespace std; 17 18/** 60fps制御を行う. */ 19void idle() 20{ 21 auto start = std::chrono::system_clock::now(); 22 glutPostRedisplay(); 23 24 auto end = std::chrono::system_clock::now(); 25 auto msec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); 26 while (msec < 50.0 / 3.0) { 27 end = std::chrono::system_clock::now(); 28 msec = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count(); 29 } 30} 31 32/** std::thread用 */ 33unsigned int threadTest() { 34 cout << "test" << endl; 35 return 0; 36} 37 38/** process.h用 */ 39/*unsigned _stdcall threadTest(void *arg) { 40 cout << "test" << endl; 41 return 0; 42}*/ 43 44void oneFrameProcessAll() { 45 /*HANDLE test; 46 test = (HANDLE)_beginthreadex(NULL, 0, threadTest, NULL, 0, NULL); 47 WaitForSingleObject(test, INFINITE); 48 CloseHandle(test);*/ 49 thread test(threadTest); 50 test.join(); 51 52} 53 54void display(void) { 55 56 oneFrameProcessAll(); 57 58 glutSwapBuffers(); 59 60 std::chrono::time_point<std::chrono::system_clock> tmpStart; 61 std::chrono::time_point<std::chrono::system_clock> tmpEnd; 62 long long tmpMsec = 0; 63 tmpStart = std::chrono::system_clock::now(); 64 65 //ここの同期待ちで遅延が発生 66 glFinish(); 67 GLenum glerr = glGetError(); 68 if (glerr != GL_NO_ERROR) { 69 cout << glerr << endl; 70 } 71 72 tmpEnd = std::chrono::system_clock::now(); 73 tmpMsec = std::chrono::duration_cast<std::chrono::milliseconds>(tmpEnd - tmpStart).count(); 74 cout << "Temp: " << tmpMsec << "msec" << endl; 75 76} 77 78/** 画面のサイズが変更された際の処理. */ 79void resize(int w, int h) { 80 glViewport(0, 0, w, h); 81 glMatrixMode(GL_PROJECTION); 82 glLoadIdentity(); 83 gluPerspective(45.0, w/h, 10.0, 1000.0); 84 glMatrixMode(GL_MODELVIEW); 85 glLoadIdentity(); 86} 87 88/** qキーかESCキーが押されると終了処理. */ 89void hitkey(unsigned char key, int x, int y) { 90 switch (key) { 91 case 'q': 92 case 'Q': 93 case 27: // esc 94 glutLeaveMainLoop(); 95 break; 96 default: 97 break; 98 } 99} 100 101/** OpenGL描画関係の初期化. */ 102void dispinit(void) 103{ 104 glClearColor(0.0, 0.0, 0.0, 1.0); 105} 106 107int main(int argc, char *argv[]) 108{ 109 110 glutInit(&argc, argv); 111 glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS); 112 glutInitWindowSize(960, 720); 113 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); 114 glutCreateWindow(argv[0]); 115 glutDisplayFunc(display); 116 glutKeyboardFunc(hitkey); 117 glutIdleFunc(idle); 118 glutReshapeFunc(resize);; 119 dispinit(); 120 121 glutMainLoop(); 122 123 system("PAUSE"); 124 125 return 0; 126}
試したこと
・スレッドの生成についてpthread.hによる方法とstd::threadクラスを用いた方法を試しましたが,同じ現象が発生しました.
・上のコードではfreeglutを用いていますが,glfwで同じようなコードを書いても,同じ現象が発生しました.
・GPUのドライバの更新もしてみましたが,効果がありませんでした.
補足情報(FW/ツールのバージョンなど)
開発にはVisual Studio 2015を使用しております.
PCのCPUはIntel Core i7-3770を,GPUはNVIDIA GTX 1070Tiを使用しております.RAMは8GBです.OSはWindows 10 Homeです.
回答1件
あなたの回答
tips
プレビュー