5
\$\begingroup\$

I am using SharpDX to render 3D graphics and i cannot get to work constant buffer in my shader since it contains an array. Currently it looks like this:

cbuffer cb0 : register(b0)
{
    matrix mWorld;
    matrix mView;
    matrix mProj;
    float4 vLightDir[2];
    float4 vLightColor[2];
    float4 vOutputColor;
}

But how to define a struct in C#, which will be correctly marshalled to such constant buffer in shader? In C# we don't have "excplicit" array initialization, e.g. this line of code i used in C++ will not work in C#:

struct cb0
{
  // ...
  Vector4 twos[2];// C#: Vector4[] twos;
// ...
}

I always set StructLayout option Pack=16 for my structs for alignment, but HOW to define such struct with C#? i have tried to define struct like this:

struct cb0_t//pack=16
        {
            public Matrix mWorld;
            public Matrix mView;
            public Matrix mProj;
            public Vector4 vLightDir0;
            public Vector4 vLightDir1;
            public Vector4 vLightColor0;
            public Vector4 vLightColor1;
            public Vector4 vOutputColor;
        }

Yes, it works with this, but this IS NOT COOL. Thank you, sorry for my english...

\$\endgroup\$
2
  • \$\begingroup\$ unsafe+fixed is not solution here, as using 'manual' write to stream. it's all awful. \$\endgroup\$
    – Croll
    Mar 10, 2014 at 9:01
  • \$\begingroup\$ Does Vector4[] twos = new Vector4[2] not work? That's strange, I guess. \$\endgroup\$ Mar 13, 2014 at 11:38

2 Answers 2

1
\$\begingroup\$

If you make a light structure and send that as an array it should work, also maybe use two constant buffers?

Looks something like this(HLSL):

struct Light
{
float4 vLightDir;
float4 vLightColor;
};
cbuffer Camera : register(b0)
{
matrix mWorld;
matrix mView;
matrix mProj;
}

cbuffer Lights : register(b1)
{
Light lights[];  
}

C#

[StructLayout(LayoutKind.Sequential)]
public struct Light
{
public Vector4 LightDir;
public Vector4 LightColor;
}
[StructLayout(LayoutKind.Sequential)]
public struct Camera
{
public Matrix mWorld;
public Matrix mView;
public Matrix mProj;
}
private Light[] lights = new Light[2] { };
private Buffer LightCB;

public void updatelight(DirectXDevice _dev)
{
lights(0) = new light();
lights(0).LightDir = new vector4();
lights(0).LightColor = new vector4();
lights(1) = new light();
lights(1).LightDir = new vector4();
lights(1).LightColor = new vector4();
LightCB = _dev.CreateBuffer(BindFlags.ConstantBuffer, lights);
}
\$\endgroup\$
0
\$\begingroup\$

It looks like you can use the MarshalAs attribute like so

[StructLayout(LayoutKind.Sequential, Pack = 16)]
public struct cb0_t
{
    public Matrix mWorld;
    public Matrix mView;
    public Matrix mProj;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
    public Vector4[] vLightDir;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
    public Vector4[] vLightColor;
    public Vector4 vOutputColor;
} 

You can take a look at this article, search for the heading Arrays.

Otherwise here's a shorter solution on StackOverflow.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .