我有一个用HLSL编写的像素着色器,它声明了以下常量缓冲区:
cbuffer RenderParametersData : register(b2)
{
float4 LineColor[16];
};
在其中一个着色器函数中,我根据索引“color”查找输出颜色(这实际上不是一种颜色,只是将索引放入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级,所以现在情况正常。
答案 0 :(得分:1)
我通过指定编译器不应生成着色器模型2.0程序集来解决此问题。问题末尾的更多细节。