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

时间:2017-05-22 18:20:22

标签: opengl cuda

我正在使用CUDA OpenGL interop来获得灰度图像。我在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上使用更少的内存来渲染图像?

2 个答案:

答案 0 :(得分: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地图,但顶点仍然是。

答案 1 :(得分:1)

好的,我找到了答案。主要问题是,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