Directx 像素着色器中动态常量缓冲区索引的性能

Directx 像素着色器中动态常量缓冲区索引的性能,directx,direct3d,hlsl,pixel-shader,Directx,Direct3d,Hlsl,Pixel Shader,我有一个用HLSL编写的像素着色器,它声明了以下常量缓冲区: cbuffer RenderParametersData : register(b2) { float4 LineColor[16]; }; 在其中一个着色器函数中,我根据索引“color”(它不是真正的颜色,只是将索引放入LineColor数组的方便位置)查找输出颜色: 这导致生成的汇编代码中指令槽的数量急剧增加。保持其他所有内容不变,但执行常量数组查找-output.Color=LineColor[0]-算术运算的数量

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

cbuffer RenderParametersData : register(b2) 
{
    float4 LineColor[16];
};
在其中一个着色器函数中,我根据索引“color”(它不是真正的颜色,只是将索引放入LineColor数组的方便位置)查找输出颜色:

这导致生成的汇编代码中指令槽的数量急剧增加。保持其他所有内容不变,但执行常量数组查找-
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个算术指令的限制

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

谢谢

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


我已经解决了这个问题。我向FXC指定我的目标是ps_4_0_level_9_1,这导致它为着色器模型2.0和4.0生成程序集。我发现每个元素的额外比较问题只发生在Model2.0汇编代码中。将编译器targeter切换到PS_4_0只会得到model 4.0代码,而且由于我没有被限制到level 9_1,所以现在一切正常

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

出于好奇:为什么在输入中使用浮点索引而不仅仅是专用的整数组件?这至少可以消除缩放浮点并将其转换回整数的成本。也不要使用一个固定的缓冲区考虑使用包含颜色的纹理资源。@卢修斯-如果我可以在着色器中得到一个int,并用它做索引,我会的。你知道怎么做吗?对于DX9,我的可用语义可能是COLOR(所有UNORMS)或TEXCOORD(所有float)。还有别的选择吗?关于你的第二点,如果我目前的方法不起作用,我将不得不切换到纹理资源,我只是认为cbuffer在这里可能会更好,并且可以避免mipping问题(如闪烁)。“[…]允许使用没有特殊意义的任意语义。”来自。我想这意味着您可以提出自定义语义。因为我不知道你想要什么效果,所以我不能说纹理是否适合这里。但我会尝试一下,看看它的性能如何。毕竟它们是用来寻找颜色的。谢谢@Lucius,我已经开始用纹理来重新实现它。但是,在要点上,您知道在cbuffer中使用数组时这是否是预期的行为吗?我的cbuffer中从来没有太多数据,所以我真的不知道。使用整数索引是否会提高性能?
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