3.10_图形互操作性

3.10 图形互操作性

图形互操作性函数族使得CUDA可以读写属于OpenGL或Direct3D API的内存。如果应用程序可以通过主机内存共享数据获取可以接受的性能,这些API就没有存在的必要了。但是本地内存的带宽可以高达140G/s,而事实上PCIe总线带宽却很少能达到6G/s,在可能的情况下让应用程序保持数据在GPU上是十分重要的。使用这些图形交互操作API,CUDA内核可以写入数据到图像和纹理中,随后合并到由OpenGL和Direct 3D执行的图形输出。

因为图形和CUDA应用程序必须在低层协调以开启互操作性。应用程序必须发出信号表明它们的意图来尽早执行图形交互操作。特别是,必须通过调用特殊的上下文创建API,例如cuD3D10CtxCreate()或CUDAGLSetDevice(),通知CUDA上下文,让它知道会与给定的API交互。

在驱动程序之间的协调同样会促成在图形API和CUDA之间的资源共享,按以下的两个步骤进行:

1)注册:是一个成本高昂的底层操作,该操作把开发者需要共享资源的意图告诉给底层驱动程序,可能会引发所需要资源的移动或锁定。

2)映射:一个预期会频繁出现的轻量级操作。

在CUDA的早期版本中,图形互操作API按四种不同的图形API(OpenGL、Direct3D 9、Direct3D 10和Direct3D 11)严格的分离开。例如,对Direct3D 9互操作中,下列的函数可以配合使用:

  • cuD3D9RegisterResource()/cudaD3D9RegisterResource()
    cuD3D9MapResources()/cudaD3D9MapResources()
    cuD3D9UnmapResources()/cudaD3D9UnmapResources()
    cuD3D9UnregisterResource()/cudaD3D9UnregisterResource()

因为实际的硬件能力是相同的,忽略访问它们的API,许多函数被在CUDA 3.2中予以合并。注册函数仍保持着API分离性,因为它们在绑定时需要区分API。但映射、解映射和移除注册资源这些函数变为公用的了,对应上述函数的CUDA 3.2 API如下:

  • cuD3D9RegisterResource()/cudaD3D9RegisterResource()
    cuGraphicsMapResources()/cudaGraphicsMapResources()
    cuGraphicsUnmapResources()/cudaGraphicsUnmapResources()
    cuGraphicsUnregisterResource()//cudaGraphicsUnregisterResource()

Direct3D 10中的互操作API与上述函数全部类同,唯一不同的是开发者必须使用

cuD3D10RegisterResource()/cudaD3D10RegisterResource()代替cuD3D9*形式。

CUDA 3.2同样增加了使用图形API访问CUDA数组形式的纹理功能。在Direct 3D中,纹理只是资源的一种,可以被IDirect3DResource9*(或IDirect3DResource10*,等)引用。而在OpenGL中,提供了一个独立的函数:cuGraphicsGLRegisterImage()。