2013-10-08 2 views
9

Я пишу систему рендеринга в CUDA и хочу, чтобы результаты быстро отображались через OpenGL, не касаясь основной памяти. Я в принципе сделать следующее:CUDA/OpenGL interop, рисовать текстуру OpenGL с CUDA

Создать и инициализировать OpenGL текстуры, и зарегистрировать его в CUDA, как cudaGraphicsResource

GLuint viewGLTexture; 
cudaGraphicsResource_t viewCudaResource; 

void initialize() { 
    glEnable(GL_TEXTURE_2D); 
    glGenTextures(1, &viewGLTexture); 

    glBindTexture(GL_TEXTURE_2D, viewGLTexture); 
    { 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.getWidth(), view.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    } 
    glBindTexture(GL_TEXTURE_2D, 0); 

    cudaGraphicsGLRegisterImage(&viewCudaResource, viewGLTexture, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard) 
} 

Всякий раз, когда представление изменяет размер изменить размер окна просмотра и текстуры изображения соответствующим образом:

void resize() { 
    glViewport(0, 0, view.getWidth(), view.getHeight()); 

    glBindTexture(GL_TEXTURE_2D, viewGLTexture); 
    { 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.getWidth(), view.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    } 
    glBindTexture(GL_TEXTURE_2D, 0); 
} 

И то каждый кадр i сопоставляет graphicsResource как cudaSurfaceObject через cudaArray, ядро ​​рендеринга вызова, его можно отменить и синхронизировать, чтобы OpenGL рисовал полноэкранный квадрат с этой текстурой:

void renderFrame() { 
    cudaGraphicsMapResources(1, &viewCudaResource); 
    { 
     cudaArray_t viewCudaArray; 
     cudaGraphicsSubResourceGetMappedArray(&viewCudaArray, viewCudaResource, 0, 0); 
     cudaResourceDesc viewCudaArrayResourceDesc; 
     { 
      viewCudaArrayResourceDesc.resType = cudaResourceTypeArray; 
      viewCudaArrayResourceDesc.res.array.array = viewCudaArray; 
     } 
     cudaSurfaceObject_t viewCudaSurfaceObject; 
     cudaCreateSurfaceObject(&viewCudaSurfaceObject, &viewCudaArrayResourceDesc); 
     { 
      invokeRenderingKernel(viewCudaSurfaceObject); 
     } 
     cudaDestroySurfaceObject(viewCudaSurfaceObject)); 
    } 
    cudaGraphicsUnmapResources(1, &viewCudaResource); 

    cudaStreamSynchronize(0); 

    glBindTexture(GL_TEXTURE_2D, viewGLTexture); 
    { 
     glBegin(GL_QUADS); 
     { 
      glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f); 
      glTexCoord2f(1.0f, 0.0f); glVertex2f(+1.0f, -1.0f); 
      glTexCoord2f(1.0f, 1.0f); glVertex2f(+1.0f, +1.0f); 
      glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f, +1.0f); 
     } 
     glEnd(); 
    } 
    glBindTexture(GL_TEXTURE_2D, 0); 

    glFinish(); 
} 

Проблема: всякий раз, когда просмотр изменяется, все вызовы CUDA начинают извергать «неизвестную ошибку», и визуально это выглядит так, что текстура фактически не изменяется, просто растягивается по всему виду. Почему это происходит и как я могу это исправить?

ответ

9

Кажется, что interop требует перерегистрации текстур при изменении размера. Следующие работы:

void resize() { 
    glViewport(0, 0, view.getWidth(), view.getHeight()); 

     // unregister 
    cudaGraphicsUnregisterResource(viewCudaResource); 
     // resize 
    glBindTexture(GL_TEXTURE_2D, viewGLTexture); 
    { 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, view.getWidth(), view.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    } 
    glBindTexture(GL_TEXTURE_2D, 0); 
     // register back 
    cudaGraphicsGLRegisterImage(&viewCudaResource, viewGLTexture, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard); 
} 
Смежные вопросы