DX11 InputLayout无法设置为多个着色器

时间:2014-01-25 06:48:03

标签: hlsl directx-11

调用CreateInputLayout创建一个输入布局,该布局仅适用于具有完全相同语义位置的着色器,使用单个缓冲区作为顶点数据。

例如:

VSInput1
{
    float3 Position  : POSITION;
    float2 TexCoord0 : TEXCOORD0;
    float3 Normal    : NORMAL;
};

无法正确翻译为:

VSInput2
{
    float3 Position  : POSITION;
    float3 Normal    : NORMAL;
};

即,在使用VSInput2附加的着色器和VSInput1的输入布局时,来自TEXCOORD0的{​​{1}}将在VSInput1的位置使用NORMAL尽管使用VSInput2中的输入布局,表明VSInput1位于NORMAL之后。

此行为表明TEXCOORD0仅使用语义来确定着色器是否拥有它们,否则忽略内存中的变量位置。

这太可怕了,因为它需要以下两个选项之一:

1)使用CreateInputLayout着色器的已编译着色器代码创建新的输入布局。

这需要更多内存来为需要使用多个着色器的每个缓冲区创建新的输入布局(考虑阴影)。 OpenGL通过确定数据应驻留在缓冲区中的位置,轻松处理非连续内存位置。显然,DX11没有。

2)将顶点数据分解为单独的缓冲区。

这比按顺序排列内存要慢,即跳转到某个位置只是为了返回上一个缓冲区中的下一个位置。

来自MS website

  

从寄存器读取数据时可能会重新解释数据

有没有办法确保以上述方式解释寄存器而无需在asm中写入着色器?

如果需要asm,那么如何创建输入布局?

1 个答案:

答案 0 :(得分:1)

无法手工制作输入布局。如果你想要一个更通用的输入汇编机制,你总是可以选择从ShaderResourceView读取顶点数据,使用你喜欢的任何逻辑来解释它。但请记住,如果您希望布局在单个着色器中在运行时具有灵活性,则需要进行大量分支或预加载算法,这会降低性能。

更好的方法实际上是您的选择(1)。虽然创建多个输入布局确实会增加内存需求,但在运行时却明显更快;任何着色器的输入布局“只是工作”将需要某种运行时修补;明显的帧率差异与几百字节的开销相比?我会选择穿。出于同样的性能原因,我也怀疑在OpenGL中幕后发生了同样的事情,尽管它可能不会直接通过API公开。

最终,切换输入布局通常是昂贵的,应该避免。实际上,最好的方法是尽量只坚持少数几种,并在必要时进行切换。您可能最终会浪费一点内存,但是通过重用VSInput1作为与VSInput2关联的着色器的输入,您几乎肯定会获得更好的性能,即使您没有使用{{ 1}}输入。

真正最好的方法是实施您认为最好的方法,个人资料,并了解您可以在哪些方面进行性能改进。除非这只是编程简单,否则你可能会运气不好。