我正在使用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上使用更少的内存来渲染图像?
答案 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