只有glClear(.)颜色显示,没有其他渲染(CUDA/OpenGL互操作)

Only glClear(..) color is displayed, nothing else rendered (CUDA/OpenGL interop)

本文关键字:CUDA OpenGL 互操作 其他 颜色 glClear 显示 只有      更新时间:2023-10-16

我有一个WinForms应用程序,其中有一个面板(500x500像素),我想在其中渲染一些东西。现在我要用一种特定的颜色来填充它。我想使用OpenGL/CUDA互操作来做到这一点。

我得到面板配置为区域渲染的东西,然而,当我运行我的代码,面板只是填充了glClear(..)的颜色,并没有由内核分配显示。它今天早上有点工作(不一致),在我试图整理SwapBuffers()混乱时,我想我搞砸了。

这是OpenGL的像素格式初始化。它似乎工作得很好,我有两个缓冲区,如我所料,上下文是正确的:

static  PIXELFORMATDESCRIPTOR pfd=              
{
    sizeof(PIXELFORMATDESCRIPTOR),              // Size Of This Pixel Format Descriptor
    1,                                          // Version Number
    PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
    PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
    PFD_DOUBLEBUFFER,                           // Must Support Double Buffering
    PFD_TYPE_RGBA,                              // Request An RGBA Format
    16,                                         // Select Our Color Depth
    0, 0, 0, 0, 0, 0,                           // Color Bits Ignored
    0,                                          // No Alpha Buffer
    0,                                          // Shift Bit Ignored
    0,                                          // No Accumulation Buffer
    0, 0, 0, 0,                                 // Accumulation Bits Ignored
    16,                                         // 16Bit Z-Buffer (Depth Buffer) 
    0,                                          // No Stencil Buffer
    0,                                          // No Auxiliary Buffer
    PFD_MAIN_PLANE,                             // Main Drawing Layer
    0,                                          // Reserved
    0, 0, 0                                     // Layer Masks Ignored
};
GLint  iPixelFormat; 
// get the device context's best, available pixel format match 
if((iPixelFormat = ChoosePixelFormat(hdc, &pfd)) == 0)
{
    MessageBox::Show("ChoosePixelFormat Failed");
    return 0;
}
// make that match the device context's current pixel format 
if(SetPixelFormat(hdc, iPixelFormat, &pfd) == FALSE)
{
    MessageBox::Show("SetPixelFormat Failed");
    return 0;
}
if((m_hglrc = wglCreateContext(m_hDC)) == NULL)
{
    MessageBox::Show("wglCreateContext Failed");
    return 0;
}
if((wglMakeCurrent(m_hDC, m_hglrc)) == NULL)
{
    MessageBox::Show("wglMakeCurrent Failed");
    return 0;
}   
在这之后,我设置ViewPort如下:
glViewport(0,0,iWidth,iHeight);                     // Reset The Current Viewport
glMatrixMode(GL_MODELVIEW);                         // Select The Modelview Matrix
glLoadIdentity();                                   // Reset The Modelview Matrix
glEnable(GL_DEPTH_TEST);

然后我设置清亮色,并设置清亮:

glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);  

现在我设置CUDA/OpenGL互操作:

cudaDeviceProp prop; int dev;
memset(&prop, 0, sizeof(cudaDeviceProp));
prop.major = 1; prop.minor = 0;
checkCudaErrors(cudaChooseDevice(&dev, &prop));
checkCudaErrors(cudaGLSetGLDevice(dev));
glBindBuffer    = (PFNGLBINDBUFFERARBPROC)GET_PROC_ADDRESS("glBindBuffer");
glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)GET_PROC_ADDRESS("glDeleteBuffers");
glGenBuffers    = (PFNGLGENBUFFERSARBPROC)GET_PROC_ADDRESS("glGenBuffers");
glBufferData    = (PFNGLBUFFERDATAARBPROC)GET_PROC_ADDRESS("glBufferData");
GLuint bufferID;
cudaGraphicsResource * resourceID;
glGenBuffers(1, &bufferID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferID);
glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, fWidth*fHeight*4, NULL, GL_DYNAMIC_DRAW_ARB);
checkCudaErrors(cudaGraphicsGLRegisterBuffer( &resourceID, bufferID, cudaGraphicsMapFlagsNone ));

现在我尝试调用我的内核(它只是为每个像素绘制特定的颜色)并显示它。

uchar4* devPtr;
size_t size;
// First clear the back buffer:
glClearColor(1.0f, 0.5f, 0.0f, 0.0f); // orange
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
checkCudaErrors(cudaGraphicsMapResources(1, &resourceID, NULL));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void**)&devPtr, &size, resourceID));
animate(devPtr); // This will call the kernel and do a sync (see later)
checkCudaErrors(cudaGraphicsUnmapResources(1, &resourceID, NULL));
// Swap buffers to bring back buffer forward:
SwapBuffers(m_hDC);

在这一点上,我希望看到内核的颜色在屏幕上,但是没有!我看到的是橙色,这是我刚刚设置的透明色。

下面是对内核的调用:
void animate(uchar4* dispPtr)
{
    checkCudaErrors(cudaDeviceSynchronize());
    animKernel<<<blocks, threads>>>(dispPtr, envdim);;
    checkCudaErrors(cudaDeviceSynchronize());
}

这里envdim只是尺寸(所以是500x500)。内核本身:

__global__ void animKernel(uchar4 *optr, dim3 matdim)
{
    int x = threadIdx.x + blockIdx.x * blockDim.x;
    int y = threadIdx.y + blockIdx.y * blockDim.y;
    int offset = x + y * matdim.x;
    if (x < matdim.x && y < matdim.y)
    {
        // BLACK:
        optr[offset].x = 0; optr[offset].y = 0; optr[offset].z = 0;
    }
}

我做过的事:

  • cudaGraphicsResourceGetMappedPointer的size返回的值是1000000,对应于uchar4的500x500矩阵,所以这很好。
  • 每个内核都打印了它要写入的值和位置,这似乎没问题。
  • 为清晰的颜色播放alpha值,但这似乎没有做任何事情(还吗?)
  • 多次运行animate()函数。不知道为什么我认为这会有帮助,但我试过了…

所以我想我错过了一些东西,但我正在疯狂地寻找它。任何建议吗?帮助吗?

这又是一个我自己回答的问题!嗯,就像我想的,这是一行的问题。问题在于呈现调用本身。

配置很好,我对上面代码的一个问题是:我从未调用glDrawPixels() ,这是必要的,以便OpenGL驱动程序将共享缓冲区(GL_PiXEL_UNPACK_BUFFER_ARB)源复制到显示缓冲区。正确的呈现顺序是:

uchar4* devPtr;
size_t size;
// First clear the back buffer:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
checkCudaErrors(cudaGraphicsMapResources(1, &resourceID, NULL));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void**)&devPtr, &size, resourceID));
animate(devPtr); // This will call the kernel and do a sync (see later)
checkCudaErrors(cudaGraphicsUnmapResources(1, &resourceID, NULL));
// This is necessary to copy the shared buffer to display
glDrawPixels(fWidth, fHeight, GL_RGBA, GL_UNSIGNED_BYTE, 0);
// Swap buffers to bring back buffer forward:
SwapBuffers(m_hDC);

我要再次感谢Acade——呃,CUDA范例,对我的帮助。尽管书中的示例代码使用了GLUT(这对这个完全没用…),但书中引用了普通的gl函数。