Directx10和Directx11很多resource类都有个Map()函数,个人感觉它是一个蛮重要的CPU和GPU沟通桥梁。下面以ID3D11DeviceContext::Map()为例讲下。
ID3D11DeviceContext::Map官方解释是:ID3D11DeviceContext::Map Method Get a pointer to the data contained in a subresource, and deny the GPU access to that subresource.
1HRESULT Map( 2 ID3D11Resource *pResource, 3 UINT Subresource, 4 D3D11_MAP MapType, 5 UINT MapFlags, 6 D3D11_MAPPED_SUBRESOURCE *pMappedResource 7);
个人理解总结是当需要用CPU读写(GPU正在读写的)subresouce(最常用如buffer)时,就用Map()得到该subresource的pointer(D3D11_MAPPED_SUBRESOURCE*),然后将D3D11_MAPPED_SUBRESOURCE::pData强制转换成CPU理解的类型(struct,class),CPU就可以对得到的struct*或class*读写了。
1// 附录D3D11_MAPPED_SUBRESOURCE结构体 2typedef struct D3D11_MAPPED_SUBRESOURCE 3{ 4 void *pData; 5 UINT RowPitch; 6 UINT DepthPitch; 7}D3D11_MAPPED_SUBRESOURCE;
Map用法总结1: debug时用CPU读写GPU之前读写的buffer(比如GPU计算输出的结果),然后再通过CPU输出来检验对错。
1//将GPU读或读写的buffer *pGBuffer拷贝到可给CPU读的buffer并返回,以便调试 2 3ID3D11Buffer* GPUBaseApp::CreateAndCopyToDebugBuf(ID3D11Buffer* pGBuffer) 4{ 5 D3D11_BUFFER_DESC bufferDesc; 6 ZeroMemory(&bufferDesc,sizeof(bufferDesc)); 7 pGBuffer->GetDesc(&bufferDesc); 8 bufferDesc.CPUAccessFlags=D3D11_CPU_ACCESS_READ; 9 bufferDesc.Usage=D3D11_USAGE_STAGING; 10 bufferDesc.BindFlags=0; 11 bufferDesc.MiscFlags=0; 12 13 ID3D11Buffer* pDebugBuffer=NULL; 14 15 if( SUCCEEDED(m_pDevice->CreateBuffer(&bufferDesc,NULL,&pDebugBuffer)) ) 16 { 17 m_pDeviceContext->CopyResource(pDebugBuffer,pGBuffer); 18 } 19 return pDebugBuffer; 20} 21 22HRESULT Function() 23{ 24 //看Direct Compute的计算结果 25 ID3D11Buffer* debugOutBuffer=NULL; 26 ID3D11Buffer* debugInBuffer=NULL; 27 28 debugOutBuffer=CreateAndCopyToDebugBuf(m_pOutBuffer); 29 debugInBuffer=CreateAndCopyToDebugBuf(m_pInputBuffer); 30 31 VoronoiOutBufType* pOut=NULL; 32 VoronoiInBufType* pIn=NULL; 33 34 D3D11_MAPPED_SUBRESOURCE mappedOutResource; 35 D3D11_MAPPED_SUBRESOURCE mappedInResource; 36 37 m_pDeviceContext->Map(debugOutBuffer,0,D3D11_MAP_READ,0,&mappedOutResource); 38 pOut=(VoronoiOutBufType*)mappedOutResource.pData; 39 40 m_pDeviceContext->Map(debugInBuffer,0,D3D11_MAP_READ,0,&mappedInResource); 41 pIn=(VoronoiInBufType*)mappedInResource.pData; 42 43 //printf("OutBuffer的结果如下:\n"); 44 //for(int i=0;i<30;i++) 45 // printf("%d %f\n",pOut[i].index,pOut[i].dist); 46 47 m_pDeviceContext->Unmap(debugOutBuffer,0); 48 SAFE_RELEASE(debugOutBuffer); 49 50 m_pDeviceContext->Unmap(debugInBuffer,0); 51 SAFE_RELEASE(debugInBuffer); 52} 53
Map用法2: 更新Constant buffer,把CPU中新得到的CB_MouseInfo类型数据mouseInfo写入GPU中Constant Buffer。
1struct CB_MouseInfo 2{ 3 UINT x; 4 UINT y; 5 UINT btDown; 6}; 7 8CB_MouseInfo mouseInfo; 9 10HRESULT GPUBaseApp::UpDateMouseInfoCB() 11{ 12 HRESULT hr=S_OK;
14 D3D11_MAPPED_SUBRESOURCE subData;
16ZeroMemory(&subData,sizeof(subData));
17m_pDeviceContext->Map(m_pConstantBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&subData); 19 20 memcpy(subData.pData,&mouseInfo,sizeof(CB_MouseInfo)); 21 22 m_pDeviceContext->Unmap(&subData,0); 23 24 return hr; 25}
注意点,当调用了Map(),最后记得调用ID3D11DeviceContext::Unmap Method使得GPU重新获取对该resouce的读写权。
|