libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.44k stars 1.76k forks source link

Main loop and window dragging in Windows #9102

Closed 1vanK closed 6 months ago

1vanK commented 7 months ago

On Windows, dragging or resizing a window blocks the main thread. Currently the recommended main loop looks like this:

while (game_is_still_running) {
    SDL_Event event;
    while (SDL_PollEvent(&event)) {  // poll until all events are handled!
        // decide what to do with this event.
    }

    // update game state, draw the current frame
}

Is it possible to write this in the form:

while (game_is_still_running) {
    SDL_Event event;
    while (SDL_ExistsEventsInQueue() && SDL_PollEvent(&event)) { // This not block main thread
        // decide what to do with this event.
    }
   // update game state, draw the current frame
}

p.s. SDL_AppIterate() is no good for me. Also I read about SDL_AddEventWatch(), but such things should be hidden inside SDL.

1vanK commented 7 months ago

My idea is to prevent SDL_PollEvent() from blocking when the user moves or resizes the window

1vanK commented 7 months ago

https://sourceforge.net/projects/win32loopl/ https://stackoverflow.com/a/21240384

Starbuck5 commented 6 months ago

FYI, this has already been discussed a lot in https://github.com/libsdl-org/SDL/issues/1059, with a solution implemented for SDL3.

nfries88 commented 6 months ago

kinda hilarious to see that my work over the course of maybe 20 hours is still apparently the most accessible information on this a decade later.

as Starbuck mentioned, SDL3 provides a much more rugged, portable, and simpler solution to this problem by resolving the fundamental conflict between rolling your own main loop with rendering external to event processing and how the OS or compositor wants you to write your main loop (or in many cases, to not do that at all). SDL3 provides an optional callback interface as described in docs/README-main-functions.md use that instead of fighting the OS.

1vanK commented 6 months ago

docs/README-main-functions.md

I use own main() for console version of app, which accepts command line arguments in utf-8 encoding

https://github.com/dviglo2d/dviglo2d/blob/main/libs/dviglo/main/main.hpp#L32-L38 https://github.com/dviglo2d/dviglo2d/blob/main/libs/dviglo/main/main.cpp#L14-L32

1vanK commented 6 months ago

https://github.com/libsdl-org/SDL/commit/02f356439d1fedf0b4e5f96cd23c2d570e2f7be2

When using event watcher, I get SDL_EVENT_WINDOW_EXPOSED message even without changing or moving the window. This hack sjould have its own event name, otherwise, in addition to this crutch, you will have to invent an additional crutch to check that the update and rendering were not called twice per frame: from the main loop and from the watcher.

1vanK commented 6 months ago

In addition, using functions int SDL_AppIterate(void), etc breaks the logic of object-oriented applications with overriding virtual methods update(), render(). Even hack with DL_EVENT_WINDOW_EXPOSED break OOP

nfries88 commented 6 months ago

I'm not sure what you mean by "breaks the logic": SDL_AppIterate would be the appropriate place for all your per-frame logic, you'll just need to make your state global or singleton - or better, encapsulate them in a single global state machine.

You can absolutely make this interface work, developers using high level portable UI frameworks have been pushed to do it forever.

1vanK commented 6 months ago

docs/README-main-functions.md

I need to open log file before SDL init and close after SDL destruction. How can I do this?

1vanK commented 6 months ago

With callbacks when user clicks on app window title, but does not move the window immediately, microfreeze occurs.

1vanK commented 6 months ago

https://gamedev.net/forums/topic/440341-wm_syscommand-and-moving-a-window/3919110/

As you can see, there's a 500ms delay between WM_SYSCOMMAND and the next message.

1vanK commented 6 months ago

Could this issue be reopened? The current solution doesn't work.

Even this not fix the problem изображение

since the frieze occurs within the modal loop and the timer doesn't even work

1vanK commented 6 months ago

This dirty code with manual moving window solve this problem:

https://github.com/dviglo2d/dviglo2d/commit/e16f683008d65591b754a1715827338a94118509#diff-3c25d8de4f6d347a905731062e33d50c15948d07a3bcdcc9c2f785059b05b84a

nfries88 commented 6 months ago

I need to open log file before SDL init and close after SDL destruction. How can I do this?

in the constructor for a static object; same way you make stuff happen before main() gets called.

https://gamedev.net/forums/topic/440341-wm_syscommand-and-moving-a-window/3919110/

As you can see, there's a 500ms delay between WM_SYSCOMMAND and the next message.

oof. has to be waiting on something inside DefWndProc. At this point though, it's basically an OS bug.

1vanK commented 6 months ago

At this point though, it's basically an OS bug.

96% of gamers use Windows: https://store.steampowered.com/hwsurvey/

Therefore, it is not so important whether it is a bug or a feature. The problem cannot just be ignored

nfries88 commented 6 months ago

how many games are routinely played in a bordered window?

and do any of those games that are routinely played in a bordered window not have this issue?

1vanK commented 6 months ago

What difference will any answer make? If SDL solves the problem, there will be more working games. Moreover, SDL is used not only for games, but also for applications.

nfries88 commented 6 months ago

why would you expect SDL to solve this specific problem of DefWindowProc introducing delays?

icculus commented 6 months ago

Can we please not get into this argument again? I already had to lock one issue about this topic.

nfries88 commented 6 months ago

Sorry. On this topic, would it be possible to ensure that the new GPU API can portably be used in a single non-main thread with some basic rules? Since the SDL event queue is already thread-safe, that would enable a good best practice for dealing with this type of problem by moving the entire gameloop to another thread and just using the main thread as an event pump, even if it wouldn't extend to the old SDL2 APIs.

1vanK commented 6 months ago

how many games are routinely played in a bordered window?

and do any of those games that are routinely played in a bordered window not have this issue?

Vampire Survivors

I tested version 1.4.

изображение

There is no frieze when you click on the window title.

According to Wikipedia, they changed the engine in version 1.6, which I have not tested.

1vanK commented 6 months ago

Also cookie clicker (Steam version)

изображение

Of course, these applications are based on a web component and Google was able to solve this problem. But you couldn't.

icculus commented 6 months ago

Okay, I see we're all doing this again, so I'm locking this thread.