summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-12-22 13:35:52 -0500
committerGitHub <noreply@github.com>2025-12-22 13:35:52 -0500
commitf76a2ec004a11025ff100f33886556cf74a20e6b (patch)
treebebce63ed1cbe06742e48891e9526b64e24f0627 /Source/Core/VideoCommon
parent07d071a0b889ac1a7c2e6cc2d03db57cc2fd81e5 (diff)
parent43104036749251ca75454b266e2f49910080c130 (diff)
Merge pull request #14166 from jordan-woyak/immediate-xfb-limit
VideoCommon: Add setting to limit immediate swaps to one per VI.
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/Present.cpp17
-rw-r--r--Source/Core/VideoCommon/Present.h3
2 files changed, 19 insertions, 1 deletions
diff --git a/Source/Core/VideoCommon/Present.cpp b/Source/Core/VideoCommon/Present.cpp
index ea7cb65f95..ea7f2d6d74 100644
--- a/Source/Core/VideoCommon/Present.cpp
+++ b/Source/Core/VideoCommon/Present.cpp
@@ -95,8 +95,13 @@ static void TryToSnapToXFBSize(int& width, int& height, int xfb_width, int xfb_h
Presenter::Presenter()
{
+ auto& video_events = GetVideoEvents();
+
m_config_changed =
- GetVideoEvents().config_changed_event.Register([this](u32 bits) { ConfigChanged(bits); });
+ video_events.config_changed_event.Register([this](u32 bits) { ConfigChanged(bits); });
+
+ m_end_field_hook = video_events.vi_end_field_event.Register(
+ [this] { m_immediate_swap_happened_this_field.store(false, std::memory_order_relaxed); });
}
Presenter::~Presenter()
@@ -109,6 +114,8 @@ bool Presenter::Initialize()
{
UpdateDrawRectangle();
+ m_immediate_swap_happened_this_field.store(false, std::memory_order_relaxed);
+
if (!g_gfx->IsHeadless())
{
SetBackbuffer(g_gfx->GetSurfaceInfo());
@@ -214,6 +221,12 @@ void Presenter::ViSwap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height,
void Presenter::ImmediateSwap(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height)
{
+ if (m_immediate_swap_happened_this_field.exchange(true, std::memory_order_relaxed) &&
+ Config::Get(Config::GFX_HACK_CAP_IMMEDIATE_XFB))
+ {
+ return;
+ }
+
const u64 ticks = m_next_swap_estimated_ticks;
FetchXFB(xfb_addr, fb_width, fb_stride, fb_height, ticks);
@@ -984,6 +997,8 @@ void Presenter::DoState(PointerWrap& p)
m_next_swap_estimated_ticks = m_last_xfb_ticks;
m_next_swap_estimated_time = Clock::now();
+ m_immediate_swap_happened_this_field.store(false, std::memory_order_relaxed);
+
ImmediateSwap(m_last_xfb_addr, m_last_xfb_width, m_last_xfb_stride, m_last_xfb_height);
}
}
diff --git a/Source/Core/VideoCommon/Present.h b/Source/Core/VideoCommon/Present.h
index e9ad21dbd9..7e5ce651e3 100644
--- a/Source/Core/VideoCommon/Present.h
+++ b/Source/Core/VideoCommon/Present.h
@@ -169,6 +169,7 @@ private:
u32 m_last_xfb_height = MAX_XFB_HEIGHT;
Common::EventHook m_config_changed;
+ Common::EventHook m_end_field_hook;
// Updates state for the SmoothEarlyPresentation setting if enabled.
// Returns the desired presentation time regardless.
@@ -181,6 +182,8 @@ private:
// Can be used for presentation of ImmediateXFB swaps which don't have timing information.
u64 m_next_swap_estimated_ticks = 0;
TimePoint m_next_swap_estimated_time{Clock::now()};
+
+ std::atomic_bool m_immediate_swap_happened_this_field{};
};
} // namespace VideoCommon