如何使用OpenCL以零拷贝方式直接写入linux帧缓冲区?

如何使用OpenCL以零拷贝方式直接写入linux帧缓冲区?,opencl,framebuffer,memory-mapping,zero-copy,Opencl,Framebuffer,Memory Mapping,Zero Copy,我正在使用OpenCL进行一些图像处理,并希望使用它将RGBA图像直接写入帧缓冲区。工作流程如下图所示: 1) 将帧缓冲区映射到用户空间 2) 使用带有“CL_MEM_ALLOC_HOST_PTR”标志的clCreateBuffer创建OpenCL缓冲区 3) 使用clEnqueueMapBuffer将结果映射到帧缓冲区 但是,它不起作用。屏幕上什么也没有。然后我发现从帧缓冲区映射的虚拟地址与映射到OpenCL的虚拟地址不同。有没有人将数据从GPU零拷贝移动到帧缓冲区?有没有人可以帮助我使用什么

我正在使用OpenCL进行一些图像处理,并希望使用它将RGBA图像直接写入帧缓冲区。工作流程如下图所示:

1) 将帧缓冲区映射到用户空间

2) 使用带有“CL_MEM_ALLOC_HOST_PTR”标志的clCreateBuffer创建OpenCL缓冲区

3) 使用clEnqueueMapBuffer将结果映射到帧缓冲区

但是,它不起作用。屏幕上什么也没有。然后我发现从帧缓冲区映射的虚拟地址与映射到OpenCL的虚拟地址不同。有没有人将数据从GPU零拷贝移动到帧缓冲区?有没有人可以帮助我使用什么方法

一些关键代码:

if ((fd_fb = open("/dev/fb0", O_RDWR, 0)) < 0) {
    printf("Unable to open /dev/fb0\n");
    return -1;
}
fb0 = (unsigned char *)mmap(0, fb0_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_fb, 0);
...
cmDevSrc4 = clCreateBuffer(cxGPUContext, CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR, sizeof(cl_uchar) * imagesize * 4, NULL, &status);
...
fb0 = (unsigned char*)clEnqueueMapBuffer(cqCommandQueue, cmDevSrc4, CL_TRUE, CL_MAP_READ, 0, sizeof(cl_uchar) * imagesize * 4, 0, NULL, NULL, &ciErr);
if((fd_fb=open(“/dev/fb0”,O_RDWR,0))<0){
printf(“无法打开/dev/fb0\n”);
返回-1;
}
fb0=(无符号字符*)mmap(0,fb0大小,保护读取,保护写入,映射共享,fd\u fb,0);
...
cmDevSrc4=clCreateBuffer(cxGPUContext、CL\u MEM\u READ\u WRITE、CL\u MEM\u ALLOC\u HOST\u PTR、sizeof(CL\u uchar)*imagesize*4、NULL和status);
...
fb0=(无符号字符*)ClenqueueEmapBuffer(cqCommandQueue,cmDevSrc4,CL_TRUE,CL_MAP_READ,0,sizeof(CL_uchar)*图像大小*4,0,NULL,NULL,&ciErr);

对于带有现有缓冲区的零拷贝,您需要在
clCreateBuffer()
函数调用中使用
CL\u MEM\u use\u HOST\u PTR
标志。此外,还需要将指向现有缓冲区的指针作为倒数第二个参数


我不知道linux帧缓冲区内部是如何工作的,但即使从设备到主机的零拷贝也可能导致额外的数据拷贝到GPU进行渲染。因此,您可能希望直接使用OpenGL渲染OpenCL缓冲区。查看OpenCL的
cl\u khr\u gl\u共享
扩展。

我还不知道OpenCL,我只是在搜索如何从中写入帧缓冲区,然后点击你的帖子。打开它并像在代码中那样映射它看起来不错

我已经用CPU做到了:

这并不总是有效的,这取决于计算机。我使用的是旧的Dell Latitude D530,不仅无法写入帧缓冲区,而且没有GPU,因此使用OpenCL与使用CPU相比没有任何优势。如果你有一个/dev/fb0,你可以在屏幕上用

cat /dev/random > /dev/fb0
那么你可能会有机会从OpenCL。使用Mali,至少有一种方法可以将指针从CPU传递到GPU。您可能需要添加一些偏移量(我认为覆盆子圆周率是真的)。它可以由Xorg进行双缓冲,有很多原因导致它无法工作