How are you able to tell D3D12 where to look for the cbuffer data at? It seems like calling Map gives you a pointer to use, where the driver has allocated that memory.
That does look like the job of the D3D12_CPU_DESCRIPTOR_HANDLE that you pass to CreateConstantBufferView. Is he really suggesting calling CreateConstantBufferView for each binding of a cbuffer? And plus, when I call that function, I pass it the result of ID3D12DescriptorHeap::GetCPUDescriptorHandleForHeapStart(), not a memory address...
Yeah you put a memory address into a D3D12_CONSTANT_BUFFER_VIEW_DESC, and then D3D copies that into a descriptor for you. When you want to tell D3D to read constants from your memory address, you give it this descriptor. So, "giving a pointer to d3d" == "giving it a descriptor that contains this pointer".
You can try calling CreateConstantBufferView on every bind, it probably actually won't be too bad :) I pretty much do that on consoles, but you're in control of memory management there a lot more, so I can actually get away with doing this without causing any allocations to actually occur (just patching some data in-place...).
What you can do on PC to avoid these allocations is pre-create a whole bunch of descriptors (cbuffer-views) for each 256 byte block of your huge buffer. e.g.
* Create a big buffer (your 'constant stack'), large enough to hold every dynamic constant required in your frame, plus padding... Unfortunately D3D12 mandates that buffers be 256byte aligned.
* Get the base address of the buffer and in a loop that increments this address by 256 bytes, pre-create cbuffer-views/descriptors for each 256 byte block.
* Repeat that loop with different sizes if required (e.g. for 1KB buffers, or 4KB buffers).
* Now when the user needs to supply dynamic constants, write them into your giant buffer at the appropriate offset, and then fetch the pre-created view/desecriptor that corresponds with this offset.
* Give that descriptor to D3D as your cbuffer data.
Next frame, switch to using a different constant-stack buffer. The frame after that, use a fence to ensure the GPU has finished with the previous-previous frame, and then reuse the first constant-stack buffer again.
For non-dynamic cbuffers, don't bother with any of this and just pre-allocate their immutable data, and pre-create their descriptor.