将c#结构编组到DX11缓存中

本文关键字:DX11 缓存 结构 | 更新日期: 2023-09-27 18:14:51

我有一些问题(我认为)在c#中包装我的结构并将它们传递给我在hsl中注册的缓冲区。当我以一种方式包装我的结构时,信息似乎能够传递到着色器:

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

你认为我包装结构的方式有问题吗?或者问题可能在其他地方,我只认为这是我的包装,因为当我用TestStruct设置常量缓冲区时,我可以得到第一个例子,但一旦我将其扩展到包括InternalTestStruct,它似乎不起作用。

请帮忙就太好了。

将c#结构编组到DX11缓存中

使用

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

由于InternalType的大小为4,它将被打包到16的布局中,因此它与您使用int完全相同。

要使用InternalTestStruct匹配第二个c#结构,你需要这样做:

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

如果您将internaltype更改为大于1的大小,则填充将自动生效(但最好保持显式)