Jump to content
  • Advertisement
Sign in to follow this  
Mattlekim

Performance incressing

This topic is 1489 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,

 

I have wrote my own 2d gaming engine running in xna for windows phone.

 

I would like some advice on how to improve the performance on it.

 

The area of interest is the parallax scrolling.

 

Basically the engine supports as may layers as I need.

 

Each layer can have many anchors. And each anchor can have many textures.

 

each anchor has a rectangle properties that stores the total area on screen that all the textures take up.

This way I can run a simple check to see if the anchor is on screen and if i need to render it to screen or not.

all textures are drawn from a large sprite sheet 1280x1280 to save the GPU changing texture all the time.

 

However if a have a large number of textures in an anchor (50 or more) My framrate starts to drop below 60fps.

 

Sinces the bottle neck is in my anchor code iv posted it bellow.

  public class Ancor
    {
        public Vector2 Pos;
        public int width, height;

        public float Shade = 1f;

        public List<AncorTexture> Textures;

        /// <summary>
        /// crates a full copy of this class
        /// </summary>
        /// <returns></returns>
        public Ancor DeepCopy()
        {
            Ancor a = new Ancor(Vector2.Zero);

            a.Pos = Pos;
            a.width = width;
            a.height = height;
            a.Shade= Shade;
           

            for (int i =0; i < Textures.Count; i++)
                a.Textures.Add(Textures[i].DeepCopy());
            return a;
        }

        public Ancor(Vector2 pos)
        {
            Textures = new List<AncorTexture>();
            width = 100;
            height = 200;
            Pos = pos - new Vector2(width * .5f, height * .5f);
        }

        public Ancor(Vector2 pos, int wdt, int hgt)
        {
            Textures = new List<AncorTexture>();
            Pos = pos;
            width = wdt;
            height = hgt;
        }

        public Ancor(Vector2 pos, int wdt, int hgt,float shade)
        {
            Textures = new List<AncorTexture>();
            Pos = pos;
            width = wdt;
            height = hgt;
            Shade = shade;
        }

        public void AddTexture(Vector2 pos, int imgid)
        {
            Textures.Add(new AncorTexture(pos - Pos, imgid, Game1.TextureAncorToAddRot, Game1.TextureAncorToAddScale));

            ResizeAncor(pos - Pos, imgid, Game1.TextureAncorToAddScale);
        }

        public void ResizeAncor(Vector2 pos, int imgid, float scale)
        {
            Vector2 newoffset = Vector2.Zero;

            Rectangle size = new Rectangle((int)pos.X, (int)pos.Y, SpriteSheetHelper.Data.parts[imgid].Width, SpriteSheetHelper.Data.parts[imgid].Height);
            size.Width = (int)(SpriteSheetHelper.Data.Center[imgid].X * scale * 2);
            size.Height = (int)(SpriteSheetHelper.Data.Center[imgid].Y * scale * 2);
            size.X -= (int)(SpriteSheetHelper.Data.Center[imgid].X * scale);
            size.Y -= (int)(SpriteSheetHelper.Data.Center[imgid].Y * scale);

            if (size.X < 0)
            {
                newoffset.X = size.X;
                Pos.X += size.X;
                width -= size.X;
            }

            if (size.Y < 0)
            {
                newoffset.Y = size.Y;
                Pos.Y += size.Y;
                height -= size.Y;
            }


            for (int i = 0; i < Textures.Count; i++)
                Textures[i].offset -= newoffset;

            if (size.Width + size.X > width)
                width = size.Width + size.X;

            if (size.Height + size.Y > height)
                height = size.Height + size.Y;
        }

        public void Draw(ref SpriteBatch sb, ref Vector2 cam, ref float xdist, ref float ydist)
        {
           
            for (int i = 0; i < Textures.Count; i++)
            {
                
                sb.Draw(SpriteSheetHelper.SSTexture, Textures[i].offset + this.Pos - new Vector2(cam.X * xdist, cam.Y * ydist), SpriteSheetHelper.Data.parts[Textures[i].imgId], new Color(Shade, Shade, Shade, 1),
                    Textures[i].rot, SpriteSheetHelper.Data.Center[Textures[i].imgId], Textures[i].scale, SpriteEffects.None, 0f);
            }

        }

        public void TemplateDraw(ref SpriteBatch sb, Vector2 pos)
        {
            Vector2 scale = new Vector2(100f / width, 100f / height);
            scale = Vector2.One;
            for (int i = 0; i < Textures.Count; i++)
                sb.Draw(SpriteSheetHelper.SSTexture, pos + Textures[i].offset * scale, SpriteSheetHelper.Data.parts[Textures[i].imgId], new Color(Shade, Shade, Shade, 1),
                    Textures[i].rot, SpriteSheetHelper.Data.Center[Textures[i].imgId], Textures[i].scale * scale, SpriteEffects.None, 0f);

        }

        public void Draw(ref SpriteBatch sb, ref Vector2 cam, ref float xdist, ref float ydist , float fade, bool colour)
        {
            for (int i = 0; i < Textures.Count; i++)
                if (i == LayerHander.Texture_Selected && colour)
                    sb.Draw(SpriteSheetHelper.SSTexture, Textures[i].offset + this.Pos - new Vector2(cam.X * xdist, cam.Y * ydist), SpriteSheetHelper.Data.parts[Textures[i].imgId], Color.Red * fade,
                        Textures[i].rot, SpriteSheetHelper.Data.Center[Textures[i].imgId], Textures[i].scale, SpriteEffects.None, 0f);
                else
                    sb.Draw(SpriteSheetHelper.SSTexture, Textures[i].offset + this.Pos - new Vector2(cam.X * xdist, cam.Y * ydist), SpriteSheetHelper.Data.parts[Textures[i].imgId], new Color(Shade, Shade, Shade, 1) * fade,
                        Textures[i].rot, SpriteSheetHelper.Data.Center[Textures[i].imgId], Textures[i].scale, SpriteEffects.None, 0f);

        }
        public void EditorDraw(ref SpriteBatch sb)
        {

        }

    }

