XBOX performance, space ship interior/exterior gameplay

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
meathelix
Posts: 14
Joined: Tue Oct 19, 2010 6:39 pm

XBOX performance, space ship interior/exterior gameplay

Post by meathelix »

I recently ported a project over to the 360 to some quite disappointing results. I knew there would be performance issues, but I didn't anticipate dropping to less than a frame per second as I have. It's quite likely I'm completely abusing Bepu under the hood, so I thought I'd post here with what I was doing and see if there was a better plan. Also worth noting I'm working in 0.14.3, as I haven't had time to move everything over to that as well as do the console port just yet.

First off, I looked at the other threads and tried the multithreading fix, setting the collision types to DiscreteMPRGJK, and took the collision response iterations down to 5. All of this did little to nothing to help.

Here's a video of the game running on the PC to give an idea of the geometry complexity: http://www.youtube.com/watch?v=IDOvCjkjPsc

Ok, so first I load in 20 ships from a tile based XML format. Each of these ships has around 20 rooms that have a box for the floor and ceiling and 2 or more walls that are static mesh geometry. All of those entities are shoved into a physics space that only belongs to that ship. Each ship has its own space with the interior physics geometry. There's also a global space, and each ship has a compound object that lives there with a box for each room of the ship. On any given frame, the exterior space is updated, plus only the interior space that the player is inhabiting. All of the other ship interior spaces don't get touched. There are also 50 asteroids in the global space that have spheres associated with them.

The player is a cylinder, and I've been doing a raycast from the player's head each frame to determine if there's an interactive object present in order to pop up its name on the hud.

Removing all of the collision objects for the interior of the ships (and setting the space's gravity to 0 to keep the player from plummeting out) gave me a significant boost in framerate. Taking down the number of ships and asteroids did nothing. I think removing the raycast each frame helped, but if it did it was only a minor amount. I did the above optimizations on all of the internal spaces as well as the external one with no appreciable result.

Is there anything I'm missing? Does this setup just sound like something ludicrous to try on the 360? It doesn't look that intense, but there could be a buildup of a lot of elements that just make the whole thing unsound.
meathelix
Posts: 14
Joined: Tue Oct 19, 2010 6:39 pm

Re: XBOX performance, space ship interior/exterior gameplay

Post by meathelix »

Attaching my source code in case someone is bored enough to dig through it. It's all pretty horrible right now, as I'm in the throwing paint on canvas phase and haven't started going back to refactor and make things general purpose and nice.
Attachments
Ship3d.cs
Ship interior code
(8.17 KiB) Downloaded 231 times
Game1.cs
Main game loop
(32.52 KiB) Downloaded 230 times
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: XBOX performance, space ship interior/exterior gameplay

Post by Norbo »

How long is each individual timestep actually taking? Is it really taking upwards of a second per update, or is it more like 20-30 ms of computation per 16 ms of simulation time with internal timestepping? The former case implies something is badly wrong, though I don't know what it would be right now. The latter case implies it just needs more regular optimizing and refinement to get the physics update in budget.

By your description, it doesn't sound like you have extravagantly complex compound bodies or anything. I see at a glance some stuff in Ship3d that looks like it's creating Box entities as voxels or something similar, but I'm not sure. Even if it were, using those for the interior would probably be just fine since only one such complicated object would be managed at any time. A single raycast per frame won't amount to anything in the grand scheme of things so I wouldn't worry about that either.

At a glance it appears that your world is also scaled up by a factor of 10. That will likely produce more difficult situations for various parts of the engine. Normalizing the sizes is recommended and may help avoid numerical problems now or in the future. Since the engine may have to do a little less work to figure out certain configurations, it may provide a little speed boost.

The two files provided seem to be using the windows-style multithreading setup. That will wreak havoc on the Xbox360, since it does not schedule threads across cores automatically like the PC. Their processor affinity needs to be set, and care needs to be taken to provide the proper number of threads:

Code: Select all

            Space.ThreadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 1 }); }, null);
            Space.ThreadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 3 }); }, null);
            Space.ThreadManager.AddThread(delegate { Thread.CurrentThread.SetProcessorAffinity(new[] { 5 }); }, null);
