2011-11-16 56 views
3

我遇到了一些問題(我認爲)在C#中打包我的結構並將它們傳遞給我在HLSL中註冊的cbuffers。當我在一個地收拾我的結構信息,似乎能夠傳遞到shader:編組C#構造成DX11緩衝區

[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它不似乎上班。

任何幫助將是偉大的。

在此先感謝。

回答

0

當你使用:

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的大小大於一則填充將成爲自動的(但它總是很高興,以保持它明確)。