2013-04-16 31 views
1

我有个像素着色器,写在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个算术指令的限制。

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

谢谢!

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

编辑2:我解决了这个问题。我正在向FXC指定我的目标是ps_4_0_level_9_1,这导致它为着色器模型2.0和4.0生成装配。我发现每个元素的附加比较问题只发生在2.0型汇编代码中。将编译器目标器切换到PS_4_0只会获得模型4.0代码,并且由于我不受限于9_1级,所以现在情况已经很好了。

+0

出于好奇:为什么在输入中使用浮点型索引而不仅仅是一个专用的整数部分?这至少会消除缩放浮点数并将其转换回整数的成本。考虑使用包含颜色的纹理资源,而不是一个常量缓冲区。 – Lucius

+0

@Lucius - 如果我可以在着色器中得到一个int,并用这个做索引,我会的。你知不知道怎么?对于DX9,它看起来像我可用的语义是COLOR(所有UNORMS)或TEXCOORD(全部浮动)。还有其他选择吗?关于你的第二点,如果我目前的方法不起作用,我将不得不切换到纹理资源,我只是认为一个cbuffer可能会在这里更好地工作,并避免瑕疵问题(如闪闪发光)。 –

+0

**“[..]任意语义允许没有特殊含义。”[MSDN]中的**(http://msdn.microsoft.com/zh-cn/library/windows/desktop/bb509647(v = vs.85)的.aspx)。我想这意味着你可以想出自定义的语义。因为我不知道你在做什么样的效果,我不能说这里的纹理是否适合。但我会试一试,看看它在性能方面的表现如何。毕竟他们是*制作*查找颜色。 – Lucius

回答

1

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

相关问题