How to use shader constant-buffers?
Asked Answered
M

3

5

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

Mcclenaghan answered 9/4, 2013 at 9:42 Comment(0)
B
11

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.

Buyers answered 9/4, 2013 at 12:43 Comment(2)
thanks - one follow up if thats ok - you say here that the Effect framework is legacy - does that mean Effects 11 should be avoided too? I can't see this mentioned on msdn.microsoft.com/en-us/library/windows/desktop/… although blogs.msdn.com/b/chuckw/archive/2012/10/24/… mentions it is provided mainly for porting ease from Effects 10. Is the recommendation to skips its use altogether?Mcclenaghan
Effects11/Effects/FX files are obsolete and no longer maintained by Microsoft (that's why the whole Effects11 is even only accessible from the old DirectX June 2010 SDK or a blog post). Thus, they won't improve it anymore to support next Direct3D features. It is also impossible to use it from Windows RT Applications.Buyers
U
1

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;
}
Unknown answered 17/4, 2013 at 14:25 Comment(0)
T
0

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.

Thimbu answered 9/4, 2013 at 9:53 Comment(3)
thanks, I don't think they abstract away from the hardware model that constant buffers have slots. The two syntaxes and how-slots-are-numbered question is wrapper independent I think?Mcclenaghan
yeah, it just seem that your question actually raises the question of core library vs wrapper libraries. There are a whole bunch of commonplace issues that occur as a result of picking a wrapper library, which are not necessarily tied or unique to the problem domain. If it helps, that is the direction I am approaching this from. Is the real problem that the frameworks you are referencing do not have adequate documentation?Thimbu
I don't think it is - they are both thin wrappers around DirectX - the concept of buffer slot is a DirectX concept not a wrapper library concept. This is a documentation (or me not finding the documentation) problem though I believe.Mcclenaghan

© 2022 - 2024 — McMap. All rights reserved.