I can't really seem to figure out how to bind two constant buffers to my shaders. I have them described like so. One in slot b0 and the other in slot b1.
cbuffer WVPData : register(b0)
{
matrix model;
matrix view;
matrix projection;
};
cbuffer DirLightData : register(b1)
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float3 Direction;
float pad;
};
Then for the root signature it's described like so.
CD3DX12_DESCRIPTOR_RANGE range[2];
CD3DX12_ROOT_PARAMETER parameter[1];
range[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0);
range[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 1);
parameter[0].InitAsDescriptorTable(_countof(range), range, D3D12_SHADER_VISIBILITY_ALL);
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | // Only the input assembler stage needs access to the constant buffer.
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS;
CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
descRootSignature.Init(_countof(parameter), parameter, 0, nullptr, rootSignatureFlags);
ComPtr<ID3DBlob> pSignature;
ComPtr<ID3DBlob> pError;
DX::ThrowIfFailed(D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf()));
DX::ThrowIfFailed(d3dDevice->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(), IID_PPV_ARGS(&mRootSignature)));
I believe that's correct. I think the problem I have is when I create the constant buffer and the cbv below. Specifically right under the "Describe and create the constant buffer view." comment. I don't really understand what's going on.
// Create a descriptor heap for the constant buffers.
{
D3D12_DESCRIPTOR_HEAP_DESC heapDesc = {};
heapDesc.NumDescriptors = 2;
heapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
// This flag indicates that this descriptor heap can be bound to the pipeline and that descriptors contained in it can be referenced by a root table.
heapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
DX::ThrowIfFailed(d3dDevice->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&mCbvHeap)));
mCbvHeap->SetName(L"Constant Buffer View Descriptor Heap");
}
// Create the constant buffer.
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&uploadHeapProperties,
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(CAlignedWVPDataSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&mWVPConstantBuffer)));
DX::ThrowIfFailed(d3dDevice->CreateCommittedResource(
&uploadHeapProperties,
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(CAlignedDirLightDataSize),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr,
IID_PPV_ARGS(&mDirLightConstantBuffer)));
// Describe and create a constant buffer view.
D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc[2];// = {};
cbvDesc[0].BufferLocation = mWVPConstantBuffer->GetGPUVirtualAddress();
cbvDesc[0].SizeInBytes = CAlignedWVPDataSize;
cbvDesc[1].BufferLocation = mDirLightConstantBuffer->GetGPUVirtualAddress();
cbvDesc[1].SizeInBytes = CAlignedDirLightDataSize;
CD3DX12_CPU_DESCRIPTOR_HANDLE cbvHandle0(mCbvHeap->GetCPUDescriptorHandleForHeapStart(), 0, 0);
d3dDevice->CreateConstantBufferView(cbvDesc, cbvHandle0);
CD3DX12_CPU_DESCRIPTOR_HANDLE cbvHandle1(mCbvHeap->GetCPUDescriptorHandleForHeapStart(), d3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV), 1);
d3dDevice->CreateConstantBufferView(cbvDesc, cbvHandle1);
// Initialize and map the constant buffers. We don't unmap this until the
// app closes. Keeping things mapped for the lifetime of the resource is okay.
DX::ThrowIfFailed(mWVPConstantBuffer->Map(0, nullptr, reinterpret_cast<void**>(&mMappedWVPBuffer)));
memcpy(mMappedWVPBuffer, &mWVPData, sizeof(mWVPData));
DX::ThrowIfFailed(mDirLightConstantBuffer->Map(0, nullptr, reinterpret_cast<void**>(&mMappedDirLightBuffer)));
memcpy(mMappedDirLightBuffer, &mDirLightData, sizeof(mDirLightData));
Note: Slot b0 works perfect. I can change world view projection data just fine. But b1 does not work at all. What am I doing wrong?