Constant buffers stay constant throughout entire dispatches / draw calls, and thus their data can presumably be shared as efficiently as possible between different threads using those buffers.
But I guess this probably doesn't mean they are "free" in terms of memory bandwidth? Are they loaded from memory once per thread group / wave (whatever hardware terminology is fitting), or are they somehow cached more efficiently?
What other performance metrics / considerations do they affect? Is there something like register pressure where CB size can impact how well your shader can be parallelized if the CB is too large (even below the 65k limit)?
Is the size of your constant buffer something you should keep an eye out for when optimizing shaders, or is it shared efficiently enough that it's generally not a point of worry? For example, in many cases one can probably output constant buffer constants as shader code constants (leading to more variants) instead. Or maybe some computation in the shader is the result of two values in the CB - you could add a third value to the CB, or compute it on the fly in the shader for every single pixel / thread but in return you maybe don't have to fetch as much memory... how to reason about this?
How is this impacted by different hardware vendors? For example, in certain cases I saw it recommended to use struct buffers instead of constant buffers, even if all data fetched is the same in an entire thread group, but only on certain hardware (was it AMD GCN?). I think light cluster culling is such a case, where one might want to fetch light list data with a struct buffer.
My overall question is how to reason about the performance implications of constant buffers on various hardware .