Any help would be appricated.

Share this post


Link to post
Share on other sites
Advertisement

The lag appears to be inside Draw().

When you have a lot of textures, Textures.Count is higher, and that causes more things to be drawn, which results in a lower framerate.

I’m not sure what kind of performance you are expecting when you are making 50 draw calls just for one anchor (and who knows how many other anchors there are on the screen in the same frame).

 

 

If the sprites in each anchor don’t change then why not render them all to a single image and make it 1 draw call per anchor instead of 50?

If any of the textures are the same, put the sprites using the same textures in a single vertex buffer and draw them all in one call.

If the textures are not the same, why do you have so many unique textures instead of a texture atlas?

 

When you have sprites sharing the same texture you can draw them in a batch.  If you don’t have any sprites sharing textures, make a way for them to share textures.

 

 

L. Spiro

Share this post


Link to post
Share on other sites

Hi,

 

Thanks for you responce.

 

All draws are part of the same texture, and at the moment my achors remane constant.

 

Now you talk about rendering to a buffer then drawing that buffer to the screen, instead of all the draw calls.

I have a few questions.

 

At what point would this be faster? I know that there is an overhead in changed in texture on the GPU so lets say there are only 2 draw calls. Would it still be faster to render each anchor to a buffer on the loading of the level. And use that buffer to draw with for each anchor when there were only a few draw calls within an anchor?

 

Also what would you say would be the maximum size of a buffer (width and height) before its size causes performance issues?

Edited by Mattlekim

Share this post


Link to post
Share on other sites


At what point would this be faster? I know that there is an overhead in changed in texture on the GPU so lets say there are only 2 draw calls. Would it still be faster to render each anchor to a buffer on the loading of the level. And use that buffer to draw with for each anchor when there were only a few draw calls within an anchor?

 

Depends, do your anchor-textures cause a lot of overdraw? In detail, are there a lot of textures inside each anchor that overlap each other? If so, then using the buffer-technique can yield a performance benefit by removing that overdraw.

 


Also what would you say would be the maximum size of a buffer (width and height) before its size causes performance issues?

 

AFAIK there is no performance overhead in buffer size, at least in the way you would be using them, but there is a maximum texture size depending on the GPU, my 780GTX ti is limited at 16384x16384 (mutally exclusive for each dimension, cannot be exceeded in any dimension even if the other dimension is shrinked).

Share this post


Link to post
Share on other sites


If the sprites in each anchor don’t change then why not render them all to a single image and make it 1 draw call per anchor instead of 50?

 

He's using SpriteBatch and all the textures are the same, so it should be coalescing those calls into a single draw call (assuming SpriteSortMode.Deferred or SpriteSortMode.Texture is being used).

 

And whatever you're doing make sure you aren't using SpriteSortMode.BackToFront or SpriteSortMode.FrontToBack.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!