利用D3D抓取GPU数据

2014/09/19

(转载自:http://blog.csdn.net/wchm_seu/article/details/5832829)

microsoft 提供的D3D SDK是用来进行3D建模和利用GPU运算的一组接口的集合,

D3D SDK至少有两个优点:

1、提供了一种3D建模的构架,程序员可以很容易的用这种构架来建模自己的3D模型

2、提供了一种GPU和CPU并行运算的解决方案,,为提供应用程序的性能提供了一种思路

这些对于D3D 程序员应该并不陌生,具体可以参见Direct 3D SDK文档。

 

这篇文章主要想讲一个在D3D编程中经常遇到的一个问题,从GPU中把数据取出,存入本地磁盘中。这个功能的应用也应该比较常见,例如保存游戏录像视频等。实现GPU to CPU拷贝的D3D 方法还是比较多的,但对于视频转存来说,能达到实时转存效果才有真正的利用价值。

 

这里首先简要介绍一下D3D 渲染的基本流程:

      1. D3D setting states//设置渲染环境

      2. g_pd3dDevice->beginscene();

      3. D3D 管线渲染

      4. g_pd3dDevice->EndScene();

 

至此,D3D的渲染过程已经结束,渲染处理的最终数据被存于D3D surface(这是在GPU中开辟的存储区域), 下面可以根据具体的需求来对该surface进行后处理:

1 直接显示:g_pd3dDevice->present();

2 转存到本地磁盘,即GPU to CPU的copy.

 

这里给出比较常见的一种处理方法:

g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&pBackbuffer);

        pBackbuffer->LockRect(&Source,NULL,0);

copy(Dest,Source);

pBackbuffer->UnLock();

 

这种方法缺点很严重,就是由于IPtrD3dsurface lock的内存是位于显卡中,这样在做copy(Dest,Source)的时候,非常缓慢,基本无法实现实时转存的要求。

 

那microsoft有没有提供更好的解决方案呢?哈哈,答案是肯定的,直接上代码:

 

g_pd3dDevice->GetBackBuffer(0,0,D3DBACKBUFFER_TYPE_MONO,&pBackbuffer);

 

g_pd3dDevice->CreateOffscreenPlainSurface( d3dpp.BackBufferWidth,

												d3dpp.BackBufferHeight,
												d3dpp.BackBufferFormat,
												D3DPOOL_SYSMEM,
												&g_p2DSurface,
												NULL);
 
 

g_pd3dDevice->GetRenderTargetData(pBackbuffer, g_p2DSurface);

 

  g_p2DSurface->LockRect(&Source,NULL,0);

          copy(Dest,Source);

          g_p2DSurface->UnLock();

这段代码的处理速度是很赞的,对于正在急于寻找处理方法而又看到我这篇文章的朋友将是很幸运的。
至于其深层的原因,关键还是取决去CreateOffscreenPlainSurface函数,这个函数在内存中开辟了一块区域g_p2DSurface,microsoft可能采取了某种策略使得这块内存区域是最利于GPU拷贝的。真正的本质原因由于没有看过源代码,也不是很清楚。

你可能感兴趣的:(利用D3D抓取GPU数据)