Skip to content

Commit 0894e7e

Browse files
committed
GS: Snapshot the display resolution for cross-thread reads
GSgetDisplayResolution() took a raw pointer from g_gs_renderer and dereferenced it, but guncon2 calls it from the EE thread. If the GS thread reopened the renderer between the null check and the read, the pointer dangled. Store the resolution on the GS thread where it is already computed and read the copy instead. This matches s_last_draw_rect directly above it, which exists for this exact reason and which the same guncon2 call site already reads via GSTranslateWindowToDisplayCoordinates. Reported by chaoticgd.
1 parent 929cd22 commit 0894e7e

2 files changed

Lines changed: 9 additions & 15 deletions

File tree

pcsx2/GS/GS.cpp

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -662,21 +662,6 @@ void GSgetInternalResolution(int* width, int* height)
662662
*height = res.y;
663663
}
664664

665-
void GSgetDisplayResolution(int* width, int* height)
666-
{
667-
GSRenderer* gs = g_gs_renderer.get();
668-
if (!gs)
669-
{
670-
*width = 0;
671-
*height = 0;
672-
return;
673-
}
674-
675-
const GSVector2i res(gs->PCRTCDisplays.GetResolution());
676-
*width = res.x;
677-
*height = res.y;
678-
}
679-
680665
void GSgetStats(SmallStringBase& info)
681666
{
682667
GSPerfMon& pm = g_perfmon;

pcsx2/GS/Renderers/Common/GSRenderer.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ std::unique_ptr<GSRenderer> g_gs_renderer;
4646
// Since we read this on the EE thread, we can't put it in the renderer, because
4747
// we might be switching while the other thread reads it.
4848
static GSVector4 s_last_draw_rect;
49+
static GSVector2i s_last_display_resolution;
4950

5051
// Last time we reset the renderer due to a GPU crash, if any.
5152
static Common::Timer::Value s_last_gpu_reset_time;
@@ -57,6 +58,7 @@ GSRenderer::GSRenderer()
5758
: m_shader_time_start(Common::Timer::GetCurrentValue())
5859
{
5960
s_last_draw_rect = GSVector4::zero();
61+
s_last_display_resolution = GSVector2i(0, 0);
6062
}
6163

6264
GSRenderer::~GSRenderer() = default;
@@ -221,6 +223,7 @@ bool GSRenderer::Merge(int field)
221223
}
222224

223225
const GSVector2i resolution = PCRTCDisplays.GetResolution();
226+
s_last_display_resolution = resolution;
224227
fs = GSVector2i(static_cast<int>(static_cast<float>(resolution.x) * GetUpscaleMultiplier()),
225228
static_cast<int>(static_cast<float>(resolution.y) * GetUpscaleMultiplier()));
226229

@@ -997,6 +1000,12 @@ void GSTranslateWindowToDisplayCoordinates(float window_x, float window_y, float
9971000
*display_y = rel_y / draw_height;
9981001
}
9991002

1003+
void GSgetDisplayResolution(int* width, int* height)
1004+
{
1005+
*width = s_last_display_resolution.x;
1006+
*height = s_last_display_resolution.y;
1007+
}
1008+
10001009
void GSSetDisplayAlignment(GSDisplayAlignment alignment)
10011010
{
10021011
s_display_alignment = alignment;

0 commit comments

Comments
 (0)