2014-04-24 7 views
1

Допустим, у меня есть Compute Shader, который извлекает данные из Texture2DArray, используя идентификатор группы, как это:Понимание «индекс пробоотборник массива должен быть буквальным выражением» ошибки в ComputeShaders

Texture2DArray<float4> gTextureArray[2]; 
[numthreads(32, 1, 1)] 
void Kernel(uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID) 
{ 
    float3 tmp = gTextureArray[GroupID.x].Load(int4(GroupThreadID.x,GroupThreadID.x,0,0)).rgb; 

    .... 
} 

И скажем, Я запускаю его так: deviceContext->Dispatch(2, 0, 0);

Итак, 2 группы, 32 потока, каждый из которых считывает значения пикселей из Texture2DArray. Все потоки в GroupID.x = 0 будут считывать значения из gTextureArray [0], а все потоки в GroupID.y = 0 будут считывать значения из gTextureArray [1]. Оказывается, я не могу скомпилировать этот простой код, вместо этого я получаю эту ошибку компиляции error X3512: sampler array index must be a literal expression

Теперь я знаю, что могу сделать это вместо того, чтобы:

Texture2DArray<float4> gTextureArray[2]; 
[numthreads(32, 1, 1)] 
void Kernel(uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID) 
{ 
    float3 tmp = float3(0,0,0); 
    if(GroupID.x == 0) 
     tmp = gTextureArray[0].Load(int4(GroupThreadID.x,GroupThreadID.x,0,0)).rgb; 
    else if(GroupID.x == 1) 
     tmp = gTextureArray[1].Load(int4(GroupThreadID.x,GroupThreadID.x,0,0)).rgb; 

    .... 
} 

Или использовать переключатель в случае, если у меня есть много группы, так что это не выглядит так ужасно (он все еще делает)

Обратите внимание на то, что нет никакой девиации варпа, поскольку все потоки в каждой группе будут проходить одна ветвь или другая. Мой вопрос: я что-то пропустил? Почему HLSL не поддерживает такую ​​индексацию, поскольку я не вижу никаких расхождений или других проблем, по крайней мере в этом случае?

ответ

1

Я не уверен, правильно ли вы связали свой трубопровод, но давайте оценим оба случая.

Когда у вас есть:

Texture2DArray<float4> gTextureArray[2]; 

Вам технически связывание массив 2 текстуры (один в слоте 0, один в слоте 1), так что во время выполнения не может переключаться шейдером слота ресурсов динамически.

Линия выше такая же, как делают:

Texture2DArray<float4> gTextureArray0; 
Texture2DArray<float4> gTextureArray1; 

Вы эффективно связать 2 различных ресурсов, в обоих случаях, следовательно, почему вы не можете динамически переключаться.

В том случае, если у вас есть текстуры массив с 2 ломтика, это становится возможным, вы должны изменить ваш код:

Texture2DArray<float4> gTextureArray; 

[numthreads(32, 1, 1)] 
void Kernel(uint3 GroupID : SV_GroupID, uint3 GroupThreadID : SV_GroupThreadID) 
{ 
    float3 tmp = gTextureArray.Load(int4(GroupThreadID.x,GroupThreadID.x,GroupID.x,0)).rgb; 

}

Z компонент индекса среза, так и в в этом случае это совершенно возможно.

+0

Да. Ты прав. Использование массивов текстур в том, как я предлагал, кажется, просто синтаксическим сахаром. Дополнительные разъяснения были даны в этом сообщении http://www.gamedev.net/topic/655854-understanding-the-%E2%80%9Csampler-array-index-must-be-a-literal-expression%E2%80% 9D-error-in-computeshaders/ – Juste

+0

@catflier, как мне объединить Texture2d в C# с Texture2DArray в hlsl? Мне недостает ссылки. Используя переключатель в hlsl, чтобы избежать вышеупомянутого исключения, sux –

+0

@JeroenvanLangen это довольно просто во время создания, чтобы построить массив текстур, но ответ будет зависеть от какой оболочки C#, которую вы используете (slimdx или sharpdx), также можно сделать это из gpu сгенерированный ресурс с вызовами рисования, вычислениями или копией области ресурсов. Может быть, вопрос будет еще проще (также помогает людям, чтобы эти ответы не были зарыты в комментарии). – catflier