Display.update() takes just over 1 second to run in specific situations

Started by chickenofdoom, November 14, 2012, 00:20:35

Previous topic - Next topic

chickenofdoom

I'm making a 2d game, using the space invaders example as a base. When a certain game object is being rendered, and only when that game object is doing things, calls to Display.update() frequently take between 1000 and 1030 milliseconds to run. There is no issue when only rendering the same texture by itself, or when running the game logic without rendering that particular object.

I'm not really sure how to approach this, any idea what might cause it to happen?

CodeBunny

Having a really, really, really slow render step?

What's your rendering code?

chickenofdoom

That's the thing, it's specifically Display.update() that is taking that long. I'm saving
(Sys.getTime() * 1000) / timerTicksPerSecond
to a variable on the line before and the line after I call Display.update(), and it's about 1000 ms (usually exactly 1008). The call to my rendering method in the same loop is always under 10ms.

As for my code, there's a lot of it spread over a number of classes. I might try isolating the problem into some stub code if I can't figure this out soon. As for the rendering itself, I'm basically using the space invaders Sprite class unchanged except I've swapped out the Texture and TextureLoader classes with org.newdawn.slick.opengl.Texture and org.newdawn.slick.opengl.TextureLoader.

CodeBunny

My statement still stands.

The GPU functions asyncronously; calling glBegin() ... glEnd() for example doesn't block until the entire draw process is computed. It queues the commands on the GPU and then allows you to start calling other stuff on the CPU. However, since Display.update() swaps the window buffers, it does need to block in order to show everything correctly. If you attempted to perform some extremely heavy-duty rendering on the GPU, then you'll see exactly the behavior you're talking about.

Of course, it could be some other issue, such as a driver issue/etc, but we'd need some more info to determine that. Do you get better performance on other machines/OSes? Is vsync enabled? Are you calling Display.sleep, and if so, at what framerate?

Also, are you creating/destroying GL data every frame, instead of reusing things across multiple cycles? That's another possibility (however unlikely) that might explain it.

chickenofdoom

I've tried vsync, makes everything run a lot slower overall, doesn't affect the current issue, not currently enabled.

I don't call Display.sleep, and currently use Display.sync(60), though swapping that out for something using Thread.sleep doesn't fix anything.

If I run it on my xp netbook (compared to my windows 7 desktop), I still get some Display.update() lagging in the same situation, but it's at nowhere near the same scale (around 50 ms rather than 1000), and much more consistent.

As far as I know I'm not doing anything like that with GL data. Other than what's in the Sprite, Texture, and TextureLoader classes, the only GL code I call on a regular basis is

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

Fool Running

What GPU/graphics card is in the computer that is really slow? What size is the texture you are attempting to use in the slow case?
Make sure the texture isn't bigger then glGetInteger(GL_MAX_TEXTURE_SIZE) in either the X or Y direction.

EDIT:
Quote from: chickenofdoom on November 14, 2012, 00:20:35...and only when that game object is doing things...
Didn't see this. What does "doing things" entail? What exactly is it doing when it's slow.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

chickenofdoom

Quote from: Fool Running on November 14, 2012, 13:35:56
What GPU/graphics card is in the computer that is really slow? What size is the texture you are attempting to use in the slow case?
Make sure the texture isn't bigger then glGetInteger(GL_MAX_TEXTURE_SIZE) in either the X or Y direction.
My graphics card is a Radeon 5850. The starting size of the texture is currently 380x285, 32kb, though I've changed that and it doesn't seem to make a difference.

Quote
What does "doing things" entail? What exactly is it doing when it's slow.
Making copies of itself. After some more testing I noticed that the one second lags also sometimes occur (less frequently) when the object isn't doing anything, and also there are between 200 and 300 instances of it being rendered. More or less than that and it doesn't happen unless it is making copies.

More tests show that the 200-300 instance lag happens with other objects too, regardless of whether they are even touched by the code before they get rendered, usually when the count is right around 260. More or less that and the lag dissapears entirely.

chickenofdoom

I managed to reproduce the problem in a short piece of code with just rendering.

links to code and files needed to run it:
http://pastebin.com/9xtfChkW
https://www.dropbox.com/sh/674mov0b5u4qi1q/2hel6_lWNC

When I run this, display.update() always takes one second to run every time. When I uncomment the loop at line 168 (which makes 300 more images be rendered per frame), my framerate goes back to 60.

Fool Running

It runs fine for me on my machine at work (horrible Intel integrated graphics). Only thing that I can think of is that it's some weird driver bug.
You might try change the Sprite.draw() method to be the following on the off chance that it has something to do with the worthless push/pop of the matrix stack (Note that this is better anyways since you are avoiding the overhead of the matrix manipulations):
    public void draw(int x, int y) {
        // bind to the appropriate texture for this sprite
        texture.bind();

        // draw a quad textured to match the sprite
        glBegin(GL_QUADS);
        {
            glTexCoord2f(0, 0);
            glVertex2f(x, y);

            glTexCoord2f(0, texture.getHeight());
            glVertex2f(x, y + height);

            glTexCoord2f(texture.getWidth(), texture.getHeight());
            glVertex2f(x + width, y + height);

            glTexCoord2f(texture.getWidth(), 0);
            glVertex2f(x + width, y);
        }
        glEnd();
    }
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

chickenofdoom

When I remove those the program doesn't display anything. Edit: figured that out that it gives a context to the translate position call and that the translate call was the problem.

Turns out it was probably a driver bug though; I updated my graphics drivers and the problem seems to have gone away. Thanks for the help!