【问题标题】:DX11 InputLayout cannot be set to multiple shadersDX11 InputLayout 无法设置多个着色器
【发布时间】:2014-01-26 05:53:34
【问题描述】:

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

例如:

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

无法正确转换为:

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

即,当使用附加到VSInput2 的着色器和来自VSInput1 的输入布局时,来自VSInput1TEXCOORD0 将用于代替来自VSInput2NORMAL,尽管使用来自@ 的输入布局987654331@ 说明NORMALTEXCOORD0 之后。

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

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

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

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

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

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

来自 MSwebsite:

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

有没有办法确保寄存器以上述要求的方式解释,而不必在 asm 中编写着色器?

如果需要 asm,那么如何创建 Input Layout?

【问题讨论】:

  • DX10 和 DX11 使用该机制在初始化时准备一切,并在渲染帧时防止不必要的复杂和昂贵的过程。现代 GPU 不再有硬件可以轻松地从缓冲区中获取。这意味着顶点着色器需要为每个不同的缓冲区布局重新编译。 OpenGL 继续坚持 DX9 懒惰的方式,在每次绘制时,由于未预料到的渲染上下文,事情会在没有控制的情况下触发。
  • 您提出的解决方案 1 和 2 是相同的,因为在 GPU 旁边的较低层中无论如何都需要不同的着色器。 OpenGL 只是对你隐藏了更多东西,并且错过了提前准备东西的机会,因为 API 更关心遗留兼容性,并且不像过去那样靠近 GPU 硬件。

标签: hlsl directx-11


【解决方案1】:

手工制作输入布局是不可能的。如果您想要更通用的输入组装机制,您始终可以选择从 ShaderResourceView 读取顶点数据,并使用您喜欢的任何逻辑对其进行解释。但是请记住,如果您希望布局在运行时在单个着色器中保持灵活,您将需要大量的分支或预加载算法,这会降低性能。

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

最终,切换输入布局通常代价高昂,应该避免。确实,最好的方法是尝试只使用其中的一小部分,仅在必要时切换。您最终可能会浪费一点内存,但通过重用VSInput1 作为与VSInput2 关联的着色器的输入,您几乎肯定会获得更好的性能,即使您没有使用float2 TexCoord0 : TEXCOORD0; 输入。

真正的最佳方法是实施您认为最好的方法,profile,然后看看您可以在哪些方面改进性能。除非这只是为了简化编程,否则你可能会倒霉。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多