Выделение C # структурирует в буферы DX11 - PullRequest
3 голосов
/ 16 ноября 2011

У меня есть некоторые проблемы с (я думаю) упаковкой моей структуры в C # и передачей их через cbuffers, которые я зарегистрировал в HLSL.Когда я упаковываю свою структуру одним способом, кажется, что информация может передаваться шейдеру:

[StructLayout(LayoutKind.Explicit, Size = 16)]
internal struct TestStruct
{
    [FieldOffset(0)]
    public Vector3 mEyePosition;

    [FieldOffset(12)]
    public int type;
}

Когда я создаю эту структуру и устанавливаю ее в качестве моего постоянного буфера в C #, кажется, она работает нормально.Я получаю те цвета, которые я ожидаю вернуть:

cbuffer PerFrame : register(b0)
{
    Vector3 eyePos;
    int type;
}

float3 GetColour()
{
    float3 returnColour = float(0.0f, 0.0f, 0.0f);

    switch(type)
    {
        case 0:
            returnColour = float3(1.0f, 0.0f, 0.0f);
            break;
        case 1:
            returnColour = float3(0.0f, 1.0f, 0.0f);
            break;
        case 2:
            returnColour = float3(0.0f, 0.0f, 1.0f);
            break;
    }

    return returnColour;
}

Но когда я изменяю структуру на структуру, используя другую структуру, она, кажется, устанавливается правильно.Обратите внимание, что внутренняя структура будет содержать дополнительную информацию, но сейчас я пытался максимально упростить ее:

[StructLayout(Layout.Explicit, Size = 16)] //Note this is 16 because HLSL packs in 4 float 'chunks'
internal struct InternalTestStruct
{
    [FieldOffset(0)]
    public int type;
}

[StructLayout(LayoutKind.Explicit, Size = 32)]
internal struct TestStruct
{
    [FieldOffset(0)]
    public Vector3 mEyePosition;

    //Missing 4 bytes here for correct packing.

    [FieldOffset(16)]
    public InternalTestStruct internal;
}

И в HLSL

struct InternalType
{
    int type;
}

cbuffer PerFrame : register(b0)
{
    Vector3 eyePos;
    InternalType internalStruct;
}

float3 GetColour()
{
    float3 returnColour = float(0.0f, 0.0f, 0.0f);

    switch(internaltype.type)
    {
        case 0:
            returnColour = float3(1.0f, 0.0f, 0.0f);
            break;
        case 1:
            returnColour = float3(0.0f, 1.0f, 0.0f);
            break;
        case 2:
            returnColour = float3(0.0f, 0.0f, 1.0f);
            break;
    }

    return returnColour;
}

DoВы думаете, есть проблема в том, как я упаковываю свои структуры?Или проблема может быть в другом месте, я только думаю, что это моя упаковка, потому что я могу заставить первый пример работать, когда я устанавливаю постоянный буфер с TestStruct, но как только я расширяю его, чтобы включить InternalTestStruct, это, кажется, не делаетработа.

Любая помощь будет отличной.

Заранее спасибо.

1 Ответ

0 голосов
/ 21 января 2013

Когда вы используете:

struct InternalType
{
    int type;
}

cbuffer PerFrame : register(b0)
{
    float3 eyePos;
    InternalType internalStruct;
} 

, поскольку InternalType имеет размер 4, он будет упакован в макет из 16, поэтому он точно такой же, как если бы вы просто использовали int.

Чтобы сопоставить вторую структуру c # с использованием InternalTestStruct, вам нужно сделать:

cbuffer PerFrame : register(b0)
{
    float3 eyePos;
    int dummy; //Here you need to force the padding
    InternalType internalStruct;
} 

Если вы измените internaltype на размер больше единицы, заполнение станет автоматическим (но всегда полезно сохранить его).явный).

...