我目前正在尝试在我的项目上互操作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&amp; Y坐标到(0,0)以外的任何值(例如,通过取消注释最后一行)然后我在LaunchKernel函数的第一行得到“未对齐错误”。 (此错误仅显示在第二帧,而不是第一帧)
我的代码基于this other answer,所以我认为这部分是正确的。
答案 0 :(得分:2)
Surface使用以字节为单位的坐标,而不是以元素为单位。对于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);