2

我有一个用 HLSL 编写的像素着色器,它声明了以下常量缓冲区:

cbuffer RenderParametersData : register(b2) 
{
    float4 LineColor[16];
};

在其中一个着色器函数中,我根据索引“颜色”查找输出颜色(这不是真正的颜色,只是将索引放入 LineColors 数组的方便位置):

output.Color = Colors[input.Color.b * 255];

这导致生成的汇编代码中指令槽的数量急剧增加。保持其他所有内容不变,而是执行常数数组查找 -output.Color = LineColor[0];算术运算的数量从 10 变为 37。几乎所有附加运算看起来像这样:

cmp r2, -r1.x, c0, r0.w
cmp r2, -r1.y, c1, r2
cmp r2, -r1.z, c2, r2
cmp r1, -r1.w, c3, r2

其中 c 增加到 15,与 LineColor 中的元素数量相匹配。将 LineColor 调整为 8 个元素的代码与第二种情况非常相似,但 c 仅变为 7,再次匹配数组中的元素数。回到持续查找,操作数下降到 10。

因此,动态常量缓冲区数组查找似乎带来了相当大的额外成本,为数组中的每个元素添加一个比较指令,加上一些开销。我对这个数组查找的成本感到非常惊讶,而且考虑到我的数组大小很快就会增加一个数量级,这将使我超过 64 条算术指令的限制。

这是预期的行为吗?我在这里做错了什么,还是这是动态数组索引的必然结果?

谢谢!

编辑:只是为了添加一些额外的细节,我想要的效果是根据来自顶点着色器和纹理坐标的数据为一些四边形着色。我会在顶点着色器中完成这项工作,但必须首先进行纹理坐标的插值。

EDIT2:我已经解决了这个问题。我向 FXC 指定我的目标是 ps_4_0_level_9_1,这导致它为着色器模型 2.0 和 4.0 生成程序集。我发现每个元素的额外比较问题只发生在模型 2.0 汇编代码中。将编译器目标切换到 PS_4_0 会导致仅获得模型 4.0 代码,并且由于我不受限于级别 9_1,所以现在一切正常。

4

1 回答 1

1

我通过指定不应由编译器生成着色器模型 2.0 程序集来解决此问题。问题末尾有更多细节。

于 2013-04-17T20:38:58.790 回答