DirectCompute шейдерный ввод / вывод данных
Я учусь DirectCompute, и я застрял с StructuredBufferes. Дело в том, что я узнал, что для подачи данных в шейдер мне нужно использовать View - SRV или UAV, в зависимости от того, чего я пытаюсь достичь. Но примеры кода с сайта Microsoft не объясняют, как представление, определенное в коде C++, соответствует определенному буферу, определенному в шейдерном коде. Тем не менее, есть ключевое слово hlsl, которое я не совсем понимаю - register()
, В выборке было три буфера:
StructuredBuffer<BuffType> Buff0 : register(t0);
StructuredBuffer<BuffType> Buff1 : register(t1);
RWStructuredBuffer<BuffType> BuffOut : register(u0);
В коде C++ авторы просто устанавливают ComputeShader, 1 UAV, 2 SRV и затем вызывают Context.Dispatch(,,) (при условии, что они подготовили все буферы и представления ранее). Поэтому возникает вопрос - как я понимаю, что конкретный SRV (их два) предоставляет данные для конкретного StructuredBuffer? Управляется ли он номером регистра (например, регистр (t0) заполняется первым, регистр (t1) - вторым). Если да, то что, если я хочу сначала предоставить данные во второй буфер, а затем заполнить первый? Я чувствую себя так, что мне не хватает чего-то очень важного, но в предыдущих уроках я использовал все было намного проще благодаря методам EffectVariales и .GetVariableBy. Заранее спасибо.
1 ответ
Связанные регистры, объявленные в шейдере, соответствуют индексу в аргументе массива привязки. Например, если вы звоните CSSetShaderResources(7 /*StartSlot*/, 3 /*NumViews*/, viewArray);
это будет связывать viewArray[0]
в register(t7)
, viewArray[1]
в register(t8)
, а также viewArray[2]
в register(t9)
, Обратите внимание, что если один из элементов viewArray
является NULL
, что эффективно открепит соответствующий слот регистра.
Обратите внимание, что в HLSL, опуская явное register
Привязка автоматически назначит регистры, начиная с 0. И в общем случае StartSlot
будет 0
так что вам просто нужно убедиться, что порядок просмотров в viewArray
соответствует порядку объявления в вашем шейдере. Тем не менее, рекомендуется явно назначать регистры и проверять, соответствуют ли они вашему массиву привязки, потому что, если компилятор HLSL определит, что вам не нужно одно из объявленных представлений, он устранит его и не пропустит свой слот в неявном виде. назначение. Например:
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];
}