【转】dx11 devicecontext->map

 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.

 

  Syntax
HRESULT Map(
    ID3D11Resource *pResource,
    UINT Subresource,
    D3D11_MAP MapType,
    UINT MapFlags,
    D3D11_MAPPED_SUBRESOURCE *pMappedResource
);

 


  个人理解总结是当需要用CPU读写(GPU的)subresouce(最常用如buffer)时,就用Map()得到该subresource的pointer(D3D11_MAPPED_SUBRESOURCE*),然后将D3D11_MAPPED_SUBRESOURCE::pData强制转换成CPU理解的类型(struct,class),CPU就可以对得到的struct*或class*读写了。

 

附录D3D11_MAPPED_SUBRESOURCE结构体
typedef struct D3D11_MAPPED_SUBRESOURCE
    {
    void *pData;
    UINT RowPitch;
    UINT DepthPitch;
    }  D3D11_MAPPED_SUBRESOURCE;

 

 

 

Map函数使用的几个经典场景1:debug时用CPU读写GPU之前读写的buffer(比如GPU计算输出的结果),然后再通过CPU输出来检验对错。
//将GPU读或读写的buffer *pGBuffer拷贝到可给CPU读的buffer并返回,以便调试
ID3D11Buffer* GPUBaseApp::CreateAndCopyToDebugBuf(ID3D11Buffer* pGBuffer)
{
 D3D11_BUFFER_DESC bufferDesc;
 ZeroMemory(&bufferDesc,sizeof(bufferDesc));
 pGBuffer->GetDesc(&bufferDesc);
 bufferDesc.CPUAccessFlags=D3D11_CPU_ACCESS_READ;
 bufferDesc.Usage=D3D11_USAGE_STAGING;
 bufferDesc.BindFlags=0;
 bufferDesc.MiscFlags=0;
 
 ID3D11Buffer* pDebugBuffer=NULL;

 

 if( SUCCEEDED(m_pDevice->CreateBuffer(&bufferDesc,NULL,&pDebugBuffer)) )
 {
  m_pDeviceContext->CopyResource(pDebugBuffer,pGBuffer);
 }
 return pDebugBuffer;
}

 

HRESULT Function()
{
       ////////////////////////////////////////////////
       //==============================================
      /////////////////////////////////////////////////

 

 //===============================================
 //看Direct Compute的计算结果
 ID3D11Buffer* debugOutBuffer=NULL;
 ID3D11Buffer* debugInBuffer=NULL;

 

 debugOutBuffer=CreateAndCopyToDebugBuf(m_pOutBuffer);
 debugInBuffer=CreateAndCopyToDebugBuf(m_pInputBuffer);

 


 VoronoiOutBufType* pOut=NULL;
 VoronoiInBufType* pIn=NULL;

 

 D3D11_MAPPED_SUBRESOURCE mappedOutResource;
 D3D11_MAPPED_SUBRESOURCE mappedInResource;

 

 m_pDeviceContext->Map(debugOutBuffer,0,D3D11_MAP_READ,0,&mappedOutResource);
 pOut=(VoronoiOutBufType*)mappedOutResource.pData;

 

 m_pDeviceContext->Map(debugInBuffer,0,D3D11_MAP_READ,0,&mappedInResource);
 pIn=(VoronoiInBufType*)mappedInResource.pData;

 

 //printf("OutBuffer的结果如下:/n");
 //for(int i=0;i<30;i++)
 // printf("%d %f/n",pOut[i].index,pOut[i].dist);

 

 m_pDeviceContext->Unmap(debugOutBuffer,0);
 SAFE_RELEASE(debugOutBuffer);

 

 m_pDeviceContext->Unmap(debugInBuffer,0);
 SAFE_RELEASE(debugInBuffer);

 

 //===============================================

 

 

 

       ////////////////////////////////////////////////
       //==============================================
      /////////////////////////////////////////////////

 

}

 


Map函数使用的几个经典场景2:更新GPU Shader中Constant buffer,把CPU中新的数据struct CB_MouseInfo mouseInfo写入GPU中Constant Buffer。
struct CB_MouseInfo
{
 UINT x;
 UINT y;
 UINT btDown;
};

 

CB_MouseInfo mouseInfo;

 

HRESULT GPUBaseApp::UpDateMouseInfoCB()
{
 HRESULT hr=S_OK;

 

 D3D11_MAPPED_SUBRESOURCE subData;

 

 ZeroMemory(&subData,sizeof(subData));

 

 m_pDeviceContext->Map(m_pConstantBuffer,0,D3D11_MAP_WRITE_DISCARD,0,&subData);

 

 memcpy(subData.pData,&mouseInfo,sizeof(CB_MouseInfo));

 

 m_pDeviceContext->Unmap(&subData,0);

 

 return hr;
}

 

注意点,当调用了Map(),最后记得调用ID3D11DeviceContext::Unmap Method使得GPU重新获取对该resouce的读写权。
Invalidate the pointer to a resource and re-enable the GPU's access to that resource.

 

Syntax
void Unmap(
    ID3D11Resource *pResource,
    UINT Subresource
);

 

Parameters:

 

pResource 
ID3D11Resource 
A pointer to a ID3D11Resource interface.

 

Subresource 
UINT 
A subresource to be unmapped.

 

 

 

 

posted @ 2012-09-26 11:01  凌霄神采奕奕  阅读(1067)  评论(0编辑  收藏  举报