More information on threading can be found in the documentation: http://bepuphysics.codeplex.com/wikipag ... umentation

Here's another shot in the dark; I don't know how much it would end up affecting overall performance, but having a ton of interior spaces with their own (even inactive) thread pools could cause some unnecessary overhead. There's a bunch of idle threads hanging around, basically. The PC can handle it without a problem, but I bet the compact framework would choke on them a lot more easily. ThreadManagers can be shared between multiple spaces by setting the space's thread manager property. Be careful to dispose the pre-existing thread manager, though.

v0.15.0+ is known to be speedier than v0.14.3 as well, to varying degrees depending on what is being simulated.
meathelix
Posts: 14
Joined: Tue Oct 19, 2010 6:39 pm

Re: XBOX performance, space ship interior/exterior gameplay

Post by meathelix »

[EDIT: Figured this out. The code has to be in an #if XBOX block, then it all builds nicely]

I can't tell if I'm supposed to include System.Threading with this or Bepusphyics.Threading

With the former, the Thread keyword resolves fine, but the SetProcessorAffinity method isn't recognized. With the latter, Thread isn't recognized. The castle example used System, but the Xbox multithreading code block was all commented out.
meathelix
Posts: 14
Joined: Tue Oct 19, 2010 6:39 pm

Re: XBOX performance, space ship interior/exterior gameplay

Post by meathelix »

Ok, state of the problem update...

I get a good framerate on the 360 when I both remove the static meshes from the ship interiors, and remove the compound bodies that represent the ships from the world space.

The static meshes needed to be replaced anyway, because they're just mesh copies of the visible geometry, and it's very simple but concave in places and probably a mess under the hood.

The compound body thing is puzzling, as they're all just boxes, and there aren't a ton of them.

Another thing I've noticed with all of this is that multithreading has had no impact. When it was slow, turning it on didn't make it faster, and when it was fast, turning it off didn't make it slower.

I'm beginning to feel a bit out of my depth here.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: XBOX performance, space ship interior/exterior gameplay

Post by Norbo »

I'd recommend trying to replicate bits of the simulation in a separate environment and seeing how they behave in isolation. Making a demo in the BEPUphysicsDemos project of individual parts would be a good option. If you find something weird doing that, it will be easy for me to analyze.
darax
Posts: 1
Joined: Fri Apr 29, 2011 7:12 am

Re: XBOX performance, space ship interior/exterior gameplay

Post by darax »

I scanned through game1.cs. As a thought, you may wish to track how long each step in your game loop is taking.
something like
DateTime StartTime = DateTime.Now;
<do stuff>
Debug.WriteLine("Stuff took {0}",(DateTime.Now-StartTime).TotalMilliseconds);

sprinkled in your update and draw methods would let you see where you are really bogged down.

One optimization that improved a previous project I was working on was culling objects that weren't in view. I don't see you doing this. It's very easy:
BoundingFrustrum mViewFrustrum = new BoundingFrustum(CameraViewMatrix * CameraProjectionMatrix); //This usually gets updated once per frame as part of calculating the camera.

and in my draw calls a simple
if(mViewFrustrum .Contains(Position))
{
//draw
} //otherwise, don't bother drawing the object as it is not in view

You might be doing this, but it wasn't obvious. When I added this, the perf benefit was substantial. Also, if you can batch up your draw calls such that you don't have to switch textures/geometries as often, you'll see a perf benefit. Sometimes this means coding up a render manager that accepts 'draw' calls but behind the scenes batches them up. I also made this optimization and it was a big perf win-but a significant complexity increase. The added complexity, however, seems to have been a step toward the industry standard way of doing things.

Here's what I ended up with-I'm not going to include everything, but you'll hopefully get the idea (and understand that this is probably NOT optimal, it's just what I happend to come up with):
public void EndFrame()
{
TexturedDrawInfo previous = new TexturedDrawInfo();
TextureShader.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
LightedShader.GraphicsDevice.RasterizerState = RasterizerState.CullNone;
BasicEffect CurrentEffect=TextureShader;
foreach (TexturedDrawInfo drawInfo in TexturedGeometries) //BeginFrame clears TexturedGeometries, draw calls add to TexturedGeometries
{
if (drawInfo.LightColor != Vector3.Zero)
{
if (CurrentEffect != LightedShader)
{
CurrentEffect = LightedShader;
CurrentEffect.GraphicsDevice.SetVertexBuffer(drawInfo.Verticies);
CurrentEffect.Texture = drawInfo.Texture;
}
LightedShader.AmbientLightColor = drawInfo.LightColor;
LightedShader.DiffuseColor = Color.White.ToVector3();

}
else
{
if (CurrentEffect != TextureShader)
{
CurrentEffect = TextureShader;
CurrentEffect.GraphicsDevice.SetVertexBuffer(drawInfo.Verticies);
CurrentEffect.Texture = drawInfo.Texture;
}
}
CurrentEffect.World = drawInfo.World;
if (previous.Verticies != drawInfo.Verticies) //objects with the same geometries...no reason to set the vertex buffer
{
CurrentEffect.GraphicsDevice.SetVertexBuffer(drawInfo.Verticies);
}
if (previous.Texture != drawInfo.Texture) //objects with the same texture, no reason to change the texture
{
CurrentEffect.Texture = drawInfo.Texture;
}

previous = drawInfo;
foreach (EffectPass pass in CurrentEffect.CurrentTechnique.Passes)
{
pass.Apply();
CurrentEffect.GraphicsDevice.DrawPrimitives(drawInfo.PrimType, 0, drawInfo.PrimitiveCount);
}
}

}

