简体   繁体   English

编组C#结构为DX11 cbuffers

[英]Marshalling C# Structs into DX11 cbuffers

I'm having some issues with (i think) the packing of my structure in C# and passing them through to cbuffers i have registered in HLSL. 我有一些问题(我认为)在C#中打包我的结构并将它们传递给我在HLSL中注册的cbuffers。 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;
}

When i create this struct and set it as my constant buffer in C# it seems to work just fine. 当我创建这个结构并在C#中将其设置为我的常量缓冲区时,它似乎工作得很好。 I get what colours returned that i expect: 我得到了我期望的颜色:

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

But when i change the structure to be a struct using another struct it does seem to set properly. 但是当我使用另一个结构将结构更改为结构时,它似乎确实设置正确。 Note that internal struct is going to be containing extra information in it, but i was trying to simplify it as much as possible for now: 请注意,内部结构将包含其中的额外信息,但我现在试图尽可能地简化它:

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

And in HLSL 在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 you think there is a problem in the way i am packing my structs? 你觉得我收拾结构的方式有问题吗? Or could the issue be elsewhere, i only think it is my packing because i can get the first example to work when i set the constant buffer with a TestStruct, but as soon as i expand it to include the InternalTestStruct it doesn't seem to work. 或者问题可能在其他地方,我只认为这是我的包装,因为我可以得到第一个例子,当我用TestStruct设置常量缓冲区时,但只要我扩展它以包含InternalTestStruct它似乎不工作。

Any help would be great. 任何帮助都会很棒。

Thanks in advance. 提前致谢。

When you use: 当你使用:

struct InternalType
{
    int type;
}

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

since InternalType is of size 4 it will pack into the layout of 16, so it's exactly the same as if you were just using an int. 因为InternalType的大小为4,所以它将打包成16的布局,所以它与你刚刚使用int的方式完全相同。

To match the second c# structure using InternalTestStruct, you'd need to do: 要使用InternalTestStruct匹配第二个c#结构,您需要执行以下操作:

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

If you change internaltype to a size larger than one the padding will then become automatic (but it's always nice to keep it explicit). 如果将internaltype更改为大于1的大小,则填充将变为自动(但保持显式始终是好的)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM