[SharpDX] How to initialize ConstantBuffer?

Started by
5 comments, last by unbird 10 years, 5 months ago

I'm quite confused as to how to correctly initialize the constant buffer using SharpDX. There is basically no documentation explaining how the process differs from the raw C++ process and the only posts I can find that mention doing it with SharpDX seem to be slightly varied use cases.

I have three matrices that need to go in the constant buffer. In my hlsl file, I have:


cbuffer ConstantBuffer : register(b0)
{
    matrix World;
    matrix View;
    matrix Projection;
}

In my C# code, I set up my matrices like so:


_viewMatrix = Matrix.LookAtLH(new Vector3(0, 1, -5), new Vector3(0, 1, 0), Vector3.UnitY);
_projectionMatrix = Matrix.PerspectiveFovLH((float)Math.PI/4f, ratio, .1f, 110f);
_worldMatrix = Matrix.Identity;

Then I set up my constant buffer like so:


_constantBuffer = new BufferData<Matrix>(_device, BindFlags.ConstantBuffer,
	Utilities.SizeOf<Matrix>()*3, new[] { _worldMatrix, _viewMatrix, _projectionMatrix });
_context.VertexShader.SetConstantBuffer(0, _constantBuffer.Buffer);
_context.UpdateSubresource(ref _worldMatrix, _constantBuffer.Buffer);

Now, I'm not 100% sure that I've done it wrong! However, my cube doesn't render anywhere, which I'm very confused about, and I guess I'm assuming it's related to the constant buffer setup as I can't see anything else that might be a problem.

For complete reference, all my code is here: https://gist.github.com/axefrog/7108721 (including "BufferData", which I referenced above)

If my constant buffer setup is fine, can you see anything else in the code that would stop a cube from appearing in the output window? For what it's worth, I am sure there are better ways of rendering cubes, but I'm just learning and it'd be nice to know what I've done wrong in this case.

Advertisement

Are you sure you are allowed to dispose of the backbuffer after creating an RTV for it? I'm talking about lines 110-111. Also, I'm not 100% sure about this but I believe you need to tranpose your matrices before sending them to the shader, since HLSL expects column-major matrices by default (use Matrix.Tranpose()). By the way, what is the purpose of line 129? You've already filled in the constant buffer with data, and since you created it with CPUAccessFlags.None I'm pretty sure calling UpdateResource() on it is illegal.

Also, I'm pretty sure the way your BufferData works is wrong. You can't just give the Buffer a DataStream upon initialization and assume it's going to give you a direct window into GPU memory so that writing into that stream instantly updates the buffer GPU-side. That DataStream parameter is meant for you to let DX11 initialize the buffer immediately, especially if it's created as an Immutable resource - which cannot be modified after being created. It's only for initialization purposes and is ignored after creation. I believe you're supposed to fill in that DataStream beforehand and then give it to the buffer constructor (remember to reset its position to zero). At this point I don't think anything is actually getting uploaded to the GPU.

Anyway, does the debug runtime say anything? Open the DX11 control panel, add your program to the exception list, create the device with the Debug flag, and monitor the output. If something goes wrong the debug layer should spit out some info to help you see what's happening.

“If I understand the standard right it is legal and safe to do this but the resulting value could be anything.”

Two remarks:

  • The BufferData class is initializing a Buffer object with a Stream, but the stream cannot be updated later. It must be used only to pass initial data to the buffer. The BufferData.Update() won't do anything.
  • _context.UpdateSubresource() is supposed to update the whole constant buffer, so you need to pass a region in memory that holds World, View, Proj in the same memory layout than the cbuffer declared in your shader.

Something like this:


[StructLayout(LayoutKind.Sequential)]
public struct ConstantBufferData
{
  public Matrix World;
  public Matrix View;
  public Matrix Projection;
}
// ....
ContantBufferData data;
[.... fill data]
var contantBuffer = Buffer Create(device, BindFlags.ConstantBuffer, ref data);
[...in rendering loop]
data.World = ...;
_context.UpdateSubresource(ref data, constantBuffer);


Note that using a struct can be problematic in case you have managed objects (array) inside. In this case, you will have to use a different approach (Use a DataBuffer or DataStream and manage the layout in unamanaged memory yourself).

Thanks for the comments, they helped clarify a few things, and I was able to clean up my code a bit, so that's good.

However in the end, my cube still doesn't display. I simply get a black window. I've updated the gist to the latest version of my code here:

https://gist.github.com/axefrog/7108721

I've also attached the code as a zip, on the off chance that someone wants the actual files and visual studio solution. If you *do* download it, it's VS2012, and you'll need to do a NuGet package restore on build.

I'm sure I must be doing something stupid, but given my noob status in this area, I'm having a bunch of trouble spotting the problem...

p.s. I was trying to follow this tutorial: http://msdn.microsoft.com/en-us/library/ff729721.aspx

You're defining your indices as R16 but they're actually 32-bit (TriangleIndex members).

Such things are best diagnosed with PIX/graphics debugger.

Awesome, thanks! I now have a (sort of) cube. It's not rendering the sides but I'm sure I can figure that out myself. I just discovered that in my case, PIX is replaced by the built-in graphics debugger in Visual Studio 2012 in Windows 8. http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275(v=vs.85).aspx

Thanks again for the help, it's tough being a noob!

You're welcome.

You now probably have a winding issue. You can "fix" that by using a rasterizer state disabling culling altogether but it's better to get the winding of your triangles right.

The first steps with a low-level graphics API are frustrating. We all started there wink.png

This topic is closed to new replies.

Advertisement