【问题标题】:Marshalling C# Structs into DX11 cbuffers将 C# 结构编组到 DX11 cbuffers
【发布时间】:2011-11-16 00:52:37
【问题描述】:

我在(我认为)用 C# 打包我的结构并将它们传递给我在 HLSL 中注册的 cbuffer 时遇到了一些问题。当我以一种方式打包我的结构时,信息似乎能够传递给着色器:

[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# marshalling hlsl struct slimdx


    【解决方案1】:

    使用时:

    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 的大小,则填充将变为自动(但保持明确总是好的)。

    【讨论】:

      猜你喜欢
      • 2010-12-17
      • 2022-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多