DX12学习笔记(龙书)(小点5:常量缓冲区的创建)

常量缓冲区 constant buffer:

  1. 类型:ID3D12Resource
  2. 用处:被着色器程序所引用。比如我们有一个局部空间-齐次裁剪空间,每秒都要更新的话。
  3. 和顶点、索引缓冲区的区别:常量缓冲区由cpu每帧更新一次。
  4. 方式:把常量缓冲区创建到【上传堆】(而非【默认堆】)。
  5. 要求:缓冲区的大小必为硬件最小分配空间(256B)的整数倍。
  6. 可以储存多个相同类型。
    创建一个缓冲区资源,并利用它来储存NumElements个常量缓冲区。

struct ObjectConstants
{DirectX::XMFLOAT4X4 WorldViewProj = MathHelper::Identity4x4();}

UINT mElementByteSize=d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));//它会算成256B的整数倍。
ComPtr<ID3D12Resource> mUploadCBuffer; //这里定义了一个缓冲区资源
device->CreateCommittedResource(
	&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),//这里表示创建到【上传堆】
	D3D12_HEAP_FLAG_NONE,
	&CD3DX12_RESOURCE_DESC::Buffer(mElementByteSize * NumElements) //这里是指定了大小
	D3D12_RESOURCE_STATE_GENERIC_READ,
	nullptr,
	IID_PPV_ARGS(&mUploadCBuffer);
)

DirectX12新引进了一条可用于定义常量缓冲区的HLSL语法:

struct ObjectConstants
{
	float4x4 gWorldViewProjl;
	uint matIndex;
}
ConstantBuffer<ObjectConstants> gObjConstants :register(b0);

我们可以利用下列获取数据成员的语法,在着色器里访问常量缓冲区中国的各个字段:

uint index =gObjConstants.matIndex;

7. 我们可以通过CPU为常量缓冲区资源更新数据,
找到指向新数据的指针。 mMappedData
用memcpy函数将数据从系统内存(system memory CPU段控制的内存) 复制到常量缓冲区。

ComPtr<ID3D12Resource> mUploadBuffer;
BYTE* mMappedData=nullptr;
mUploadBuffer->Map(0,nullptr,reinterpret_cast<void**>(&mMappedData));
memcpy(mMappedData,&data,dataSizeInBytes);

//当常量缓冲区更新完成后,我们应在释放映射内存之前对其进行Unmap(取消映射)操作:
if(mUploadBuffer != nullptr)
	mUploadBuffer->Umap(0,nullptr)

DirectX12龙书里做了便捷式的类,在UploadBuffer.h文件夹中。实现了上传缓冲区资源的构造、析构函数、处理资源的映射、取消映射操作,还提供了CopyData方法来更新缓冲区内的特定元素。
在需要通过CPU修改上传缓冲区数据的时候(比如观察矩阵有了变化),便可以使用CopyData.

最后一个例子:我们要存一个矩阵到常量缓存区中。


XMMATRIX worldViewProj =world*view*proj;
ObjectConstants objConstant;
XMStoreFloat4x4(&objConstants.WorldViewProj,XMMatrixTranspose(worldViewProj));
mObjectCB->CopyData(0,objConstants);

你可能感兴趣的:(DX12学习笔记(龙书)(小点5:常量缓冲区的创建))