体绘制加速技术之数据异步传输

来源:互联网 发布:淘宝秒杀在哪 编辑:程序博客网 时间:2024/05/14 15:44

异步数据传输允许在不需要CPU的参与下进行数据传输,比如在数据传输的时候CPU可以继续完成其他任务。当CPU启动传输操作之后,接下来由DMA控制器来完成传输操作。

如果体数据比较大,无法全部存储在GPU内存空间中,那么数据块在渲染过程中需要不断被重新加载到GPU内存当中。为了在加载的过程中获得最佳性能,数据块需要在主存中以某种方式存放,以使得他们能够被当做连续块传输到GPU中。

当采用glTexSubImage3D()等命令进行纹理数据传输时,CPU会进行数据拷贝直至所有数据都被传输到GPU中。这样,导致的结果是接下来的所有OpenGL命令都停止执行了。OpenGL中PBO(pixel buffer object)允许用DMA方式来以异步方式把数据传输到GPU,这样在进行数据传输的时候,CPU不会停止执行其他任务。但是,前提是数据必须已经以GPU所需的内部格式存放在AGP memory中。

PBO介绍参考:PBO(Pixel Buffer Object)

关于AGP memory可以参考:AGP

但是,有一些图形卡使用一种重新安排的内部格式来存储三维纹理以增加相邻数据的局部性。这就导致了CPU必须在把数据块加载到GPU之前在主存中重新安排数据格式。一种可能的解决这个问题的方法是在主存中以GPU内部格式存放数据,然后通知驱动数据已经以所需要的格式准备好。但是目前没有支持此功能的OpenGL官方机制。

NPOT(non-power-of-two)纹理即维数不是2的整数次幂的纹理在被加载到GPU之前不需要被重新安排格式。因此,NPOT纹理能够以接近理论极限的带宽异步传输数据。

NPOT纹理详细资料可参考:NPOT Texture

需要注意的是这样的NPOT纹理应该比较小,这样不会产生因为视角的不同性能不同的情况。推荐使用接近64*64*64的体数据比如64*64*63.


下面给出一段采用异步传输方式加载体数据的示例代码。data是从某个raw体数据文件中读取到的数据。

[cpp] view plaincopyprint?
  1.        //asynchronous data upload : using PBO  
  2. GLuint texBuffer;  
  3. //create and bind texture image buffer object  
  4. glGenBuffers(1,&texBuffer);  
  5. glBindBuffer(GL_PIXEL_UNPACK_BUFFER,texBuffer);  
  6. glBufferData(GL_PIXEL_UNPACK_BUFFER,size,NULL,GL_STREAM_DRAW);  
  7. //map the texture image buffer  
  8. void *pboMemory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);  
  9. memcpy(pboMemory,data,size);  
  10. if (!glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER))  
  11. {  
  12.     cout << "ERROR : Unmap PBO failed" << endl;  
  13.     exit(1);  
  14. }  
  15. glTexImage3D(GL_TEXTURE_3D, 0, GL_INTENSITY, WIDTH, HEIGHT, DEPTH, 0,   
  16.     GL_LUMINANCE, GL_UNSIGNED_BYTE,BUFFER_OFFSET(0));