Thanks a lot, that did the trick, it’s not showing up now on the hot path at all, which is nice.
I just basically worked from the Microsoft XNA instancing sample, and I guess a lot of stuff is not great there.
For example they resize the array per frame
They do stuff like
// Gather instance transform matrices into a single array.
Array.Resize(ref instanceTransforms, instances.Count);
…
// If we have more instances than room in our vertex buffer, grow it to the neccessary size.
if ((instanceVertexBuffer == null) ||
(instances.Length > instanceVertexBuffer.VertexCount))
{
if (instanceVertexBuffer != null)
instanceVertexBuffer.Dispose();
instanceVertexBuffer = new DynamicVertexBuffer(GraphicsDevice, instanceVertexDeclaration,
instances.Length, BufferUsage.WriteOnly);
}
// Transfer the latest instance transform matrices into the instanceVertexBuffer.
instanceVertexBuffer.SetData(instances, 0, instances.Length, SetDataOptions.Discard);
…
foreach (ModelMeshPart meshPart in mesh.MeshParts)
{
// Tell the GPU to read from both the model vertex buffer plus our instanceVertexBuffer.
GraphicsDevice.SetVertexBuffers(
new VertexBufferBinding(meshPart.VertexBuffer, meshPart.VertexOffset, 0),
new VertexBufferBinding(instanceVertexBuffer, 0, 1)
);
per frame, which really is not optimal i guess.
I changed some stuff about that, well still a lot to optimize obviously.
NOW
my biggest memory filler is SetRenderTarget. I guess I can’t do anything about that though, right?
For stuff like Bloom I need to change it at least 10 times, but that shouldn’t be a problem should it?
eg.
_graphicsDevice.SetRenderTarget(_bloomRenderTarget2DMip2);
But rendertarget changes alone are accountable for more than 20% of my bytes
So … I need to try it out later, but is it generally preferable to use stuff like this?
RenderTargetBinding bindingBloomRenderTarget2DMip0 = new RenderTargetBinding(_bloomRenderTarget2DMip0);
[…]
_graphicsDevice.SetRenderTargets(bindingBloomRenderTarget2DMip0);
EDIT:
OK OK back with some research, which i guess you guys knew already.
So turns out if i use:
- RenderTarget initialized earlier and then I use SetRenderTarget(RenderTarget) I create a lot of garbage.
- RenderTargetBinding initialized earlier and then I use SetRenderTargets(RenderTargetBinding) - same garbage.
- RenderTargetBinding initialized earlier and then SetRenderTargets(RenderTargetBinding) no garbage.
It is a bit frustrating that this seems to be the optimal way, yet I have never ever seen it done like this in any sample or tutorial.
Soooo to sum up. The way to do it is apparently:
1.
Create a field in your DrawClass like this
RenderTargetBinding myRenderTargetBinding = new RenderTargetBinding[1];
when creating the rendertargets (aka when resizing or initializing the game) do this:
myRenderTarget2D = new RenderTarget2D( …some properties…);
myRenderTargetBinding[0] = myRenderTarget2D;
in your draw method use this:
graphicsDevice.SetRenderTargets(myRenderTargetBinding);