CUDA/OpenGL InterOp:使用灰度图像作为纹理

Posted

技术标签:

【中文标题】CUDA/OpenGL InterOp:使用灰度图像作为纹理【英文标题】:CUDA/OpenGL InterOp: Using Grayscale Image as Texture with 【发布时间】:2017-10-22 12:13:39 【问题描述】:

我将 CUDA OpenGL 互操作用于灰度图像。我在 CPU 上有一个大小为 imgW x imgH 的灰度图像。我打算将图像复制到 GPU 内存,然后使用 CUDA 更新它。同时,OpenGL 应该渲染更新后的图像。

我有以下有效的代码:

//img: a grayscale image on the CPU
//Allocate Buffer using OpenGL
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, __bufferIdMain);
glBufferData(GL_PIXEL_UNPACK_BUFFER, imgW * imgH * 4, 0, GL_DYNAMIC_COPY); //Must allocate 4 times the memory required, otherwise don't work
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);

checkCudaErrors(cudaGraphicsGLRegisterBuffer(&__cudaVboResourceMain, __bufferIdMain, vbo_res_flags));

//Copy grayscale image to GPU memory
checkCudaErrors(cudaGraphicsMapResources(1, &__cudaVboResourceMain, 0));
checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void ** ) &dptr, &num_bytes, __cudaVboResourceMain));
cudaMemcpy(dptr, img, imgW * imgH, cudaMemcpyHostToDevice); //CUDA can use dptr

//Generate Texture from Buffer
glGenTextures(1, &__textureIdMain);
glBindTexture( GL_TEXTURE_2D, __textureIdMain);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, imgW, imgH, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);

我的显示功能以及定时器功能只是绘制纹理。代码有效,但我唯一的问题是,调用glBufferData(GL_PIXEL_UNPACK_BUFFER, imgW * imgH * 4, 0, GL_DYNAMIC_COPY); 时需要使用 4 倍以上的内存。我尝试仅使用 imgW * imgH 而不是 imgW * imgH * 4 但不渲染图像。请注意,我只将 imgW * imgH 字节复制到 GPU 内存。有没有办法在 GPU 上使用更少的内存来渲染图像?

【问题讨论】:

能否提供更多的数据,例如bufferIdMain和cudaVboResourceMain的配置(VOB代表Vertex Buffer Object吗?) 【参考方案1】:

根据您的描述,您正在对顶点缓冲区对象进行操作,或者至少 API 是这样认为的。你要使用cudaGraphicsGLRegisterImage,描述here,确实可以使用obe组件纹理:

也可以通过 cudaMemcpy2D() 调用读取和写入数组。 cudaGraphicsGLRegisterImage() 支持所有带有 1、2、 或 4 个组件和一个内部类型的浮点数(例如 GL_RGBA_FLOAT32), 标准化整数(例如,GL_RGBA8、GL_INTENSITY16)和非标准化 整数(例如,GL_RGBA8UI) - 更多信息请参见: http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#opengl-interoperability

文档中提供的示例是针对顶点的,实际上是在 2D 地图中,但仍然是顶点。

【讨论】:

我使用 GL_PIXEL_UNPACK_BUFFER 进行注册。我使用cudaGraphicsGLRegisterBuffer(&__cudaVboResourceMain, __bufferIdMain, vbo_res_flags) 之类的东西来注册缓冲区。然而,我面临的问题是由于对齐。以后我会尝试使用cudaGraphicsGLRegisterImage【参考方案2】:

好的,我找到了答案。主要问题是,GL_PIXEL_UNPACK_BUFFER 与 4 个字节对齐。我在创建缓冲区之前添加了以下行。现在我可以分配所需的内存了。

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBufferData(GL_PIXEL_UNPACK_BUFFER, imgW * imgH, 0, GL_DYNAMIC_COPY); // Now only using just the necessary amount of memory

【讨论】:

以上是关于CUDA/OpenGL InterOp:使用灰度图像作为纹理的主要内容,如果未能解决你的问题,请参考以下文章

2021-08-16 灰度图rgb<>yuv

Unity中实现灰度图效果

matlab中如何将灰度图转化为二值黑白图像?敬请各位大侠指点!

python opencv将图片转为灰度图

python使用OpenCV加载图像为灰度图(图像原本为彩色图)并可视化灰度图像(Load image as grayscale and show image)

Inkscape svg彩色图转灰度图