最近在学习opengl和cuda混合编程。
使用的库是glfw3.3和glew2.1.0。cuda11.4
glDrawPixels()不能绘制图片是为什么啊?无论是把内存中的数组作为数据源还是绑定了一个有数据的pbo,调用glDrawPixels()之后输出都是一整块黑色。
代码节选如下(文件很多,只挑了相关的贴上):
global void kernel(GLubyte* inPtr, GLubyte* outPtr) {
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
outPtr[(x + 1000 * y) * 4 + 0] = 0;
outPtr[(x + 1000 * y) * 4 + 1] = 255;
outPtr[(x + 1000 * y) * 4 + 2] = 255;
outPtr[(x + 1000 * y) * 4 + 3] = 255;
if ((x == 990) && (y == 990)) {
printf("Pixel(%d, %d)\n"
"Input:R:%d\tG:%d\tB:%d\tA:%d\n",
x, y,
inPtr[(x + 1000 * y) * 4 + 0],
inPtr[(x + 1000 * y) * 4 + 1],
inPtr[(x + 1000 * y) * 4 + 2],
inPtr[(x + 1000 * y) * 4 + 3]);
printf("Output:R:%d\tG:%d\tB:%d\tA:%d\n\n",
outPtr[(x + 1000 * y) * 4 + 0],
outPtr[(x + 1000 * y) * 4 + 1],
outPtr[(x + 1000 * y) * 4 + 2],
outPtr[(x + 1000 * y) * 4 + 3]);
}
}
/设置PBO/
void windowObject::setPBO(void) {
glGenBuffers(2, PBO);
/分配显存空间/
/PBO[0]用于存储帧缓存数据/
glBindBuffer(GL_PIXEL_PACK_BUFFER, PBO[0]);
glBufferData(GL_PIXEL_PACK_BUFFER, width * height * 4/RGBA/, NULL, GL_DYNAMIC_READ);
/把缓冲区作为资源分享给CUDA,该缓存区可读可写/
/* 这个绑定缓存区必须在glBufferData()后面逐个共享,不能先都绑定
* BufferData再一起共享显存
/
checkCUDAError(cudaGraphicsGLRegisterBuffer(&inputRes, PBO[0], cudaGraphicsMapFlagsNone));
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
/PBO[1]用于写入像素映射后的数据/
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO[1]);
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_DYNAMIC_DRAW);
checkCUDAError(cudaGraphicsGLRegisterBuffer(&outputRes, PBO[1], cudaGraphicsMapFlagsNone));
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
/像素映射的主要过程/
void windowObject::pixelMapping(void) {
/从后缓存中读取数据/
glReadBuffer(GL_BACK);
/绑定像素读取PBO/
glBindBuffer(GL_PIXEL_PACK_BUFFER, PBO[0]);
/像素读取,从左下(0,0)坐标读widthheight的一整个画面/
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
/读完解绑PBO/
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
/开启像素映射/
checkCUDAError(cudaGraphicsMapResources(1, &inputRes, NULL));
checkCUDAError(cudaGraphicsMapResources(1, &outputRes, NULL));
checkCUDAError(cudaGraphicsResourceGetMappedPointer((void**)&d_inPBO, &inSize, inputRes));
checkCUDAError(cudaGraphicsResourceGetMappedPointer((void**)&d_outPBO, &outSize, outputRes));
}
/像素取消映射/
void windowObject::pixelUnmapping(void) {
checkCUDAError(cudaGraphicsUnmapResources(1, &inputRes, NULL));
checkCUDAError(cudaGraphicsUnmapResources(1, &outputRes, NULL));
}
/绘制映射后的图片/
void windowObject::drawPixels(void) {
glDrawBuffer(GL_BACK);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, PBO[1]);
//glRasterPos2i(0, 0);
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
/绘制完毕后解绑/
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
}
int main(int argc, char* argv[])
{
...
/设置PBO/
/1个窗口有2个PBO,一个用于读取帧缓存,经过像素映射到另一个PBO,再回传绘制到帧缓存/
/像素映射过程可以用CUDA并行计算/
window[0].setPBO;
/*设置视口数量*/
window[0].setViewports(1, 1);
/*激活MSAA*/
glEnable(GL_MULTISAMPLE);
/*开启深度测试*/
glEnable(GL_DEPTH_TEST);
/*主循环*/
while (!glfwWindowShouldClose(window[0].windowPtr)) {
/*设置清空时的背景色*/
glClearColor(0.2f, 0.5f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
...
/*像素映射渲染*/
window[0].pixelMapping();
/*调用CUDA核函数进行像素映射*/
kernel <<<window[0].gridSize, window[0].blockSize >>> (window[0].d_inPBO, window[0].d_outPBO);
/*同步主机和设备*/
checkCUDAError(cudaDeviceSynchronize());
/*像素取消映射*/
window[0].pixelUnmapping();
/*像素绘制*/
window[0].drawPixels();
/*完成像素映射后才交换缓存区*/
glfwSwapBuffers(window[0].windowPtr);
/*键盘和鼠标输入*/
window[0].input(model[0]);
/*检查是否触发了事件(键盘输入、鼠标移动等)*/
glfwPollEvents();
}
...
}
结果如下:
为了debug,重新用glRasterPos2i设定了绘制起点,得到下面的结果:
可以发现问题就是glDrawPixels()画了个寂寞。 。是这个函数使用的时候有什么注意事项我给漏了吗。。。