Skip to content

Commit 3bfa564

Browse files
committed
vk/windows: Try to keep msq thread from ever stopping
- NVIDIA drivers hook into the msq before our nativeEvent handler. This means NV is aware of events before rpcs3 is aware of them and sometimes stops until a new event is triggered. If rpcs3 is inside a driver call at this time, the system will deadlock since the driver waits for msq which waits for the renderer which waits for the driver. - Use explicit hook management to control window events - Add fence timeout to attempt detection of surface loss events
1 parent 987b607 commit 3bfa564

File tree

7 files changed

+420
-314
lines changed

7 files changed

+420
-314
lines changed

rpcs3/Emu/RSX/GSRender.h

Lines changed: 75 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#pragma once
1+
#pragma once
22

33
#include "Emu/RSX/RSXThread.h"
44
#include <memory>
@@ -35,13 +35,14 @@ struct RSXDebuggerProgram
3535

3636
enum wm_event
3737
{
38-
none, //nothing
39-
geometry_change_notice, //about to start resizing and/or moving the window
40-
geometry_change_in_progress, //window being resized and/or moved
41-
window_resized, //window was resized
42-
window_minimized, //window was minimized
43-
window_restored, //window was restored from a minimized state
44-
window_moved, //window moved without resize
38+
none, // nothing
39+
toggle_fullscreen, // user is requesting a fullscreen switch
40+
geometry_change_notice, // about to start resizing and/or moving the window
41+
geometry_change_in_progress, // window being resized and/or moved
42+
window_resized, // window was resized
43+
window_minimized, // window was minimized
44+
window_restored, // window was restored from a minimized state
45+
window_moved, // window moved without resize
4546
window_visibility_changed
4647
};
4748

@@ -62,57 +63,78 @@ using draw_context_t = void*;
6263
>;
6364
#endif
6465

65-
class GSFrameBase
66-
{
67-
public:
68-
GSFrameBase() = default;
69-
GSFrameBase(const GSFrameBase&) = delete;
70-
virtual ~GSFrameBase() {}
66+
class GSFrameBase
67+
{
68+
public:
69+
GSFrameBase() = default;
70+
GSFrameBase(const GSFrameBase&) = delete;
71+
virtual ~GSFrameBase() {}
7172

72-
virtual void close() = 0;
73-
virtual bool shown() = 0;
74-
virtual void hide() = 0;
75-
virtual void show() = 0;
73+
virtual void close() = 0;
74+
virtual bool shown() = 0;
75+
virtual void hide() = 0;
76+
virtual void show() = 0;
77+
virtual void toggle_fullscreen() = 0;
7678

77-
virtual void delete_context(draw_context_t ctx) = 0;
78-
virtual draw_context_t make_context() = 0;
79-
virtual void set_current(draw_context_t ctx) = 0;
80-
virtual void flip(draw_context_t ctx, bool skip_frame=false) = 0;
81-
virtual int client_width() = 0;
82-
virtual int client_height() = 0;
79+
virtual void delete_context(draw_context_t ctx) = 0;
80+
virtual draw_context_t make_context() = 0;
81+
virtual void set_current(draw_context_t ctx) = 0;
82+
virtual void flip(draw_context_t ctx, bool skip_frame = false) = 0;
83+
virtual int client_width() = 0;
84+
virtual int client_height() = 0;
8385

84-
virtual display_handle_t handle() const = 0;
86+
virtual display_handle_t handle() const = 0;
8587

86-
protected:
88+
protected:
8789

88-
//window manager event management
89-
wm_event m_raised_event;
90-
std::atomic_bool wm_event_raised = {};
91-
std::atomic_bool wm_event_queue_enabled = {};
90+
// window manager event management
91+
std::deque<wm_event> m_raised_events;
92+
std::atomic_bool wm_event_queue_enabled = {};
93+
std::atomic_bool wm_allow_fullscreen = { true };
9294

9395
public:
94-
//synchronize native window access
95-
std::mutex wm_event_lock;
96+
// synchronize native window access
97+
shared_mutex wm_event_lock;
98+
99+
void wm_wait() const
100+
{
101+
while (!m_raised_events.empty() && !Emu.IsStopped()) _mm_pause();
102+
}
96103

97-
virtual wm_event get_default_wm_event() const = 0;
104+
bool has_wm_events() const
105+
{
106+
return !m_raised_events.empty();
107+
}
98108

99109
void clear_wm_events()
100110
{
101-
m_raised_event = wm_event::none;
102-
wm_event_raised.store(false);
111+
if (!m_raised_events.empty())
112+
{
113+
std::lock_guard lock(wm_event_lock);
114+
m_raised_events.clear();
115+
}
116+
}
117+
118+
void push_wm_event(wm_event&& _event)
119+
{
120+
std::lock_guard lock(wm_event_lock);
121+
m_raised_events.push_back(_event);
103122
}
104123

105124
wm_event get_wm_event()
106125
{
107-
if (wm_event_raised.load(std::memory_order_consume))
126+
if (m_raised_events.empty())
108127
{
109-
auto result = m_raised_event;
110-
m_raised_event = wm_event::none;
111-
wm_event_raised.store(false);
112-
return result;
128+
return wm_event::none;
113129
}
130+
else
131+
{
132+
std::lock_guard lock(wm_event_lock);
114133

115-
return get_default_wm_event();
134+
const auto _event = m_raised_events.front();
135+
m_raised_events.pop_front();
136+
return _event;
137+
}
116138
}
117139

118140
void disable_wm_event_queue()
@@ -124,6 +146,16 @@ class GSFrameBase
124146
{
125147
wm_event_queue_enabled.store(true);
126148
}
149+
150+
void disable_wm_fullscreen()
151+
{
152+
wm_allow_fullscreen.store(false);
153+
}
154+
155+
void enable_wm_fullscreen()
156+
{
157+
wm_allow_fullscreen.store(true);
158+
}
127159
};
128160

129161
class GSRender : public rsx::thread
@@ -141,4 +173,6 @@ class GSRender : public rsx::thread
141173
void on_exit() override;
142174

143175
void flip(int buffer) override;
176+
177+
GSFrameBase* get_frame() { return m_frame; };
144178
};

0 commit comments

Comments
 (0)