Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm having some issues with the packing of my structure in C# and passing them through to cbuffers I have registered in HLSL. When I pack my struct in one manner the information seems to be able to pass to the shader:

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

    [FieldOffset(12)]
    public int type;
}

This works perfectly when used against this HLSL fragment:

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;
}

However, when I use the following structure definitions...

// Note this is 16 because HLSL packs in 4 float 'chunks'.
// It is also simplified, but still demonstrates the problem.
[StructLayout(Layout.Explicit, Size = 16)] 
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 mInternal;
}

... the following HLSL fragment no longer works.

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;
}

Is there a problem with the way I am packing the struct, or is it another issue?

To re-iterate: I can pass a struct in a cbuffer so long as it does not contain a nested struct.

share|improve this question
add comment

1 Answer

The layout is perfectly valid for both samples in C#/HLSL (I did a quick test with your layout and It's working - SharpDX based), so I suspect that there is something wrong elsewhere (marshaling the struct/update of the constant buffer... etc). You should also be able to debug your application with PIX and check exactly if the uploaded buffer is wrongly packed.

share|improve this answer
    
I suspect he might have found a bug in SlimDX. –  Jonathan Dickinson Nov 16 '11 at 16:40
    
I will show my constant buffer C# update code when i get home today, i'm hoping it isn't a SlimDX bug, or if it is i hope it's been fixed :| –  Craig Nov 16 '11 at 23:57
    
SlimDX doesn't manually marshal anything but DirectX structures, so that seems unlikely, but it will depend on what actual API calls you're making (as the code sample currently illustrates none). –  Josh Petrie Nov 17 '11 at 16:30
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.