Ilia
Ilia

Reputation: 341

DirectCompute shader data input/output

I am learning DirectCompute and I am stuck with StructuredBufferes. The thing is I learned that to supply data to shader I need to use a View - SRV or UAV, depending on what I am trying to achieve. But code examples from Microsoft site do not explain, how does a view defined in C++ code correspond to a specific Buffer defined in shader code. However, there is a hlsl keyword I dont really understand - register(). In sample there were three bufferes:

    StructuredBuffer<BuffType> Buff0 : register(t0);
    StructuredBuffer<BuffType> Buff1 : register(t1);
    RWStructuredBuffer<BuffType> BuffOut : register(u0);

In C++ code the authors just set ComputeShader, 1 UAV, 2 SRV's and then call Context.Dispatch(,,) (assuming they have prepared all buffers and views before). So the question is - how do I understand that the particular SRV (there are two of them) provide data for the particaular StructuredBuffer? Is it controlled by register number(e.g. register(t0) is filled first, register(t1) - second). If yes, what if I want to provide data to second buffer first, and then fill the first one? I feel myself that I miss something very important, but in previous tutorials I used everything was a lot easier because of EffectVariales and .GetVariableBy methods. Thanks in advance.

Upvotes: 1

Views: 919

Answers (1)

MooseBoys
MooseBoys

Reputation: 6793

The register bindings declared in the shader correspond to the index in the binding array argument. For example, if you call CSSetShaderResources(7 /*StartSlot*/, 3 /*NumViews*/, viewArray);, this will bind viewArray[0] to register(t7), viewArray[1] to register(t8), and viewArray[2] to register(t9). Note that if one of the elements of viewArray is NULL, that will effectively unbind the corresponding register slot.

Note that in HLSL, omitting the explicit register binding will automatically assign registers starting from 0. And in the common case, StartSlot will be 0, so you just need to make sure that the order of views in viewArray matches the declaration order in your shader. Still, it's best practice to explicitly assign regsters and make sure they match your binding array, because if the HLSL compiler determines you don't need one of the declared views, it'll eliminate it and won't skip over its slot in implicit assignment. For example:

StructuredBuffer<float> foo; // register(t0)
StructuredBuffer<float> bar; // eliminated!
StructuredBuffer<float> baz; // register(t1) // skipped over bar!
RWStructuredBuffer<float> biz; // register(u0)
void main()
{
    float x = foo[0];
    if(x < 0) x = 0;
    else if(x >= 0) x = 1;
    else x = bar[0]; // branch never hit, compiler optimizes out the only use of bar!
    biz[0] = x + baz[0];
}

Upvotes: 2

Related Questions