Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ DirectX11如何从常量缓冲区中删除未使用的变量?_C++_Directx_Directx 11 - Fatal编程技术网

C++ DirectX11如何从常量缓冲区中删除未使用的变量?

C++ DirectX11如何从常量缓冲区中删除未使用的变量?,c++,directx,directx-11,C++,Directx,Directx 11,我调用D3DReflect()来推断编译着色器使用的常量缓冲区的布局,我注意到它们通常包含未使用的变量 我已经在使用D3DStripShader()删除调试信息,我想知道在调用D3DReflect()之前是否有类似的方法从常量缓冲区删除这些未使用的变量 这通常是一种好的做法吗? 由于这意味着大多数时候每个原始CBUFER/阶段/程序都有一个CBUFER,我不知道剥离未使用变量的收益是否优于拥有更多(更小)CBUFER的损失?没有简单的方法做到这一点。常数缓冲区的幼稚观点是,每个人都会做出显式的

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

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


这通常是一种好的做法吗?
由于这意味着大多数时候每个原始CBUFER/阶段/程序都有一个CBUFER,我不知道剥离未使用变量的收益是否优于拥有更多(更小)CBUFER的损失?

没有简单的方法做到这一点。常数缓冲区的幼稚观点是,每个人都会做出显式的结构来保存它们的常量,这些结构将被着色器和调用C++代码共享(或者不管C)。因此,如果着色器编译器更改了结构的布局,一切都将中断

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

因此,通常有两种选择:

  • 将常量拆分为多个常量缓冲区,大致分组为一起使用的集合。编译器将剥离整个未使用的常量缓冲区,因此您可以使用它来获得粗略剥离。这很耗时,而且您必须维护设置的分区,但这可能足够好了,这取决于您的情况

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

  • 这也是一系列工作(在我们的实现中,我们必须将所有常量声明包装在一个宏中-包装器代码使用所有静态/非静态声明构建一个大字符串,并定义
    STRIPPED\u constant\u DEFINITIONS
    以包含该字符串):


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

    确定它们未使用吗?大多数GPU将非常高兴地优化出任何真正未使用的变量。。。在任何情况下,我都会保留它们,因为几乎可以肯定的是,如果它们加载了一次数据,就会出现字节对齐和令人毛骨悚然的小优化……它们是未使用的,因为编译后的代码不读取它们(使用
    D3D\u SVF\u USED
    )检测到它们,但是它们仍然在cbuffer中,我想创建一个没有它们的新的粗糙cbuffer(或者打包原始的)。如何编译着色器?我使用带有标记的
    D3DCompile\u OPTIMIZATION\u LEVEL3的
    D3DCompile()
    。如何声明常量缓冲区?您可能会看到填充,或者某个变量未被当前编译的着色器引用,但被同一文件中的其他着色器引用。我还非常小心删除常量缓冲区中未使用的变量,因为编译的字节码将向量偏移引用到该缓冲区中。如果其中一个变量存在于中间,那么在删除了一个变量之后,您就将所有引用的代码无效。谢谢,这正是我的目标。宏回退到静态var确实是剥离全局cbuffer的一种聪明方法。您是每个程序只使用一个唯一的剥离常量缓冲区,还是尝试在不同阶段之间共享它们?我们仍然使用效果框架加载着色器,但我们独立编译每个着色器阶段(使用上述技巧编译两次)。因此,我们有一个包含所有阶段的所有常量的标题,但是VS/PS/etc。。。每个都获得一个唯一的全局cbuffer,该全局cbuffer仅包含该阶段中使用的常量。由于着色器的数量以及由此产生的复杂性,我们不会在不同着色器或阶段之间共享cbuffer布局。
    #if defined (STRIPPED_CONSTANT_DEFINITIONS)
    STRIPPED_CONSTANT_DEFINITIONS
    #else
    bool someConstant;
    float4 color;
    ...
    #endif