我传入了一个常量缓冲区,布局如下:
struct
{
float spread;
D2D1_POINT_2F dimension;
D2D1_POINT_2F dimension2;
} m_constants;为了调试起见,dimension和dimension2具有相同的值。
在着色器中,我有:
cbuffer constants
{
float spread;
float2 dimension;
float2 dimension2;
};
float4 main(
float4 pos : SV_POSITION,
float4 posScene : SCENE_POSITION,
float4 uv0 : TEXCOORD0
) : SV_Target
{
float width = dimension.x;
float height = dimension.y;
float2 uv2 = float2(posScene.x / width, posScene.y / height);
color.rgb = float3(uv2.xy, 0);
return color;
}理论上,这应该会输出一个左下角为绿色,右上角为红色的渐变。事实的确如此。但是,如果在着色器中我有足够的宽度和高度来使用dimension2。我得到一个水平渐变,从左边的绿色到右边的黄色。
为什么会这样呢?当我将m_constants传递给着色器时,这两个维度具有相同的值
发布于 2013-01-30 04:56:58
常量缓冲区数据默认按16字节对齐,因此这意味着:
cbuffer constants
{
float spread;
float2 dimension;
float2 dimension2;
};将会是
cbuffer constants
{
float spread; // 4 bytes
float2 dimension; // 4 + 8 = 12 bytes
float dummy; //12+8 = 20, which means we cross 16 for dimension 2, hence a dummy 4 bytes element is added
float2 dimension2;
};这里有一个描述这一点的link。
因此,安排结构的更好方法是:
struct
{
D2D1_POINT_2F dimension;
D2D1_POINT_2F dimension2;
float spread;
} m_constants;并相应地修改hlsl副本:
cbuffer constants
{
float2 dimension;
float2 dimension2;
float spread; // No more 16 bytes crossing problem
};另一种方法是在不修改初始布局的情况下,在c++ side中声明您的结构,如下所示:
#pragma pack(push)
#pragma pack(16)
struct
{
float spread;
D2D1_POINT_2F dimension;
D2D1_POINT_2F dimension2;
} m_constants;
#pragma pack(pop)这将强制结构对齐16个字节。
您也可以使用/Zp16编译器标志,但这将应用于程序中的每个结构(这并不总是可取的)。在visual studio中,转到“项目属性”“-> c/c++ ->代码生成”,然后有“结构成员对齐”选项,您可以在其中进行设置。
您也可以在c++端使用packoffset,但这意味着hlsl布局需要与打包的hlsl布局匹配(这意味着您在hlsl常量缓冲区中保持相同的顺序,但仍然必须修改hlsl版本)。
https://stackoverflow.com/questions/14574061
复制相似问题