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?
2 replies to this topic
Sponsor:
#2 Members - Reputation: 1124
Posted 27 November 2012 - 12:16 PM
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()))
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()))
Edited by eppo, 27 November 2012 - 12:29 PM.
#3 Members - Reputation: 255
Posted 27 November 2012 - 01:09 PM
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?
[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?
Edited by cephalo, 27 November 2012 - 06:06 PM.






