Sign in to follow this  
Bombshell93

use of DynamicVertexBuffer's for hardware instancing

Recommended Posts

one of my friends is on a Game Dev course in collage and his final exam is to make a game, hes allowed help on art assets and specific parts of an engine (in this case the graphics) so long as he designs and programs the player interaction and gameplay, So I'm writing him a Renderer (in XNA as its what he'd prefer to use)

The game will essentially be a vertical scrolling bullet-hell shooter, that said efficient drawing of multiple similar units is a must, so I've turned to hardware instancing but I'm a bit hesitant to continue to approach it the way I that I have.

I've set up a basic entity / component system to build around. The DrawComponents on creation register themselves with the DrawManager, which then sorts them via the model and texture they reference. When drawing time comes around it checks if there are the same number of instances as the last frame or if there is an instance buffer at all.

if there is not the same number of instances or there isnt a buffer then a new DynamicVertexBuffer is made and filled up (if there was a buffer it is disposed before doing this), if there was a suitable buffer then its data is simple regathered and set (for instances which may have moved or rotated or whatever).

It feels a bit dirty creating a new buffer whenever I need it resized but there doesn't seem to be a way to resize it. I'm not getting any performance issues I'm just wondering if there might be a preferred way to approach hardware instancing for objects which may or may not exist consistently?

Thanks in Advanced,
Bombshell

Share this post


Link to post
Share on other sites

It can be larger than you need. Just make it initially large enough to handle the max number of instances you think you'll need (and either keep the "resize" logic for when you go over, or just fail to draw any additional instances).

Share this post


Link to post
Share on other sites

okay I've given it a go and expanded the rendering engine in general, but I have a problem, for sake of testing I'm drawing 27 instances of a single model (which is fairly low poly), and my framerate is through the floor at 16 FPS.
the problem seems to be updating the vertex buffer (per second taking up over half of the second)
Here is the part taking up the most time, though its worth noting both rendering the shadow map and rendering the scene itself is taking up 12% of the second each too.


				Model model = assetManager.getModel(m);
				if (!buffers.ContainsKey(m) || models[m].Count > modelCount[m])
				{
					if (!buffers.ContainsKey(m))
					{
						buffers.Add(m, null);
						modelCount.Add(m, 0);
					}
					else
						buffers[m].Dispose();

					modelCount[m] = models[m].Count;
					if (modelCount[m] < 10)
						modelCount[m] = 10;
					buffers[m] = new DynamicVertexBuffer(graphicsDevice, vertexDeclaration, 
						modelCount[m], BufferUsage.None);
					instances.Add(m, new Instance[modelCount[m]]);
					int i;
					for (i = 0; i < models[m].Count; i++)
					{
						instances[m][i] = new Instance(models[m][i].transform, 
							camera, models[m][i].textureCoord);
						models[m][i].index = i;
					}
					for (; i < modelCount[m]; i++)
					{
						instances[m][i] = new Instance(Matrix.CreateScale(0), 
							camera, Vector2.Zero);
					}
					buffers[m].SetData(instances[m]);
				}
				else
				{
					int i = 0;
					for (i = 0; i < models[m].Count; i++)
					{
						instances[m][i].transform = 
							Matrix.Transpose(models[m][i].transform);
						instances[m][i].worldViewIT = 
							Matrix.Transpose(Matrix.Invert(instances[m][i].transform * camera.View));
						models[m][i].index = i;
					}
					//for (; i < modelCount[m]; i++)
					//{
					//	instances[i] = new Instance(Matrix.CreateScale(0), camera, Vector2.Zero);
					//}

					buffers[m].SetData(instances[m]);
				}
			}

 


I'm obviously doing something wrong but I'm not all that familiar with how to efficiently use instancing,
if anyone can spare some advice or references on the matter it would be a great help.

My mistake, my stopwatch was placed awkwardly giving me false times, I was also sending a bad value to the draw call telling it to draw thousands of instances.

Edited by bombshell93

Share this post


Link to post
Share on other sites

I can't tell from your code, but make sure you aren't creating new vertex buffers each frame. Just create one (or however many you need) at startup. Then SetData the necessary (changing) data each frame.

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