3

假设我有一个计算着色器,它使用组的 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 不支持这种索引,因为我看不到任何分歧或其他问题,至少在这种情况下?

4

1 回答 1

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 分量是切片索引,所以在这种情况下这是完全可能的。

于 2014-06-19T17:04:15.663 回答