Я передаю в постоянный буфер со следующим макетом:
struct
{
float spread;
D2D1_POINT_2F dimension;
D2D1_POINT_2F dimension2;
} m_constants;
для отладки размерность и размер2 имеют одинаковые значения.
В шейдере у меня есть:
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;
}
это, теоретически, должно вывести градиент с зеленым цветом внизу слева и красным вверху справа. И это так.
Но если в шейдере у меня есть ширина и высота, чтобы использовать размер2 вместо этого. я получаю горизонтальный градиент от зеленого слева до желтого справа.
Это почему? оба измерения имеют одинаковое значение, когда я передал m_constants в шейдер
Данные постоянных буферов по умолчанию выровнены на 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;
};
вот ссылка на сайт это описывает это.
Таким образом, лучший способ организовать вашу структуру:
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 ++, либо объявить вашу структуру следующим образом:
#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 ++ -> Генерация кода, затем у вас есть опция «Выравнивание элементов Struct», из которой вы можете установить ее.
Вы также можете использовать packoffset на стороне hlsl, но тогда это означает, что компоновка c ++ должна совпадать с упакованной hlsl (что означает, что вы сохраняете тот же порядок в константном буфере hlsl, но все же должны изменить версию c ++).
Других решений пока нет …