I got to the point where I am tired of hardcoding shaders and decided that it was now time to look into using ID3D11ShaderReflection to get data from the shader and set my shader's constant buffer using that data. I have a simple system that loads up shaders and gets it's data. Now that I have the data, I would like to know how the correct way to upload the data to the constant buffer. I've searched on Google and couldn't find too much information on this. Any help? Thanks!
The way I usually handle constant buffers is to define a struct in C++ that matches the layout of the constant buffer as defined in HLSL; then I can just create an instance of the struct and fill in the data.
You can also create a more data-driven system where you use the offset and size information retrieved from shader reflection. You'll need to allocate some memory the size of the buffer, then memcpy() individual variables into the correct spot based on the variable's offset. It looks like that's the direction you're heading based on your code snippets.
Either way, once your data is set up in the correct layout, before you do a draw call, you then map the constant buffer to get a pointer to the GPU-visible memory, and copy the data into it. This is done with the
ID3D11DeviceContext::Map() method. For constant buffers, you should use
MAP_WRITE_DISCARD for the third parameter. This way, the same buffer object can be re-used for multiple draws within the same frame without unnecessarily stalling the CPU.
When you're finished copying the data, unmap the buffer and bind it to the pipeline, and you're ready to draw.
(NB: you can also use
UpdateSubresource() in place of
Map() for updating constant buffers, but the performance could be worse due to an extra memory copy internally.
Map() is considered best practice for updating constant buffers. See Efficient Buffer Management by John McDonald.)