2
\$\begingroup\$

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!

Here's some code: http://www.gamedev.net/topic/654950-setting-constants-using-id3d11shaderreflection/

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

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

\$\endgroup\$
6
  • \$\begingroup\$ 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! :) \$\endgroup\$
    – KamRandle
    Mar 29, 2014 at 2:35
  • \$\begingroup\$ @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. \$\endgroup\$ Mar 29, 2014 at 4:20
  • \$\begingroup\$ 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 \$\endgroup\$
    – KamRandle
    Mar 30, 2014 at 18:22
  • \$\begingroup\$ 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. :/ \$\endgroup\$
    – KamRandle
    Mar 30, 2014 at 19:13
  • \$\begingroup\$ @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. \$\endgroup\$ Mar 30, 2014 at 22:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .