DirectX11如何从常量缓冲区中删除未使用的变量
DirectX11 How to strip unused variables from constant buffer?
我调用D3DReflect()
来推导编译着色器使用的常量缓冲区的布局,我注意到它们通常包含未使用的变量。
我已经在使用D3DStripShader()
来剥离调试信息,我想知道是否有类似的方法可以在调用D3DReflect()
之前从常量缓冲区中剥离那些未使用的变量?
这通常是一种好的做法吗
由于这意味着大多数时候每个原始的cbuffer/stage/程序都有一个cbuffer,我不知道剥离未使用的变量的收益是否会优于拥有更多(较小)cbuffer的损失?
没有简单的方法可以做到这一点。常量缓冲区的天真观点是,每个人都会制作显式结构来保存自己的常量,而这些结构将由着色器和调用C++代码(或C#,不管怎样)共享。因此,如果着色器编译器更改了结构的布局,则所有内容都会中断。
在处理DX示例应用程序时,这在微观视图中是有意义的。对于一个更大的项目,很多人不会这么做。相反,它们具有在全局范围内声明常量的旧样式着色器。在DX9和其他类似的平台上,常量被映射到寄存器,因此编译器可以剥离未使用的常量(它确实这样做了)。对于DX11,编译器获取所有这些全局常量,并将它们放在一个特殊的"全局"常量缓冲区中。然后它决定你真的很关心缓冲区的结构,所以它拒绝删除任何内容。
因此,通常有两种选择:
-
将常量分解为多个常量缓冲区,大致分组为一起使用的集合。编译器将剥离整个未使用的常量缓冲区,因此您可以使用该缓冲区进行粗略剥离。这很耗时,而且您必须维护您的设置分区,但根据您的情况,这可能已经足够好了。
-
让自己不断地脱衣服。这就是我们要做的…编译完所有着色器一次后,我们使用反射API来获取二进制文件中所有常量的列表。该信息包括指示是否使用常量的标志。对于每个使用过的常量,我们只是简单地将其再次声明为正常值。对于每个未使用的常量,我们发出类似的声明,但将变量标记为静态。这具有将其从任何常量缓冲区中删除的效果(因为着色器编译器将其视为编译时间常量)。然后我们重新编译着色器,新生成的全局常量缓冲区只包含使用过的常量。
这也是一堆工作(在我们的实现中,我们必须将所有常量声明包装在宏中——包装器代码用所有静态/非静态声明构建一个大字符串,并定义STRIPPED_CONSTANT_DEFINITIONS
来包含该字符串):
#if defined (STRIPPED_CONSTANT_DEFINITIONS)
STRIPPED_CONSTANT_DEFINITIONS
#else
bool someConstant;
float4 color;
...
#endif
请注意,需要仍然将剥离的常量声明为静态,因为任何未使用的代码路径或引用这些变量的未调用函数都会导致着色器无法编译,否则。
- C++删除未使用的类属性会导致 std::logic_error
- 如果我想链接静态库并删除未使用的符号.txt我应该如何处理 Cmakelist
- 如何控制或优化或删除或释放 UNION 中未使用的内存
- 如果删除未使用的REF类,DLL将无法加载
- 删除未使用新表达式构建的对象实际上可以吗?
- 如果 LTO 中的代码依赖于其构造的副作用,是否允许 LTO 删除未使用的全局对象?
- C++删除未使用的库的生成文件问题
- 从数组中删除未使用的内存,以免输出随机数
- 删除未使用的包括
- 如何从 OpenGL 程序中删除未使用的资源
- GCC 不会删除未使用的函数
- 已删除未使用的类
- 从断言中删除未使用的值警告
- DirectX11如何从常量缓冲区中删除未使用的变量
- C++内存:删除未使用的布尔数组可以将结果从正确更改为错误
- 删除未使用的模板实例化的静态成员
- 删除未使用的变量后的c++挂起
- 编译器会删除未使用的函数、定义、变量、宏、include等吗?
- 在opengl中删除未使用的纹理
- 如何用GCC和ld删除未使用的C/ c++符号