Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I am in a situation where I am writing a framework in XNA and there will be quite a lot of static (ish) content which wont render that often. Now I am trying to take the same sort of approach I would use when doing non game development, where I don't even think about caching until I have finished my application and realise there is a performance problem and then implement a layer of caching over whatever needs it, but wrap it up so nothing is aware its happening.

However in XNA the way we would usually cache would be drawing our objects to a texture and invalidating after a change occurs. So if you assume an interface like so:

public interface IGameComponent
{
    void Update(TimeSpan elapsedTime);
    void Render(GraphicsDevice graphicsDevice);
}

public class ContainerComponent : IGameComponent
{
    public IList<IGameComponent> ChildComponents { get; private set; }

    // Assume constructor

    public void Update(TimeSpan elapsedTime)
    {
        // Update anything that needs it
    }

    public void Render(GraphicsDevice graphicsDevice)
    {
        foreach(var component in ChildComponents)
        { 
            // draw every component
        }
    }
}

Then I was under the assumption that we just draw everything directly to the screen, then when performance becomes an issue we just add a new implementation of the above like so:

public class CacheableContainerComponent : IGameComponent
{
    private Texture2D cachedOutput;
    private bool hasChanged;
    public IList<IGameComponent> ChildComponents { get; private set; }

    // Assume constructor

    public void Update(TimeSpan elapsedTime)
    {
        // Update anything that needs it
        // set hasChanged to true if required
    }

    public void Render(GraphicsDevice graphicsDevice)
    {
        if(hasChanged) 
        { CacheComponents(graphicsDevice); }
        // Draw cached output
    }

    private void CacheComponents(GraphicsDevice graphicsDevice)
    {
        // Clean up existing cache if needed
        var cachedOutput = new RenderTarget2D(...);
        graphicsDevice.SetRenderTarget(renderTarget);      
        foreach(var component in ChildComponents)
        { 
            // draw every component
        }
        graphicsDevice.SetRenderTarget(null);
    }
}

Now in this example you could inherit, but your Update may become a bit tricky then without changing your base class to alert you if you had changed, but it is up to each scenario to choose if its inheritance/implementation or composition. Also the above implementation will re-cache within the rendering cycle, which may cause performance stutters but its just an example of the scenario...

Ignoring those facts as you can see that in this example you could use a cache-able component or a non cache-able one, the rest of the framework needs not know. The problem here is that if lets say this component is drawn mid way through the game rendering, other items will already be within the default drawing buffer, so me doing this would discard them, unless I set it to be persisted, which I hear is a big no no on the Xbox. So is there a way to have my cake and eat it here?

One simple solution to this is make an ICacheable interface which exposes a cache method, but then to make any use of this interface you would need the rest of the framework to be cache aware, and check if it can cache, and to then do so. Which then means you are polluting and changing your main implementations to account for and deal with this cache...

I am also employing Dependency Injection for alot of high level components so these new cache-able objects would be spat out from that, meaning no where in the actual game would they know they are caching... if that makes sense. Just incase anyone asked how I expected to keep it cache aware when I would need to new up a cachable entity.

share|improve this question

1 Answer 1

You are not specifying if this is a 2D or 3D project, in 2D you are unlikely to run into any problems since modern graphics cards can handle much more complex scenarios, and in 3D just a simple turn of the camera would invalidate all your static terrain.

In theory your solution would work (not sure about the XBox part though) but in practice it will either be premature optimization since your never going to use it, or its going to actually slow things down since just the smallest camera change would necessitate invalidating the caches.

TLDR; Don't worry about it until you run into performance issues, in 2D cases you would need A LOT of sprites before you need to consider simplifying the rendering and in 3D cases you might want to look at OcclusionQueries or Octrees (for starters, there are way more options).

share|improve this answer
    
Sorry this is 2d, I thought I mentioned it but I haven't :( I have said the same thing about premature optimisations, however the counter argument I am receiving is that due to the constraints of the Xbox not handling renderTargets swapping nicely, it has to be developed as a step in the render logic, rather than it just being something added later on. We have spatial rendering and other things in place already, I just wanted to have a good counter argument to stop caching being implemented directly into every entity as like you say, I dont want to have this implemented until its a problem. –  Grofit Jan 21 '12 at 15:13
    
I may be a bit off base here, but if your swapping render targets I assume your doing something akin to bloom or similar? You could in these cases probably draw directly to your final buffer and use masking for rendering your effects only over the last drawn sprite. For instance if you want to add a glow around a sprite, "simply" use a stencil buffer and mark the pixels the sprite occupies, then draw a quad over the position and use the stencil buffer to draw a suitable glow. Obviously its harder than that and maybe I missed something vital, but it would reduce the number of rendertarget swaps –  Daniel Carlsson Jan 22 '12 at 8:39
    
It is not for any effects as such, it is just one of the guys I am working with wants to cache everything (just like bitmap caching). However I don't want to have to write caching logic for every entity as I don't believe we need it, and if we did I think we could add it later, but he tells me we cannot. So I was trying to find out how true the issue with preserving render states are, and if it is a real problem any way around it... –  Grofit Jan 22 '12 at 10:57
    
But what can be cached? Why are you swapping render targets for displaying sprites? It is (as far as I know) true that render target swapping on Xbox is a bit more costly, this is because it requires a memory copy to preserve the data. But I'm a bit stumped as to why you would want to swap render targets if your not making some form of composite image? One way to test things would be to see how many sprites you can render on the xbox before you drop below 60fps, I should imagine it would be more than you need, even if your compositing your characters from dozens of sprites. –  Daniel Carlsson Jan 22 '12 at 21:59
    
I think what the guy is after is more akin to texture baking, where he will render a composition of all smaller entities onto a larger texture and just re-render that every frame rather than each smaller one. For a menu or something it may make sense or anything which is static, but again I agree this shouldn't NEED to be done. –  Grofit Jan 23 '12 at 9:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.