I've only just started with Bepu, and one thing that I do which you don't is update physics on a separate thread. Doing this does require a little care when you add physics objects (I just lock the space object) but definately increased my windows performance. Still need to see what happens on the xbox.

Physics thread:
public void RunPhysics()
{
float dt = 1.0f / 60.0f;
TimeSpan sleepTime = TimeSpan.FromSeconds(dt);
try
{
while (1 == 1)
{
lock (PhysicsWorld) //Anywhere you add/remove objects you must also 'lock'.
{
PhysicsWorld.Update(dt);
}
Thread.Sleep(sleepTime);
}
}
catch (ThreadAbortException)
{
return;
}
}


You have to spawn the thread ( i do this in loadcontent():
PhysicsThread = new Thread(new ThreadStart(RunPhysics));
PhysicsThread.Start();

and at shutdown (unloadcontent is working for me) you need to kill the thread:
if (PhysicsThread != null && PhysicsThread.IsAlive)
{
PhysicsThread.Abort();
}

I have something like 3000 cubes in my scene before FPS drops below 30 on windows. Again, I still need to try xbox, but haven't gotten around to trying.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: XBOX performance, space ship interior/exterior gameplay

Post by Norbo »

I've only just started with Bepu, and one thing that I do which you don't is update physics on a separate thread.
I would be careful with this; particularly on the Xbox. It complicates code quite a bit and makes using internal multithreading a little more difficult. Accessing entity properties for rendering requires atomically retrieving buffered/interpolated states from the space's BufferedStatesManager, or else it's possible for half of the entities to be in one frame's position, and half in another. This is sort of like screen tearing when vsync isn't on, except for physics data. Corrupt data (half updated) could also be retrieved if the direct entity properties are used.

If the simulation is using internal multithreading, it should be given threads/cores that it has exclusive access to. When running the physics in a different thread, this means the main core handling gameplay logic/rendering can't efficiently be used. On the Xbox, this eliminates a third of the available cores basically. When a game's systems update everything in a 'fork and join' type way (with no big separate computation threads running simultaneously), every component can use every core to its full extent. It also can produce relatively simple code since threading behavior doesn't need to be handled outside of any individual component.

There are situations where asynchronous updating can be useful, though. One advantage is that your rendering rate is not limited by the physics rate. If your physics can't keep up, though, you will see very slow moving, jerky physics at 60 rendered fps.
Post Reply