Я учусь 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 методы.
Заранее спасибо.
Связанные регистры, объявленные в шейдере, соответствуют индексу в аргументе массива привязки. Например, если вы звоните 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];
}