Окно OpenGL не отвечает при выполнении вычислений на GPU - PullRequest
0 голосов
/ 08 ноября 2018

Это код CUDA, который выполняет трассировку лучей.Окно OpenGL используется для отображения результатов выполненной трассировки лучей.Поскольку RayTrace довольно медленный, меня не особенно беспокоит производительность OpenGL и т. Д.

Но когда вызывается трассировка лучей (startRayTrace ()), окно OpenGL просто переходит в состояние «Не отвечает»,и отображает вывод после завершения трассировки лучей.

Я не могу понять, как предотвратить переход его в состояние отсутствия ответа.Когда он переходит в состояние отсутствия ответа, я не могу свернуть окно и т. Д., Но отображаемое изображение по-прежнему отображается как есть.

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glLoadIdentity();

    float image[768][1024][3] = { 0 };

    for (int i = 0; i < 768; ++i) {
        for (int j = 0; j < 1024; ++j) {
            int idx = (767 - i) * 1024 + j;
            image[i][j][0] = host_c[idx].x;
            image[i][j][1] = host_c[idx].y;
            image[i][j][2] = host_c[idx].z;
        }
    }

    glRasterPos2i(-1, -1);
    glDrawPixels(1024, 768, GL_RGB, GL_FLOAT, image);
    glEnd();
    glutSwapBuffers();
}

void winResize(int w, int h) {
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glViewport( (w>1024)?((w-1024)/2):(0), (h>768)?((h-768)/2):(0), w, h);
    glMatrixMode(GL_MODELVIEW);
}

void startRayTrace() {
    cudaMemcpyToSymbol(cam_offset, &cam_offset_global, sizeof(double), 0, cudaMemcpyHostToDevice);

    init <<< 1, 1 >>> ();
    cudaDeviceSynchronize();

    char title[35];

    //rayTrace <<<48, 16 >>> ();
    //cudaDeviceSynchronize();

    for (int i = 0; i < 24; ++i) {
        rayTrace <<< 1, 32 >>> ();      //Overcome Watchdog timer on Windows without disabling TDR
        cudaDeviceSynchronize();
        sprintf(title, "Ray Tracing | Rendering %.2f%%...", ((i + 1) / 24.f) * 100);
        glutSetWindowTitle(title);
    }

    copyToHost <<< 1, 1 >>> (dev_c);
    cudaMemcpy(host_c, dev_c, WIDTH * HEIGHT * sizeof(vector), cudaMemcpyDeviceToHost);
}

void keyPress(unsigned char key, int x, int y) {
    if (key == 'd') {
        cam_offset_global += 10;
    }
    if (key == 'a') {
        cam_offset_global -= 10;
    }
}

void keyUp(unsigned char key, int x, int y) {
    if (key == 'd' || key == 'a') {
        startRayTrace();
    }
    //cudaDeviceSynchronize();
    glutPostRedisplay();
}

int main(int argc, char * argv[]) {

    cudaMalloc(&dev_c, WIDTH * HEIGHT * sizeof(vector));

    //OpenGL Window
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(1024, 768);
    glutCreateWindow("Ray Tracing | Rendering 0%...");

    //Ray Tracing
    startRayTrace();
    cudaDeviceSynchronize();

    const GLubyte* ren = glGetString(GL_RENDERER);
    printf("\n\n\n OpenGL Renderer : %s \n\n", ren);

    //Register Callbacks
    glutDisplayFunc(display);
    glutReshapeFunc(winResize);
    glutKeyboardFunc(keyPress);
    glutKeyboardUpFunc(keyUp);
    glutMainLoop();

    delete[] host_c;
    cudaFree(dev_c);

    return 0;
}

После завершения трассировки лучей host_c [] сохраняет изображениеданные, которые я использую для отображения вывода на glWindow.Предполагается, что glutPostRedisplay () будет повторно отображать вывод после завершения трассировки лучей и обновления host_c [], но glWindow зависает до завершения трассировки лучей.

1 Ответ

0 голосов
/ 09 ноября 2018

GLUT не будет читать дальнейшие события, пока он находится прямо в руке события. Вы звоните startRayTrace прямо с клавиатуры. Однако startRayTrace не только запускает трассировку лучей, но и ожидает завершения. И из-за этого GLUT застрянет, пока не закончится трассировка лучей.

Ядра CUDA выполняются асинхронно. Чтобы получить информацию о завершении работы ядра, добавьте cudaEvent сразу после ядра в потоке CUDA. Затем зарегистрируйте функцию обратного вызова GLUT idle. В этой функции опросите, завершилось ли событие, и когда событие завершилось, введите glutPostRedisplay.

Не cudaSync… внутри функции клавиатуры, потому что это остановится.

...