by Chris » Fri Aug 29, 2025 5:57 pm
phinet wrote: ↑Fri Aug 29, 2025 4:25 pm
Thank you for testing that! I'm sorry I can't be of more help. I'm still completely incapable of reproducing this. I think this might be an issue specific to your machine, but I'll keep an eye out for similar reports.
Maybe AMD/Mesa vs nVidia? lemming mentioned having nVidia using the proprietary driver, I have AMD with Mesa 25.0.7 (latest in Debian unstable). What do you have? Since it seems the issue is trying to present the swapchain prior to the window being shown, causing the driver to wait for something that never happens, a couple possible fixes would be to not try presenting during startup prior to the window being shown, or show the window earlier when it can start presenting to the window. Though I would need to take some time to learn GZDoom's startup code to attempt doing something like that, nor do I understand what the original issue was that lead to
the instigating commit and how that solved whatever that problem was (all it seemed to do before then is show the same window at a earlier point, which is essentially what's needed here, and I don't understand the relation to "phantom window freezing desktop" that the change is meant to handle).
phinet wrote: ↑Fri Aug 29, 2025 4:25 pm
I'm not sure if it's in the debian repos, but you might try switching from sdl2 to sd3+sd2-compat. That might fix the issue for you, but I'm really not sure. I'm also not sure if it;s a good idea to swap out the software you're using, for obvious reason.
On Debian, you can actually have libsdl2 and libsdl2-compat installed together. libsdl2-compat installs the alternate lib into some out of the way location, that you can opt into using with
LD_PRELOAD. A separate package, libsdl2-compat-shim, installs that alternate lib into the normal library path where it's used automatically.
In either case, sdl2-compat unfortunately doesn't fix the issue with Wayland native. It still freezes during init when trying to display startup progress.
EDIT:
Indeed, it seems
setmodeneeded is being set too late, well after
FStartScreen::Render is getting called, so if the display throttling allows a frame to be rendered before
setmodeneeded is set to true after checking the network game status, it freezes. If instead
setmodeneeded is set after
StartScreen is created and before it starts calling
FStartScreen::Render, it works:
Code: Select all
diff --git a/src/d_main.cpp b/src/d_main.cpp
index df64adb84..84b5535e3 100644
--- a/src/d_main.cpp
+++ b/src/d_main.cpp
@@ -3353,7 +3353,11 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector<std::string>& allw
FBaseCVar::EnableCallbacks ();
StartScreen = nostartscreen? nullptr : GetGameStartScreen(per_shader_progress > 0 ? max_progress * 10 / 9 : max_progress + 3);
- if (StartScreen != nullptr) StartScreen->Render();
+ if (StartScreen != nullptr)
+ {
+ setmodeneeded = true;
+ StartScreen->Render();
+ }
// +compatmode cannot be used on the command line, so use this as a substitute
auto compatmodeval = Args->CheckValue("-compatmode");
I have no idea whatsoever if this is a proper fix, I don't know why
setmodeneeded was set so late to begin with, or if the later instance being set true is still needed with the earlier one, or if there's any other conditions where
setmodeneeded should or shouldn't be set, or if it may reintroduce the issue the instigating patch tried to handle, but this fixes the freeze for me.
Also another thing that seems odd to me is with
commit 2e8fb069f30e2427d0810e43fb5944873e7833a9. It's calling
screen->ToggleFullscreen and
V_OutputResized(screen->GetWidth(), screen->GetHeight()); between
screen->BeginFrame();/
twod->Begin(screen->GetWidth(), screen->GetHeight()); and
twod->End();/
screen->Update();. I'm surprised this doesn't cause a problem, toggling fullscreen to show the window, and possibly resize the video output, after the screen frame has begun and the "2d" texture rendering started with the pre-fullscreen size, potentially causing it to go out of sync if going fullscreen caused the framebuffer to change size. Would it make more sense to do that earlier? Like this:
Code: Select all
diff --git a/src/common/startscreen/startscreen.cpp b/src/common/startscreen/startscreen.cpp
index 8800fb0fa..56895ae3e 100644
--- a/src/common/startscreen/startscreen.cpp
+++ b/src/common/startscreen/startscreen.cpp
@@ -667,6 +667,13 @@ void FStartScreen::Render(bool force)
// Do not refresh too often. This function gets called a lot more frequently than the screen can update.
if (nowtime - screen->FrameTime > minwaittime || force)
{
+ if (setmodeneeded)
+ {
+ setmodeneeded = false;
+ screen->ToggleFullscreen(vid_fullscreen);
+ V_OutputResized(screen->GetWidth(), screen->GetHeight());
+ }
+
screen->FrameTime = nowtime;
screen->BeginFrame();
twod->ClearClipRect();
@@ -694,13 +701,6 @@ void FStartScreen::Render(bool force)
DrawTexture(twod, StartupTexture, 0, 0, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END);
}
- if (setmodeneeded)
- {
- setmodeneeded = false;
- screen->ToggleFullscreen(vid_fullscreen);
- V_OutputResized(screen->GetWidth(), screen->GetHeight());
- }
-
twod->End();
screen->Update();
twod->OnFrameDone();
Though again, I have no idea what the implications are of this change. Why it was originally put where it is, and if doing it earlier may be a problem. In either case, it Works For Me(tm).
[quote=phinet post_id=1262459 time=1756506332 user_id=41579]
Thank you for testing that! I'm sorry I can't be of more help. I'm still completely incapable of reproducing this. I think this might be an issue specific to your machine, but I'll keep an eye out for similar reports.
[/quote]
Maybe AMD/Mesa vs nVidia? lemming mentioned having nVidia using the proprietary driver, I have AMD with Mesa 25.0.7 (latest in Debian unstable). What do you have? Since it seems the issue is trying to present the swapchain prior to the window being shown, causing the driver to wait for something that never happens, a couple possible fixes would be to not try presenting during startup prior to the window being shown, or show the window earlier when it can start presenting to the window. Though I would need to take some time to learn GZDoom's startup code to attempt doing something like that, nor do I understand what the original issue was that lead to [url=https://github.com/ZDoom/gzdoom/commit/c3fb744f47fe1590911fbca5cae9c55f87c05325]the instigating commit[/url] and how that solved whatever that problem was (all it seemed to do before then is show the same window at a earlier point, which is essentially what's needed here, and I don't understand the relation to "phantom window freezing desktop" that the change is meant to handle).
[quote=phinet post_id=1262459 time=1756506332 user_id=41579]
I'm not sure if it's in the debian repos, but you might try switching from sdl2 to sd3+sd2-compat. That might fix the issue for you, but I'm really not sure. I'm also not sure if it;s a good idea to swap out the software you're using, for obvious reason.
[/quote]
On Debian, you can actually have libsdl2 and libsdl2-compat installed together. libsdl2-compat installs the alternate lib into some out of the way location, that you can opt into using with [c]LD_PRELOAD[/c]. A separate package, libsdl2-compat-shim, installs that alternate lib into the normal library path where it's used automatically.
In either case, sdl2-compat unfortunately doesn't fix the issue with Wayland native. It still freezes during init when trying to display startup progress.
EDIT:
Indeed, it seems [c]setmodeneeded[/c] is being set too late, well after [c]FStartScreen::Render[/c] is getting called, so if the display throttling allows a frame to be rendered before [c]setmodeneeded[/c] is set to true after checking the network game status, it freezes. If instead [c]setmodeneeded[/c] is set after [c]StartScreen[/c] is created and before it starts calling [c]FStartScreen::Render[/c], it works:
[code]diff --git a/src/d_main.cpp b/src/d_main.cpp
index df64adb84..84b5535e3 100644
--- a/src/d_main.cpp
+++ b/src/d_main.cpp
@@ -3353,7 +3353,11 @@ static int D_InitGame(const FIWADInfo* iwad_info, std::vector<std::string>& allw
FBaseCVar::EnableCallbacks ();
StartScreen = nostartscreen? nullptr : GetGameStartScreen(per_shader_progress > 0 ? max_progress * 10 / 9 : max_progress + 3);
- if (StartScreen != nullptr) StartScreen->Render();
+ if (StartScreen != nullptr)
+ {
+ setmodeneeded = true;
+ StartScreen->Render();
+ }
// +compatmode cannot be used on the command line, so use this as a substitute
auto compatmodeval = Args->CheckValue("-compatmode");
[/code]
I have no idea whatsoever if this is a proper fix, I don't know why [c]setmodeneeded[/c] was set so late to begin with, or if the later instance being set true is still needed with the earlier one, or if there's any other conditions where [c]setmodeneeded[/c] should or shouldn't be set, or if it may reintroduce the issue the instigating patch tried to handle, but this fixes the freeze for me.
Also another thing that seems odd to me is with [url=https://github.com/ZDoom/gzdoom/commit/2e8fb069f30e2427d0810e43fb5944873e7833a9]commit 2e8fb069f30e2427d0810e43fb5944873e7833a9[/url]. It's calling [c]screen->ToggleFullscreen[/c] and [c]V_OutputResized(screen->GetWidth(), screen->GetHeight());[/c] between [c]screen->BeginFrame();[/c]/[c]twod->Begin(screen->GetWidth(), screen->GetHeight());[/c] and [c]twod->End();[/c]/[c]screen->Update();[/c]. I'm surprised this doesn't cause a problem, toggling fullscreen to show the window, and possibly resize the video output, after the screen frame has begun and the "2d" texture rendering started with the pre-fullscreen size, potentially causing it to go out of sync if going fullscreen caused the framebuffer to change size. Would it make more sense to do that earlier? Like this:
[code]diff --git a/src/common/startscreen/startscreen.cpp b/src/common/startscreen/startscreen.cpp
index 8800fb0fa..56895ae3e 100644
--- a/src/common/startscreen/startscreen.cpp
+++ b/src/common/startscreen/startscreen.cpp
@@ -667,6 +667,13 @@ void FStartScreen::Render(bool force)
// Do not refresh too often. This function gets called a lot more frequently than the screen can update.
if (nowtime - screen->FrameTime > minwaittime || force)
{
+ if (setmodeneeded)
+ {
+ setmodeneeded = false;
+ screen->ToggleFullscreen(vid_fullscreen);
+ V_OutputResized(screen->GetWidth(), screen->GetHeight());
+ }
+
screen->FrameTime = nowtime;
screen->BeginFrame();
twod->ClearClipRect();
@@ -694,13 +701,6 @@ void FStartScreen::Render(bool force)
DrawTexture(twod, StartupTexture, 0, 0, DTA_VirtualWidthF, displaywidth, DTA_VirtualHeightF, displayheight, TAG_END);
}
- if (setmodeneeded)
- {
- setmodeneeded = false;
- screen->ToggleFullscreen(vid_fullscreen);
- V_OutputResized(screen->GetWidth(), screen->GetHeight());
- }
-
twod->End();
screen->Update();
twod->OnFrameDone();
[/code]
Though again, I have no idea what the implications are of this change. Why it was originally put where it is, and if doing it earlier may be a problem. In either case, it Works For Me(tm).