与表面对象(Cuda/OpenGL互操作)错位的错误

问题描述:

我目前正试图在我的项目上互操作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,所以我认为这部分是正确的。

表面使用以字节为单位的坐标,而不是在元素中。对于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