5
votes

tI'm struggling to understand constant buffers in DirectX. I've seen two syntaxes

float4 myVar;

declared at top level of the shader file and

cbuffer myBuffer
{
    float4 myVar;
}

as detailed on http://msdn.microsoft.com/en-gb/library/windows/desktop/bb509581(v=vs.85).aspx

I understand that constant buffers need to be assigned to slots (zero-based indexing) and can be set in code.

The two frameworks I've looked at (SlimDX vs SharpDX) seem to use different conventions for setting them - SlimDX by string name (via shader reflection?) and SharpDX by slot number - although its not clear where the slot number is obtained from?

Can anyone shed light on the difference between the two syntaxes, if they are actually different, how slot numbers are assigned to declarations in the .fx file and how the slot numbers are shared between shaders?

Any help appreciated

3

3 Answers

11
votes

Both SharpDX and SlimDX use the same convention when using raw Direct3D10/Direct3D11 API (through Direct3D10.Device.XXX.SetConstantBuffers and Direct3D11.DeviceContext.XXX.SetConstantBuffers).

As stated in the link from the MSDN documentation, section "Default constant buffers", It is explained that variable not defined inside a Constant Buffer will end-up in a default Global Constant Buffer called "$Global".

On the other hand, legacy Effect framework (which interacts with RAW Direct3D10+ API) provides access to individual variable by their name. Internally they are using ShaderReflection to query the content of Constant Buffers and automatically handle allocate/update/upload of these constant buffers. In the end this is the constant buffer that will be uploaded to the GPU, not individual variables (that are not existing outside the constant buffer). The legacy Effect framework handles dynamically which slot to bind the constant buffer to by querying the binding slot using ShaderReflection.

Slot numbers are assigned by the compiler at compile time. If you don't specify explicitly a register (see register for cbuffer in MSDN documentation), the compiler will affect the first available slot to the first cbuffer used. There is no guarantee that the compiler will affect the same slot between shaders for a same constant buffers, unless you set the register explicitly.

1
votes

The first syntax:

float4 myVar;

is Microsoft's effect syntax, where as the second is straight hlsl. Effect syntax simplifies things a bit by automatically allocating the constant buffers for you but this comes at the cost of flexibility.

Using SharpDX you would assign a constant buffer to slot 1 like so:

cbuffer myBuffer: register(b1)
{
    float4 myVar;
}
0
votes

The documentation you are referencing is for the pure D3D shader model api. You will need to consult each individual middleware (SlimDX or SharpDX) for understanding the correspondence between their syntax and the underlying mapping.

I would assert that any third party distribution is completely free to define their own syntax (and it could be implemented in whatever overly complex way), but that is something you have to accept. You would need to consult the corresponding documentation of each third party vendor to understand the mapping, as the details may also vary version to version. If the source code is available, you could inspect it to understand the mapping yourself. And given the "black-box" nature of some frameworks, you might be expected to simply accept the framework's documenation - in which case, referring to the canonical/base library documentation would be a mistake or abstraction leak.

The final question is: why do you care about the implementation/mapping? The entire point of these libraries is to abstract away the details in a convenient way. Personally, I can see why this might be frustrating (especially if you resort to the canonical documentation instead of the platform's for whatever reason), but the related cost you pay is a consequence/tradeoff of choosing such a platform in lieu of using the core library directly.