BOOL CD3DCameraViewWnd::GetImageInfo(DWORD* pPixelBuffer, int& width,int& height)
{
BOOL result = FALSE;
IDirect3DSurface9 *_surfaceback = NULL;
if (FAILED(m_pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &_surfaceback)))
{
result = FALSE;
}
D3DSURFACE_DESC surfaceDesc;
if (!FAILED(_surfaceback->GetDesc(&surfaceDesc)))
{
width = surfaceDesc.Width;
height = surfaceDesc.Height;
}
D3DLOCKED_RECT lockedRect;
HRESULT hr = _surfaceback->LockRect( &lockedRect,0, 0); /* pointer to receive locked data指向申請到的內存區域*/ /* lock entire surface*/// no lock flags specified
if (!FAILED(hr))
{
pPixelBuffer = (DWORD*)lockedRect.pBits;
result = TRUE;
}
_surfaceback->UnlockRect();
_surfaceback->Release();
return result;
}
但是這樣存在著性能的問題,經測試獲取一幀需要200ms左右,為什么會存在這樣的問題?因為這邊有資源鎖定操作。
現在關鍵的問題就在于,資源鎖定的操作速度總是非常之慢.當然,你會跟我提, OpenGL似乎能夠快捷地完成這項任務.但是,在Direct3D中,資源鎖定操作確實是很慢的.這里面一個主要的原因是,API,驅動,以及硬件要處理一些不可回避的后臺操作.那就是GPU與CPU是并行運行的,若不加任何措施,將引起類似多線程程序同步時的競態條件的問題.
如果你試圖去修改的資源正同時被一個位于GPU處理序列中的指令使用,那么整個渲染流程就會因為你的資源鎖定而停頓或強制刷新(stalls and flushes).停頓(stall)會一直持續到你完成了對資源的修改并調用Unlock().而強制刷新(flush)則會要求GPU在你得到這個資源的訪問權之前完成目前所有的任務.
如何去解決這個問題?下面的參考資料中有一些解決方案,我沒有經過認真測試,我試了其中一個GetRenderTargetData 這樣的一種方法 ,感覺不太好用,why請看Reference3
下面給出我的解決方案
BOOL CD3DCameraViewWnd::GetImageInfo(DWORD* pPixelBuffer, int& width,int& height)
{
BOOL result = FALSE;
IDirect3DSurface9 *_surfaceback = NULL;
if (FAILED(m_pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &_surfaceback)))
{
result = FALSE;
}
D3DSURFACE_DESC surfaceDesc;
if (!FAILED(_surfaceback->GetDesc(&surfaceDesc)))
{
width = surfaceDesc.Width;
height = surfaceDesc.Height;
}
LPDIREC3DSURFACE9 surf;
if(FAILED(m_pDevice->CreateOffscreenPlainSurface(width, height,D3DFMT_A8R8G8B8,D3DPOOL_SYSTEMMEM, &surf,NULL)))
{
result = FALSE;
}
D3DXLoadSurfaceFromSurface(surf, NULL,NULL,_surfaceback,NULL,NULL,D3DX_FILTER_NONE,0);
D3DLOCKED_RECT lockedRect;
HRESULT hr = surf->LockRect( &lockedRect,0, 0); /* pointer to receive locked data指向申請到的內存區域*/ /* lock entire surface*/// no lock flags specified
if (!FAILED(hr))
{
pPixelBuffer = (DWORD*)lockedRect.pBits;
result = TRUE;
}
surf->UnlockRect();
surf->Release();
_surfaceback->Release();
return result;
}
參考資料:Reference1.http://www.cnblogs.com/mixiyou/archive/2010/02/25/1673060.html
Reference 2.http://www.cnblogs.com/mixiyou/archive/2010/02/25/1673425.html
Reference 3.http://blog.csdn.net/Nightmare/article/details/1707362
Reference 4.http://www.cnblogs.com/lancidie/archive/2011/3/14.html