HLSL: ошибка упаковки?

Я передаю в постоянный буфер со следующим макетом:

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 в шейдер

1

Решение

Данные постоянных буферов по умолчанию выровнены на 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 ++).

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]