在C++与Hlsl绑定Cbuffer数据的时候,非常容易出错,出错的根本原因是C++对数据结构内存的分配与hlsl不同。
重要:HLSL的结构体struct其实并不管你是一个变量还是几个变量,它就是按照一次放满一个float4的内存长度,多少变量都往一个float4里面塞,塞满了再接着塞下一个float4。测试结果显示:cbuffer的长度必须是float4的整数倍才行,不知道float+float3的这种组合是否可以正常获取数据,也不清楚float+float+float3+float3这种组合能不能正常分配到数据,关键取决于GPU的内存分配规则。
在进入渲染管道后,如果CPU出现了要修改buffer或者其它类型数据的时候,不可能重新new一个buffer塞进去。这个时候需要一种机制能够修改已经进入管道的数据,这种机制就是Map和Unmap机制。其本质就是对数据加锁导致GPU不能修改,然后CPU对其进行修改,修改完后还原。
Map:获取的数据中包含一个子资源的指针,并拒绝该子资源的访问GPU。
HRESULT Map( ID3D11Resource *pResource, // 需要修改的源,类型不是buffer,这说明map还可以修改状态值。 UINT Subresource, // 子资源的位置 D3D11_MAP MapType, // 这是一个枚举类型:D3D11_MAP_WRITE_DISCARD,D3D11_MAP_WRITE_NO_OVERWRITE UINT MapFlags, // 一个可选标准,不懂 D3D11_MAPPED_SUBRESOURCE *pMappedResource // 返回的内容 ); typedef struct D3D11_MAPPED_SUBRESOURCE { void *pData; // 传说中我们可以修改的东东 UINT RowPitch; // 对某一行的某个像素 UINT DepthPitch; // 对应某一行,这两个参数最好不用 } D3D11_MAPPED_SUBRESOURCE;
Unmap:无效的指针指向的资源,并重新启用GPU的访问该资源。
void Unmap( ID3D11Resource *pResource, UINT Subresource );
例子:
m_immediateContext->Map(matrixBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); // 得到const buffer指针. dataPtr = (TransitionMatrix*)mappedResource.pData; // 设置transform矩阵. D3DXMATRIX worldMatrix; D3DXMatrixIdentity(&worldMatrix); Matrix4 transform = D3DXMatrix2Matrix4(worldMatrix) * cameraManager->getView() * cameraManager->getPerspective();//D3DXMatrix2Matrix4(viewMatrix) cameraManager->getView() dataPtr->transform = transform.Transpose(); // 矩阵需要转置 m_immediateContext->Unmap(matrixBuffer, 0);
此文主要是想演示一下如何修改资源。