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:使用灰度图像作为纹理的主要内容,如果未能解决你的问题,请参考以下文章
matlab中如何将灰度图转化为二值黑白图像?敬请各位大侠指点!
python使用OpenCV加载图像为灰度图(图像原本为彩色图)并可视化灰度图像(Load image as grayscale and show image)