在ManagedCUDA中将CUDA输出数组/表面绑定到GL纹理

时间:2016-03-26 19:00:19

标签: opengl cuda managed-cuda

我目前正在尝试将某种形式的输出从CUDA程序连接到GL_TEXTURE_2D以用于渲染。我并不担心CUDA的输出类型(无论它是阵列还是表面,我都可以调整程序)。

所以问题是,我该怎么做? (我当前的代码将输出数组复制到系统内存,并使用GL.TexImage2D再次将其上传到GPU,这显然非常低效 - 当我禁用这两段代码时,它每秒执行大约300次内核执行高达400)

我已经有了一些测试代码,至少将GL纹理绑定到CUDA,但我甚至无法从中获取设备指针...

ctx = CudaContext.CreateOpenGLContext(CudaContext.GetMaxGflopsDeviceId(), CUCtxFlags.SchedAuto);

uint textureID = (uint)GL.GenTexture(); //create a texture in GL
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, width, height, 0, OpenTK.Graphics.OpenGL.PixelFormat.Rgba, PixelType.UnsignedByte, null); //allocate memory for the texture in GL

CudaOpenGLImageInteropResource resultImage = new CudaOpenGLImageInteropResource(textureID, CUGraphicsRegisterFlags.WriteDiscard, CudaOpenGLImageInteropResource.OpenGLImageTarget.GL_TEXTURE_2D, CUGraphicsMapResourceFlags.WriteDiscard); //using writediscard because the CUDA kernel will only write to this texture

//then, as far as I understood the ManagedCuda example, I have to do the following when I call my kernel
//(done without a CudaGraphicsInteropResourceCollection because I only have one item)
resultImage.Map();
var ptr = resultImage.GetMappedPointer(); //this crashes
kernelSample.Run(ptr); //pass the pointer to the kernel so it knows where to write
resultImage.UnMap();

尝试获取指针时抛出以下异常:

ErrorNotMappedAsPointer: This indicates that a mapped resource is not available for access as a pointer.

我需要做些什么来解决这个问题?

即使可以解决此异常,我如何解决问题的其他部分;也就是说,我如何在内核中使用获取的指针?我可以使用表面吗?将它作为任意数组(指针算术)访问?

编辑: 看看http://algovalley.com/java/generics.php示例,显然我甚至不需要在每次调用内核时映射资源,并调用render函数。但是,这会如何转化为ManangedCUDA?

1 个答案:

答案 0 :(得分:0)

感谢我发现的示例,我能够将其转换为ManagedCUDA(浏览源代码并摆弄后),我很高兴地宣布这确实将我的样本每秒从大约300提高到400 :)

显然需要使用3D数组(我没有在使用2D数组的ManagedCUDA中看到任何重载)但这并不重要 - 我只使用一个正好深1的3D数组/纹理。

__global__ void Sample() {
    ...
    surf3Dwrite(output, outputSurface, pixelX, pixelY, 0);
}

内核代码:     surface outputSurface;

UPDATE your_product_table SET product_price = (product_price * 2)