问题
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. 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. 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
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.
Any help would be great.
Thanks in advance.
回答1:
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.
To match the second c# structure using InternalTestStruct, you'd need to do:
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).
来源:https://stackoverflow.com/questions/8145279/marshalling-c-sharp-structs-into-dx11-cbuffers