2014-10-28 104 views
1

我目前正試圖在我的項目上互操作Cuda和OpenGL,但它證明是一項具有挑戰性的任務。我目前使用下面的代碼:與表面對象(Cuda/OpenGL互操作)錯位的錯誤

GLuint _frameTextureGL; 
cudaGraphicsResource_t _frameTextureCUDA; 

void GLInit(){ 
    glEnable(GL_TEXTURE_2D); 
    glGenTextures(1, &_frameTextureGL); 

    glBindTexture(GL_TEXTURE_2D, _frameTextureGL); 
    { 
    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, RES_X, RES_Y, 0, GL_RGBA, GL_FLOAT, NULL); 
    } 
    glBindTexture(GL_TEXTURE_2D, 0); 

    CudaErrorCheck(cudaGraphicsGLRegisterImage(&_frameTextureCUDA, _frameTextureGL, GL_TEXTURE_2D, cudaGraphicsRegisterFlagsWriteDiscard)); 
} 


void DrawFrame(){ 

    LaunchKernel(); 

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

    glFinish(); 
    glutPostRedisplay(); 
} 



LaunchKernel(){ 

    CudaErrorCheck (cudaGraphicsMapResources(1, &_frameTextureCUDA)); //error happens here 

    cudaArray_t frameCudaArray; 
    CudaErrorCheck(cudaGraphicsSubResourceGetMappedArray(&frameCudaArray, _frameTextureCUDA, 0, 0)); 
    cudaResourceDesc frameCudaArrayResourceDesc; 

    frameCudaArrayResourceDesc.resType = cudaResourceTypeArray; 
    frameCudaArrayResourceDesc.res.array.array = frameCudaArray; 

    cudaSurfaceObject_t frameCudaSurfaceObject; 
    CudaErrorCheck(cudaCreateSurfaceObject(&frameCudaSurfaceObject, &frameCudaArrayResourceDesc)); 

    KernelFunction<< <(RES_X * RES_Y/CUDA_THREADS_PER_BLOCK) + 1, CUDA_THREADS_PER_BLOCK >> >(frameCudaSurfaceObject); 

    CudaErrorCheck(cudaDestroySurfaceObject(frameCudaSurfaceObject)); 

    CudaErrorCheck(cudaGraphicsUnmapResources(1, &_frameTextureCUDA)); 
    cudaStreamSynchronize(0); 

} 

__global__ void KernelFunction(cudaSurfaceObject_t frameCudaSurfaceObject){ 

    const int maxIndex = RES_X * RES_Y; 
    int idx = threadIdx.x + blockDim.x * blockIdx.x; 

    if (idx > maxIndex) return; 

    surf2Dwrite(make_float4(1.0f, 0.0f, 0.0f, 1.0f), frameCudaSurfaceObject, 0, 0); 

    //surf2Dwrite(make_float4(1.0f, 0.0f, 0.0f, 1.0f), frameCudaSurfaceObject, (idx % RES_X) * 4, idx/RES_X); 

} 

的問題是,在內核中的surf2Dwrite會導致我的代碼的其他地方得到一個錯誤。

隨着它的當前狀態的代碼我的項目運行,但它不顯示任何東西(我認爲是正常的,因爲我沒有正確填充表面對象)。但是,如果我將X座標改變爲除(0,0)以外的任何東西(例如通過取消註釋最後一行),則會在LaunchKernel函數的第一行中得到一個「未對齊的錯誤」。 (這個錯誤只顯示在第二幀,而不是第一幀)

我已經根據我的代碼this other answer,所以我認爲這部分是正確的。

回答

2

表面使用以字節爲單位的座標,而不是在元素中。對於float4 x座標應該是x * 16(或x * sizeof(float4)),不x * 4

surf2Dwrite(make_float4(1.0f, 0.0f, 0.0f, 1.0f), frameCudaSurfaceObject, 
      (idx % RES_X) * sizeof(float4), idx/RES_X); 
+0

謝謝,這似乎修復錯誤。我改變了我的紋理使用GL_UNSIGNED_BYTE,並改變surf2Dwrite只使用4個字節。除了黑色窗戶,我還看不到其他任何東西,但這是另一個問題。 – Duolasa 2014-10-29 12:42:33

+0

如果將來有人想要使用此代碼,我通過調整glVertex2f的座標到窗口resultion而不是使用1來解決黑窗問題。 – Duolasa 2014-10-29 13:18:04