Recoder
Recoder

Reputation: 828

OpenGL window not responding when performing computation on GPU

It is a CUDA Code which performs ray tracing. The OpenGL window is used to display the output of the ray tracing performed. Since, the RayTrace is quite slow, I am not particularly concerned about OpenGL performace etc.

But when the ray-tracing (startRayTrace()) is called, the OpenGL window just goes to "Not Responding" State, and displays the output once the ray tracing is finished.

I can't figure out how to prevent it going into the not-respond state. When it goes in not respond state, I cannot minimize the window etc. but the rendered image is still shown as it is.

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;
}

Once the ray-trace is done, the host_c[] stores the image data, which I use to display the output on glWindow. The glutPostRedisplay() is supposed to re-render the output once ray trace finishes and host_c[] is updated, but the glWindow hangs until the ray-tracing finishes.

Upvotes: 0

Views: 777

Answers (1)

datenwolf
datenwolf

Reputation: 162367

GLUT is not going to read further events, while it's being right inside an event hand.er You're calling startRayTrace right from the keyboard callback. However startRayTrace doesn't just start the raytrace, it also waits for completion. And because of that, GLUT will be stuck until the raytrace finishes.

CUDA kernels are executed asynchronously. To get note of when the kernel finishes, add a cudaEvent right after the kernel in the CUDA stream. Then register a GLUT idle callback function. In that function, poll if the event did complete, and when the event did complete, issue a glutPostRedisplay.

Do not cudaSync… inside the keyboard function, because that will stall.

Upvotes: 2

Related Questions