为什么不能将布尔值打包并对齐到D3D常量缓冲区中?


9

好吧,我很难将布尔值打包并对齐到hlsl常量缓冲区中,我不确定为什么。

这是hlsl中的缓冲区

cbuffer MaterialBuffer : register(b1) {
    float3 materialDiffuseAlbedo;
    float  materialSpecularExponent;
    float3 materialSpecularAlbedo;
    bool isTextured;
};

这是用c ++编写的

struct GeometryBufferPass_MaterialBuffer {
    XMFLOAT3 diffuse;
    float specularExponent;
    XMFLOAT3 specular;
    bool isTextured;
};

我试图以各种方式移动布尔并填充结构,但是没有运气。正确的方法是什么?


这是什么原因引起的?
MichaelHouse

布尔值用于确定着色器是否需要对纹理进行采样。这样,我可以使用相同的着色器渲染带纹理和无纹理的对象。布尔仅在条件语句中使用。它没有获得正确的数据,因为它对待所有对象都相同。这是不正确的,因为目前我的球体是唯一具有纹理的物体。
KlashnikovKid 2012年

其他值起作用,但不是布尔值吗?您是否尝试过使用可用于着色器的调试器之一来查看其中的内容?
MichaelHouse

2
尝试将布尔值存储在char中。存储为1表示true,0表示false。只是为了测试,而且无论如何,布尔值在C ++中还是1字节……
Gustavo Maciel 2012年

3
布尔的大小取决于实现。在某些平台上,它的大小与int相同。 stackoverflow.com/questions/5067492/...
四分

Answers:


9

为了提高效率,将映射常量缓冲区,以使值不会跨越GPU寄存器。每个寄存器的大小为四个浮点数(16个字节),因此常量缓冲区结构在GPU上必须是其整数倍。如果要使用C ++结构来方便地映射数据,则应相应地对其进行填充(请注意,这并不总是可以很好地扩展)。

那么,您的问题是HLSL布尔值是四个字节,但在CPU端是​​一个字节(在您的特定实现中)。这会导致您的C ++结构无法正确对齐:布尔值的有效位(重要的0或1)将存储在该值的最低有效字节中,并且由于大小与位置不一致内存中该字节的字节数在结构的CPU和GPU版本中会有所不同。

手动插入适当的填充并确保正确的16字节对齐,或者仅使用适当大小的类型(如整数)应该可以解决此问题。该线程可能还对您有用,因为它包含对大致相同问题的更深入的讨论。


1
我不会遵循:“ isTextured适合同一寄存器,因为它必须跨入下一个寄存器。因此,它完全碰到了下一个寄存器。” 第二个寄存器由specular前三个组件组成,isTextured最后一个由最后一个组件组成,所以我看不到有什么需要撞入下一个寄存器的吗?1字节和4字节布尔值的长度显然很重要,但是specular在同一个寄存器中可以容纳一个。
内森·里德

你是对的; 我对寄存器的大小和类型的大小感到困惑,并提出了错误的映射表示形式。唯一的问题是相关字节在内存中的位置。我已经相应地调整了答案。

接受您的彻底回答。就像您提到的那样,这是一个很大/很小的字节序问题,使用int可以解决。
KlashnikovKid 2012年

3

好了,做了一些阅读,发现hlsl bool本质上是一个32位整数。所以我只是在c ++结构中使用了一个整数来解决我的问题。

struct GeometryBufferPass_MaterialBuffer {
    XMFLOAT3 diffuse;
    float specularExponent;
    XMFLOAT3 specular;
    int isTextured;
};

为什么不保留bool类型,而只在编译器端使用int?只是为了保留语义。
Gustavo Maciel

是的,这就是我在上面所做的。在struct cpu端使用一个整数,在常量缓冲区gpu端使用bool。
KlashnikovKid 2012年

0

float,bool和int不需要为字节序排列,特别是对于多个项目。

在此处列出的一些示例中,切换为int或float的方法可以在XMFLOAT3项之间对齐,因此可以正确引用。但是,如果需要在结构中为int,float(无XM类型)声明数组或多个项目,则可能会发现GPU值与CPU结构中设置的值不匹配。

当添加一个类型为int的数组用于照明类型时,我当然做到了。

我发现最简单的方法是坚持使用以16对齐的XM类型,这可能需要浪费元素/字节,但会为您排序字节序。EG XMINT4,只是将第一个元素.x用作您的值,或者,如果需要,则将其他元素用于其他目的,但命名不正确(请确保添加注释)。注意:XMINT2数组也将不符合逻辑顺序

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.