【问题标题】:DirectX11 How to strip unused variables from constant buffer?DirectX11 如何从常量缓冲区中删除未使用的变量?
【发布时间】:2014-10-23 22:49:00
【问题描述】:

我正在调用D3DReflect() 来推断编译着色器使用的常量缓冲区的布局,我注意到它们通常包含未使用的变量。

我已经在使用D3DStripShader() 去除调试信息,我想知道在调用D3DReflect() 之前是否有类似的方法可以从常量缓冲区中去除那些未使用的变量?


这通常是一个好习惯吗?
由于这意味着大多数时候每个原始 cbuffer/stage/program 都有一个 cbuffer,我不知道剥离未使用变量的收益是否优于失去更多(更小)cbuffer 的损失?

【问题讨论】:

  • 确定没有使用?大多数 GPU 会非常乐意优化任何真正未使用的变量...无论如何我都会保留它们,因为几乎可以肯定,如果它们加载数据一次,就会进行字节对齐和极少的优化...跨度>
  • 它们未被使用,因为编译后的代码不读取它们(使用D3D_SVF_USED检测),但它们仍在 cbuffers 中,我想创建一个没有它们的新粗 cbuffer(或打包原文)。
  • 如何编译着色器?
  • 我正在使用 D3DCompile() 和标志 D3DCOMPILE_OPTIMIZATION_LEVEL3
  • 你的常量缓冲区是如何声明的?您可能会看到填充,或者当前编译的着色器未引用某个变量,但同一文件中的不同着色器引用了该变量。我也会非常谨慎地删除常量缓冲区中未使用的变量,因为编译的字节码将向量偏移量引用到该缓冲区中。如果其中一个变量存在于中间,则您刚刚使所有引用您删除的变量之后的任何变量的代码无效。

标签: c++ directx directx-11


【解决方案1】:

没有简单的方法可以做到这一点。常量缓冲区的天真观点是,每个人都会创建显式结构来保存他们的常量,并且这些结构将由着色器和调用 C++ 代码(或 C#,等等)共享。因此,如果着色器编译器改变了结构的布局,一切都会中断。

在处理 DX 示例应用程序时,这在微观视图中是有意义的。对于一个更大的项目,很多人不这样做。相反,它们具有旧式着色器,其常量在全局范围内声明。在 DX9 和其他类似平台上,常量被映射到寄存器,因此编译器可以去除未使用的常量(确实如此)。对于 DX11,编译器获取所有这些全局常量,并将它们放在一个特殊的“全局”常量缓冲区中。然后它决定你真的关心那个缓冲区的结构,所以它拒绝删除任何东西。

所以,一般有两种选择:

  1. 将常量分成多个常量缓冲区,大致分组为一起使用的集合。编译器将剥离整个未使用的常量缓冲区,因此您可以使用它来进行粗略剥离。这很耗时,并且您必须维护设置的分区,但根据您的情况,这可能已经足够了。

  2. 实施不断剥离自己。这就是我们要做的... 在编译所有着色器一次之后,我们使用反射 API 来获取二进制文件中所有常量的列表。该信息包括指示是否使用常量的标志。对于每个使用的常量,我们只需像往常一样再次声明它。对于每个未使用的常量,我们发出类似的声明,但将变量标记为静态。这具有将其从任何常量缓冲区中删除的效果(因为它被着色器编译器视为编译时常量)。然后我们重新编译着色器,新生成的全局常量缓冲区只包含使用过的常量。

这也是一堆工作(在我们的实现中,我们必须将所有常量声明包装在一个宏中 - 包装代码构建一个包含所有静态/非静态声明的大字符串,并定义 STRIPPED_CONSTANT_DEFINITIONS包含该字符串):

#if defined (STRIPPED_CONSTANT_DEFINITIONS)
STRIPPED_CONSTANT_DEFINITIONS
#else
bool someConstant;
float4 color;
...
#endif

请注意,您需要仍将剥离的常量声明为静态,因为任何未使用的代码路径或引用这些变量的未调用函数都会导致着色器无法编译,否则。

【讨论】:

  • 谢谢,这正是我的目标。宏回退到静态变量确实是剥离全局 cbuffer 的一种聪明方法。您是每个程序只使用一个唯一的剥离常量缓冲区,还是尝试在不同阶段之间共享它们?
  • 我们仍然使用效果框架来加载我们的着色器,但是我们独立编译每个着色器阶段(并且两次,使用上述技巧)。所以我们有一个包含所有阶段的所有常量的头文件,但是 VS/PS/etc... 每个都有一个唯一的全局 cbuffer,它只包含该阶段中使用的常量。由于着色器的数量以及可能导致的复杂性,我们不会在不同的着色器或阶段之间共享 cbuffer 布局。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 2020-03-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多