假设我有一个计算着色器,它使用像这样的组的Id从Texture2DArray中检索数据:
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不支持这种索引,因为我看不出任何分歧或其他问题,至少在这种情况下?
答案 0 :(得分:1)
我不确定您是否正确绑定了您的管道,但让我们评估这两种情况。
当你有:
Texture2DArray<float4> gTextureArray[2];
技术上绑定2个纹理数组(一个在插槽0中,一个在插槽1中),因此运行时无法动态切换着色器资源插槽。
以上一行与执行相同:
Texture2DArray<float4> gTextureArray0;
Texture2DArray<float4> gTextureArray1;
在两种情况下,您都可以有效地绑定两种不同的资源,因此无法动态切换。
如果您有一个包含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分量是切片索引,因此在这种情况下,完全可能。