Sign in to follow this  
NathanRidley

[SharpDX] How to initialize ConstantBuffer?

Recommended Posts

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.

Edited by axefrog

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

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).

 

Share this post


Link to post
Share on other sites

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

Edited by axefrog

Share this post


Link to post
Share on other sites

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!

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this