Loading screen freezes

Started by
5 comments, last by NekoCode 9 years, 2 months ago

Hey guys&girls, I am trying to make loading screen and I want to see the load progress, but let me explain what happens next:

When my engine loads a world, it freezes like for about ten seconds, so UI is not updating. I tried to implement multithreading to make UI rendering context, but as some people say, it's not good to have several rendering contexts.

So, are there good way to update it?

Thanks in advance!

Advertisement
The usual way would be: There is exactly one rendering context in the application (what thread it lives on is personal preference; it can be the UI thread or its own thread). The UI thread never blocks for IO. IO can be implemented either non-blocking or in its own thread. If the IO is in its own thread it needs some way to communicate with the rest of the application. Either it sends messages in some way or the other threads periodically poll the IO status (all of these will require some form of synchronization).

The usual way would be: There is exactly one rendering context in the application (what thread it lives on is personal preference; it can be the UI thread or its own thread). The UI thread never blocks for IO. IO can be implemented either non-blocking or in its own thread. If the IO is in its own thread it needs some way to communicate with the rest of the application. Either it sends messages in some way or the other threads periodically poll the IO status (all of these will require some form of synchronization).

It's a bit complicated to do on Mac OS X/Linux.

It's a bit complicated to do on Mac OS X/Linux.

Why?

Both operating systems support threads. Both support semaphores or condition variables. That's really all you need.

In the very, very, very easiest case (you can make it much more sophisticated, of course), the render thread will write requests (a function pointer and an argument like pointer to a file name) to an array. Then it increments the semaphore by the number of items, so the loader thread wakes up and knows how many items to process. It doesn't need to use async I/O at all, on the contrary... blocking is mighty fine (far fewer problems and far less system-dependent low level crap, and no surprises like async ops suddenly running synchronously).

When it is done loading the last asset in the scene/level, it signals a condition variable, or a second semaphore, or it could simply set a boolean flag in an entirely thread-unsafe manner (it doesn't really matter, the worst thing to happen would be that the render thread picks it up a bit later).

The render thread keeps rendering and checks the boolean flag (or condition variable) at the end of every frame. Eventually the flag will become true (or the condvar will), so you know that the data is now ready to be used in the next frame.

Yes... a proper solution is much more evolved (the infamous "resource manager"), but if your problem is really just loading a complete level and not willing to skip redraws during those 10 seconds, then you can do this in like 10-15 lines of code, with a minimum set of needed OS functionality.

I'm with samoth on this one. With either a C++11-capable compiler or boost::thread it is exactly the same code on every operating system (within reasonable limits - some toasters might give troubles).

I guess the op is looking for the easy way..FunctionDoIOAsynch..


It's a bit complicated to do on Mac OS X/Linux.


What have you tried to have come to that conclusion?

If the loading screen has to wait for the world to load, then that kinda defeats the purpose of having the load screen since it will just show up and won't respond like you have found out until the world is loaded. Without some from of asynchronous ( like others have mentioned ) or time-sliced loading, there will always be that paused.

I probably don't have my own loading screen stuff done all that well but I have a function that I call from my file loading routines that essentially takes a percent value and a string and draws them to the screen. I've been having some issues where this would work for awhile and then essentially "freeze" in that my window would appear to be "not responding" while the loading code ran. It occurred to me just now it's probably because I'm not processing any other events or messages while this is going on. Now I have the code below and so far (4 tests) it appears to be working properly without any use of threading.

It's just sortta hacked together using SFML not straight up OpenGL and is probably a horrible example of coding technique but hopefully fits the general idea for what you're looking for to give you some inspiration what to try. It seems to be working for me so far.


void CGame::DoLoadProgress(char strData[], int iPercent)
{
    //m_iProgressTotalSteps is hard coded in constructor.
    sprintf(m_strLoadProgress,"Lab 18 Step %2.2d of %2.2d - %s: %2.2d%%",m_iProgressStep,m_iProgressTotalSteps,strData,iPercent);

    m_TheDisplay.mTheSurfaceWindow->setTitle(m_strLoadProgress);

    m_TheDisplay.mTheSurfaceWindow->clear(sf::Color(255,255,255));
    sf::Text text;
    text.setFont(m_TheDisplay.fontAaargh);
    text.setString(m_strLoadProgress);
    text.setColor(sf::Color(0,64,64,64));
    text.setCharacterSize(12);    //In pixels, not points.
    text.setStyle(sf::Text::Bold);
    m_TheDisplay.mTheSurfaceWindow->draw(text);
    m_TheDisplay.mTheSurfaceWindow->display();

    //Process other events so that we don't get that "window not responding" thing happening.
    sf::Event event;
    while(m_TheDisplay.mTheSurfaceWindow->pollEvent(event))
    {
        switch(event.type)
        {
            case sf::Event::Closed:
                m_TheDisplay.mTheSurfaceWindow->close();
                break;
            default:
                break;
        }

    }

}


Thanks for tips! I will try to create resource loader and renderer threads, so it shouldn't stuck anymore.

This topic is closed to new replies.

Advertisement