How To Set Constants Using ID3DShaderReflection

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.)

• Hey! Thanks for the information. I was trying to get memcpy to copy data into the the buffer but I couldn't get it to work. I already know how to upload data using a buffer and a struct, but I'm re-writing my shader system and am now trying to get memcpy to upload the correct data to the correct area in the buffer. I tried this: memcpy(&data + variable->Description.StartOffset, (void*) &matrix, variable->Description.Size) and I couldn't get it to work. What is the correct way to upload the data to the buffer with the correct offset? Thanks! :) – KamRandle Mar 29 '14 at 2:35
• @KamRandle I presume StartOffset is in bytes, so that should work assuming data is an unsigned char *. If data is some other type, the pointer arithmetic will be done in multiples of that type, so it'll screw things up. – Nathan Reed Mar 29 '14 at 4:20
• Oh, ok! I got it working. But I am having another problem now. When setting constants, there seems to be a lot of input lag. I think it is because of memcpy, but I'm not sure. Here's my code: pastebin.com/aGurEqtC – KamRandle Mar 30 '14 at 18:22
• From testing, it seems like the amount of input/visual lag (even though my frame rate is 60+) depends on which order I set the parameters in. :/ – KamRandle Mar 30 '14 at 19:13
• @KamRandle Your code shows you only setting a single variable at a time, directly in the mapped buffer. That won't work correctly since MAP_WRITE_DISCARD throws out any previous data in that constant buffer, so each time you set a variable you're losing all the other variables. That's why, like I said in my answer, you need to keep a shadow copy of the buffer in main memory---update individual variables there, then copy the whole thing to the mapped buffer, after you've updated all necessary variables, just before the draw call. – Nathan Reed Mar 30 '14 at 22:58