[SlimDX-11] updating a constant buffer each frame

Started by
1 comment, last by cephalo 11 years, 4 months ago
I've been trying to google some SlimDX samples of updating a typical worldviewproj constant buffer, and I'm getting a lot of differences and performance, marshaling gotcha's from the internets that I don't fully understand.
Let's say I have this buffer:
[source lang="csharp"] struct WorldProjectionViewBuffer
{
public Matrix World { get; set; }
public Matrix Projection { get; set; }
public Matrix View { get; set; }
public Vector4 VecEye { get; set; }

public static int SizeOf
{
get
{
int size = Marshal.SizeOf(Matrix.Identity) * 3 + Marshal.SizeOf(Vector4.Zero);
return size;
}
}
}
[/source]
Which I initialize with:
[source lang="csharp"] var cb = new WorldProjectionViewBuffer();
cb.World = Matrix.Identity;
cb.Projection = Matrix.Identity;
cb.View = Matrix.Identity;
cb.VecEye = Vector4.Zero;

worldViewCBuffer = new Buffer(Game.GraphicsDevice, new BufferDescription {
Usage = ResourceUsage.Dynamic,
SizeInBytes = WorldProjectionViewBuffer.SizeOf,
BindFlags = SlimDX.Direct3D11.BindFlags.ConstantBuffer,
CpuAccessFlags = CpuAccessFlags.Write
});

var data = new DataStream(WorldProjectionViewBuffer.SizeOf, true, true);
data.Write(cb);
data.Position = 0;

Game.GraphicsDevice.ImmediateContext.UpdateSubresource(new DataBox(0, 0, data), worldViewCBuffer, 0);
[/source]
Now, what I have read is that UpdateSubresource is slow for every frame use, and that you want to Map/Unmap such a constant buffer each frame. I'm a little confused by that, as I don't have to read these constants, just update them every frame. I read in MJP's book that the buffer in this case should be write access only and dynamic. So when I use 'MapSubresource', isn't that reading? What is the best way to write a method for updating this buffer every frame?
Advertisement
D3D11_CPU_ACCESS_READ (CpuAccessFlags.Read) implies allowing the cpu to read 'back' from gpu-memory, which in your case you don't need to do.

I'd say for a buffer that's updated every frame:

usage: D3D11_USAGE_DYNAMIC
cpu access: D3D11_CPU_ACCESS_WRITE

...then Map() it with a D3D11_MAP_WRITE_DISCARD flag (unless you wan't to update part of the buffer (which b.t.w. isn't possible with UpdateSubresource()))
Ok, here is my first stab at this. I can't test it right now because I'm neck deep in converting this dx9 project to dx11, and I won't have anything runnable for a while. The commented out parts are what I used to do with dx9.

[source lang="csharp"] public void SetupLighting(Matrix world, Matrix view, Matrix projection, Vector3 vecEye)
{
DataBox box = Game.GraphicsDevice.ImmediateContext.MapSubresource(worldViewCBuffer, MapMode.WriteDiscard, SlimDX.Direct3D11.MapFlags.None);
WorldProjectionViewBuffer viewBuffer = new WorldProjectionViewBuffer();
viewBuffer.World = world;
viewBuffer.View = view;
viewBuffer.Projection = projection;
viewBuffer.VecEye = new Vector4(vecEye, 1);

box.Data.Write<WorldProjectionViewBuffer>(viewBuffer);
box.Data.Position = 0;
Game.GraphicsDevice.ImmediateContext.UnmapSubresource(worldViewCBuffer, 0);

//EffectHandle lightingHandle = effect.GetParameter(null, "World");
//effect.SetValue<Matrix>(lightingHandle, world);
//lightingHandle = effect.GetParameter(null, "View");
//effect.SetValue<Matrix>(lightingHandle, view);
//lightingHandle = effect.GetParameter(null, "Projection");
//effect.SetValue<Matrix>(lightingHandle, projection);
//lightingHandle = effect.GetParameter(null, "vecEye");
//effect.SetValue<Vector4>(lightingHandle, new Vector4(vecEye, 1));
}
[/source]

I'm not confident that I'm doing this right. Can I just write into the returned DataBox and have it stick?

This topic is closed to new replies.

Advertisement